Bufferwechsel und Draw-Initialisierung bei Spriterotationen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Wenn die Dateien direkt so reingeladen werden, ist klar, dass DX natürlich
alle Daten mitreißt. Aber ich glaube, ich steige auf das konventionelle Array
mit Bildwerten um, dass erspart Pointerfehlensuchereien :lol:
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ok ich habs

du erzeugst ein sprite mit CreateSprite(#,x,y,mode)
dann definierst du es zur ausgabe mit UseBuffer(#)
dann ermittelst du seine adresse mit *Spr = DrawingBuffer()
und jetzt kannst du mittels PokeW() für 16bit
oder PokeL() für 32bit die farben reinschreiben.
bei 32bit ist das obere byte der alpha-kanal, check nochmal,
ob der 00 oder FF sein muss, damit es nicht transparent wird...

> Wenn die Dateien direkt so reingeladen werden, ist klar, dass DX natürlich alle Daten mitreißt.

sorry, wie meinst du das???
meinst du den header?
in der help steht, dass es für CatchSprite ein bekanntes format sein muss
wäre auszuprobieren, ob er RAW nimmt....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Meine damit, dass dX logischerweise, da von Microschrott, nur Bitmaps samt
Header reinnimmt. Was auf deren Mist gewachsen ist, verwenden die selber
in Sachen Dateien, wie wir Luft atmen. Da ist nach deren Meinung ja sowieso
alles wichtige an Bildmaterial drinne, aber naja...

Danke für die kleine Erklärung, werde gleich mal was zusammenbasteln.
Das gibt nen Credit, falls mein Spiel erscheint :allright: !
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

danke :allright:

freu mich über den credit
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Hallo

@Kekskiller
@S.M. (ist der Name ernstgemeint ... ? ):
Mir gefällt der Name auch nicht wirklich.
Kann man den nachträglich noch ändern ?

Ich habe meinen Code jetzt mal so umgeschrieben, dass er keinen Array als Zwischenspeicher mehr benötigt:

Code: Alles auswählen

#DDLOCK_WAIT=1

Structure DDPIXELFORMAT 
  dwSize.l 
  dwFlags.l 
  dwFourCC.l 
  dwRGBBitCount.l 
  dwRBitMask.l 
  dwGBitMask.l 
  dwBBitMask.l 
  dwRGBAlphaBitMask.l 
EndStructure 



Structure DDCOLORKEY
  dwColorSpaceLowValue.l 
  dwColorSpaceHighValue.l 
EndStructure 

Structure DDSCAPS2 
  dwCaps.l 
  dwCaps2.l 
  dwCaps3.l 
  dwCaps4.l 
EndStructure

Structure DDSURFACEDESC2
  dwSize.l 
  dwFlags.l 
  dwHeight.l 
  dwWidth.l 
  lPitch.l 
  dwBackBufferCount.l 
  dwRefreshRate.l 
  dwAlphaBitDepth.l 
  dwReserved.l 
  lpSurface.l 
  ddckCKDestOverlay.DDCOLORKEY 
  ddckCKDestBlt.DDCOLORKEY 
  ddckCKSrcOverlay.DDCOLORKEY 
  ddckCKSrcBlt.DDCOLORKEY 
  ddpfPixelFormat.DDPIXELFORMAT 
  ddsCaps.DDSCAPS2 
  dwTextureStage.l 
EndStructure 

Structure PB_Sprite
  Sprite.l
  Width.w
  Height.w
  Depth.w
  Mode.w
  FileName.l
  RealWidth.w
  RealHeight.w
  ClipX.w
  ClipY.w
EndStructure

Procedure GetCurrentBuffer()
  !extrn _PB_Sprite_CurrentBitmap
  !MOV Eax,[_PB_Sprite_CurrentBitmap]
  ProcedureReturn
EndProcedure

Procedure GetPixelFormat()
  !extrn _PB_DirectX_PixelFormat
  !MOV Eax,[_PB_DirectX_PixelFormat]
  ProcedureReturn
EndProcedure

Procedure _ScreenWidth()
  !extrn _PB_DirectX_ScreenWidth 
  !MOV Eax,[_PB_DirectX_ScreenWidth]
  ProcedureReturn
EndProcedure

Procedure _ScreenHeight()
  !extrn _PB_DirectX_ScreenHeight
  !MOV Eax,[_PB_DirectX_ScreenHeight]
  ProcedureReturn
EndProcedure







Procedure PutRotatedSprite(Sprite,XPos,YPos,Angle.f)
  
  *Sprite.PB_Sprite=IsSprite(Sprite)
  
  If *Sprite=0:ProcedureReturn 0:EndIf
  
  Angle.f=Angle*0.017453; *(ACos(-1)*2)/360 
  
  Cos=Cos(Angle.f)*2048
  Sin=Sin(Angle.f)*2048
  NSin=-Sin
  
  SpriteWidth=*Sprite\Width-1 
  SpriteHeight=*Sprite\Height-1 
  
  StartX=*Sprite\ClipX
  StartY=*Sprite\ClipY
  EndX=SpriteWidth+StartX
  EndY=SpriteHeight+StartY 
  
  SpriteWidth2=(SpriteWidth)/2+StartX
  SpriteHeight2=(SpriteHeight)/2+StartY
  
  ScreenWidth=_ScreenWidth()-1 
  ScreenHeight=_ScreenHeight()-1 
  
  *SpriteDDS.IDirectDrawSurface7=*Sprite\Sprite
  *DestDDS.IDirectDrawSurface7=GetCurrentBuffer()
  
  SpriteDDSD2.DDSURFACEDESC2
  DestDDSD2.DDSURFACEDESC2
  
  SpriteDDSD2\dwSize=SizeOf(DDSURFACEDESC2)
  DestDDSD2\dwSize=SizeOf(DDSURFACEDESC2)
  
  *SpriteDDS\Lock(0,SpriteDDSD2,#DDLOCK_WAIT,0)
  *DestDDS\Lock(0,DestDDSD2,#DDLOCK_WAIT,0)
  
  SrcPitch=SpriteDDSD2\lPitch
  DestPitch=DestDDSD2\lPitch
  
  SrcAddr=SpriteDDSD2\lpSurface
  DestAddr=DestDDSD2\lpSurface
  
  PixelFormat=GetPixelFormat()
  
  If PixelFormat=#PB_PixelFormat_8Bits 
    
    For y=StartY To EndY
      *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX
      
      Yv1=((y-SpriteHeight2)*NSin)>>11+XPos
      Yv2=((y-SpriteHeight2)*Cos)>>11+YPos
      For x=StartX To EndX  
        
        Xp=((x-SpriteWidth2)*Cos)>>11+Yv1
        Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
        
        If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
          
          PokeW(DestAddr+Yp*DestPitch+Xp,*SrcPtr\l)
        EndIf
        *SrcPtr+1
      Next
    Next    
    
  EndIf
  
  If PixelFormat=#PB_PixelFormat_15Bits Or PixelFormat=#PB_PixelFormat_16Bits
    
    For y=StartY To EndY
      *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*2
      
      Yv1=((y-SpriteHeight2)*NSin)>>11+XPos
      Yv2=((y-SpriteHeight2)*Cos)>>11+YPos
      For x=StartX To EndX  
        
        Xp=((x-SpriteWidth2)*Cos)>>11+Yv1
        Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
        
        If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
          
          PokeL(DestAddr+Yp*DestPitch+Xp*2,*SrcPtr\l)
        EndIf
        *SrcPtr+2
      Next
    Next    
  EndIf
  
  
  If PixelFormat=#PB_PixelFormat_24Bits_RGB Or PixelFormat=#PB_PixelFormat_24Bits_BGR
    
    For y=StartY To EndY
      *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*3
      
      Yv1=((y-SpriteHeight2)*NSin)>>11+XPos
      Yv2=((y-SpriteHeight2)*Cos)>>11+YPos
      For x=StartX To EndX  
        
        Xp=((x-SpriteWidth2)*Cos)>>11+Yv1
        Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
        
        If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
          
          Color=*SrcPtr\l
          Addr=DestAddr+Yp*DestPitch+Xp*3
          PokeW(Addr,Color)
          PokeL(Addr+2,Color>>16|Color<<8)
          
        EndIf
        *SrcPtr+3
      Next
    Next    
  EndIf
  
  If PixelFormat=#PB_PixelFormat_32Bits_RGB Or PixelFormat=#PB_PixelFormat_32Bits_BGR
    
    For y=StartY To EndY
      *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*4
      
      Yv1=((y-SpriteHeight2)*NSin)>>11+XPos
      Yv2=((y-SpriteHeight2)*Cos)>>11+YPos
      For x=StartX To EndX  
        
        Xp=((x-SpriteWidth2)*Cos)>>11+Yv1
        Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
        
        If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
          
          Color=*SrcPtr\l
          Addr=DestAddr+Yp*DestPitch+Xp*4
          PokeL(Addr,Color)
          PokeL(Addr+4,Color)
          
        EndIf
        *SrcPtr+4
      Next
    Next    
    
  EndIf
  
  *SpriteDDS\UnLock(0)
  *DestDDS\UnLock(0)
  ProcedureReturn -1
EndProcedure


InitSprite() 
InitKeyboard()

OpenScreen(800,600,16,"PutRotatedSprite()") 

LoadSprite(1,"D:\Purebasic\examples\sources\data\Geebee2.bmp",#PB_Sprite_Memory);Pfad anpassen 


ClipSprite(1,10,10,50,50)


Repeat
  ExamineKeyboard()
  Angle+1
  
  ClearScreen(0,0,0)
  
  PutRotatedSprite(1,300,300,Angle) 
  
  FlipBuffers()
  
Until KeyboardPushed(#PB_Key_Escape)
Der Code unterstützt jetzt sogar Clipping und benötigt keine externe Libraries mehr. :D


@Kaeru Gaman
du erzeugst ein sprite mit CreateSprite(#,x,y,mode)
dann definierst du es zur ausgabe mit UseBuffer(#)
dann ermittelst du seine adresse mit *Spr = DrawingBuffer()
Anstelle von UseBuffer(Sprite) musst du StartDrawing(SpriteOutput(Sprite)) benutzen.

Code: Alles auswählen

CreateSprite(Sprite,Width,Height,Mode)
StartDrawing(SpriteOutput(Sprite))
Addr=DrawingBuffer()
StopDrawing()
bei 32bit ist das obere byte der alpha-kanal, check nochmal,
ob der 00 oder FF sein muss, damit es nicht transparent wird...
Im 32-Bit Screenmodus ist das oberste Byte reserviert, und damit kein alpha-kanal.

Gruß
Stefan
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

S.M. hat geschrieben:Im 32-Bit Screenmodus ist das oberste Byte reserviert, und damit kein alpha-kanal.
beim screen ist es reserviert, weil es bei den sprites der alpha-kanal ist.
wenn natürlich '0' undurchsichtig ist, merkst du das garnicht...
S.M. hat geschrieben:Mir gefällt der Name auch nicht wirklich.
Kann man den nachträglich noch ändern ?
schick mal ne PN an Rob, den admin, gehen tuts...

[edit]
PS: ein bisschen dokumentation zu deiner proc wär ja schon ganz nett,
damit man besser dahintersteigt, was du wann warum machst...
Zuletzt geändert von Kaeru Gaman am 10.12.2004 18:08, insgesamt 1-mal geändert.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

@S.M.:
Sehr schön gelöst, vielen Dank! Das funktioniert formidabel hurtig, glaube,
das nehme ich gleich mit rein :wink: . Ich könnte mir ja im Gegenzug einen
neuen Namen für dich ausdenken :mrgreen: .

@Kaera Gaman:
Du bekommst natürlich auch deinen Eintrag, schließlich will ich ja auch
weiterhin an Effekten damit rumprobieren. Ach ich packe euch liebenswürdige
Menschen beide rein, mann bin ich jetzt happy :allright: !
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

Hallo

Ich habe meinen Code noch etwas verbessert und die Funktion PutRotatedTransSprite() hinzugefügt.
Leider ist der Code jetzt noch unübersichtlicher.

Hier der Code:

Code: Alles auswählen

#DDLOCK_WAIT=1 
#DDCKEY_SRCBLT=8
Structure DDPIXELFORMAT 
  dwSize.l 
  dwFlags.l 
  dwFourCC.l 
  dwRGBBitCount.l 
  dwRBitMask.l 
  dwGBitMask.l 
  dwBBitMask.l 
  dwRGBAlphaBitMask.l 
EndStructure 

Structure DDCOLORKEY 
  dwColorSpaceLowValue.l 
  dwColorSpaceHighValue.l 
EndStructure 

Structure DDSCAPS2 
  dwCaps.l 
  dwCaps2.l 
  dwCaps3.l 
  dwCaps4.l 
EndStructure 

Structure DDSURFACEDESC2 
  dwSize.l 
  dwFlags.l 
  dwHeight.l 
  dwWidth.l 
  lPitch.l 
  dwBackBufferCount.l 
  dwRefreshRate.l 
  dwAlphaBitDepth.l 
  dwReserved.l 
  lpSurface.l 
  ddckCKDestOverlay.DDCOLORKEY 
  ddckCKDestBlt.DDCOLORKEY 
  ddckCKSrcOverlay.DDCOLORKEY 
  ddckCKSrcBlt.DDCOLORKEY 
  ddpfPixelFormat.DDPIXELFORMAT 
  ddsCaps.DDSCAPS2 
  dwTextureStage.l 
EndStructure 

Structure PB_Sprite 
  Sprite.l 
  Width.w 
  Height.w 
  Depth.w 
  Mode.w 
  FileName.l 
  RealWidth.w 
  RealHeight.w 
  ClipX.w 
  ClipY.w 
EndStructure 

Procedure GetCurrentBuffer() ;gibt die DDrawSurface des Rendering-Buffers zurück. 
  !extrn _PB_Sprite_CurrentBitmap 
  !MOV Eax,[_PB_Sprite_CurrentBitmap] 
  ProcedureReturn 
EndProcedure 

Procedure GetPixelFormat() ;gibt das PixelFormat des Rendering-Buffers zurück
  !extrn _PB_DirectX_PixelFormat 
  !MOV Eax,[_PB_DirectX_PixelFormat] 
  ProcedureReturn 
EndProcedure 

Procedure _ScreenWidth() ;gibt die Breite des Rendering-Buffers zurück
  !extrn _PB_DirectX_ScreenWidth 
  !MOV Eax,[_PB_DirectX_ScreenWidth] 
  ProcedureReturn 
EndProcedure 

Procedure _ScreenHeight() ;gibt die Höhe des Rendering-Buffers zurück
  !extrn _PB_DirectX_ScreenHeight 
  !MOV Eax,[_PB_DirectX_ScreenHeight] 
  ProcedureReturn 
EndProcedure 









Procedure PutRotatedSprite(Sprite,XPos,YPos,Angle.f) 
  
  *Sprite.PB_Sprite=IsSprite(Sprite) 
  
  If *Sprite=0:ProcedureReturn 0:EndIf 
  
  Angle.f=Angle*0.017453; *(ACos(-1)*2)/360 
  
  Cos=Cos(Angle.f)*2048 
  Sin=Sin(Angle.f)*2048 
  NSin=-Sin 
  
  SpriteWidth=*Sprite\Width-1 
  SpriteHeight=*Sprite\Height-1 
  
  StartX=*Sprite\ClipX 
  StartY=*Sprite\ClipY 
  EndX=SpriteWidth+StartX 
  EndY=SpriteHeight+StartY 
  
  SpriteWidth2=(SpriteWidth)/2+StartX 
  SpriteHeight2=(SpriteHeight)/2+StartY 
  
  ScreenWidth=_ScreenWidth()-1 
  ScreenHeight=_ScreenHeight()-1 
  
  *SpriteDDS.IDirectDrawSurface7=*Sprite\Sprite 
  *DestDDS.IDirectDrawSurface7=GetCurrentBuffer() 
  
  SpriteDDSD2.DDSURFACEDESC2 
  DestDDSD2.DDSURFACEDESC2 
  
  SpriteDDSD2\dwSize=SizeOf(DDSURFACEDESC2) 
  DestDDSD2\dwSize=SizeOf(DDSURFACEDESC2) 
  
  *SpriteDDS\Lock(0,SpriteDDSD2,#DDLOCK_WAIT,0);schließt den Sprite- 
  *DestDDS\Lock(0,DestDDSD2,#DDLOCK_WAIT,0);und Rendering-Buffer, damit man direkt auf den Speicher zugreifen kann.
  
  
  SrcPitch=SpriteDDSD2\lPitch 
  DestPitch=DestDDSD2\lPitch 
  
  SrcAddr=SpriteDDSD2\lpSurface 
  DestAddr=DestDDSD2\lpSurface 
  
  PixelFormat=GetPixelFormat() 
  
  x=Sqr(Pow((*Sprite\Width+1)/2,2)+Pow((*Sprite\Height+1)/2,2))
  
  If XPos-x>=0 And YPos-x>=0 And XPos+x<=ScreenWidth And YPos+x<=ScreenHeight ;Kann das Bild komplett dargestellt werden ?
    
    ;======================================================================  
    If PixelFormat=#PB_PixelFormat_8Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX        
          Color=*SrcPtr\l&$FF
          PokeW(DestAddr+((((x-SpriteWidth2)*Sin)>>11+Yv2))*DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1),Color+Color<<8) ;Zeichnet den Pixel
          *SrcPtr+1 
        Next 
      Next    
      
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_15Bits Or PixelFormat=#PB_PixelFormat_16Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*2 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l&$FFFF
          PokeL(DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2)*DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*2,Color+Color<<16) ;Zeichnet den Pixel
          *SrcPtr+2 
        Next 
      Next    
    EndIf 
    
    
    If PixelFormat=#PB_PixelFormat_24Bits_RGB Or PixelFormat=#PB_PixelFormat_24Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*3 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l 
          Addr=DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2) *DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*3 ;Zeichnet den Pixel
          PokeW(Addr,Color) 
          PokeL(Addr+2,Color>>16|Color<<8) 
          
          *SrcPtr+3 
        Next 
      Next    
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_32Bits_RGB Or PixelFormat=#PB_PixelFormat_32Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*4 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l 
          Addr=DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2) *DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*4 ;Zeichnet den Pixel
          PokeL(Addr,Color) 
          PokeL(Addr+4,Color) 
          
          *SrcPtr+4 
        Next 
      Next    
      
    EndIf 
    ;====================================================================== 
    
    
  Else
    
    
    ;======================================================================   
    If PixelFormat=#PB_PixelFormat_8Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FF
            PokeW(DestAddr+Yp*DestPitch+Xp,Color+Color<<8) ;Zeichnet den Pixel
          EndIf 
          *SrcPtr+1 
        Next 
      Next    
      
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_15Bits Or PixelFormat=#PB_PixelFormat_16Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*2 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FFFF
            PokeL(DestAddr+Yp*DestPitch+Xp*2,Color+Color<<16) ;Zeichnet den Pixel
          EndIf 
          *SrcPtr+2 
        Next 
      Next    
    EndIf 
    
    
    If PixelFormat=#PB_PixelFormat_24Bits_RGB Or PixelFormat=#PB_PixelFormat_24Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*3 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l 
            Addr=DestAddr+Yp*DestPitch+Xp*3 ;Zeichnet den Pixel
            PokeW(Addr,Color) 
            PokeL(Addr+2,Color>>16|Color<<8) 
            
          EndIf 
          *SrcPtr+3 
        Next 
      Next    
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_32Bits_RGB Or PixelFormat=#PB_PixelFormat_32Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*4 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l 
            Addr=DestAddr+Yp*DestPitch+Xp*4 ;Zeichnet den Pixel
            PokeL(Addr,Color) 
            PokeL(Addr+4,Color) 
            
          EndIf 
          *SrcPtr+4 
        Next 
      Next       
    EndIf 
    ;======================================================================   
    
  EndIf
  
  *SpriteDDS\UnLock(0) ;Öffnet den Sprite-Buffer und den Rendering-Buffer wieder.
  *DestDDS\UnLock(0) 
  ProcedureReturn -1 
EndProcedure 




Procedure PutRotatedTransSprite(Sprite,XPos,YPos,Angle.f) 
  
  *Sprite.PB_Sprite=IsSprite(Sprite) 
  
  If *Sprite=0:ProcedureReturn 0:EndIf 
  
  Angle.f=Angle*0.017453; *(ACos(-1)*2)/360 
  
  Cos=Cos(Angle.f)*2048 
  Sin=Sin(Angle.f)*2048 
  NSin=-Sin 
  
  SpriteWidth=*Sprite\Width-1 
  SpriteHeight=*Sprite\Height-1 
  
  StartX=*Sprite\ClipX 
  StartY=*Sprite\ClipY 
  EndX=SpriteWidth+StartX 
  EndY=SpriteHeight+StartY 
  
  SpriteWidth2=(SpriteWidth)/2+StartX 
  SpriteHeight2=(SpriteHeight)/2+StartY 
  
  ScreenWidth=_ScreenWidth()-1 
  ScreenHeight=_ScreenHeight()-1 
  
  *SpriteDDS.IDirectDrawSurface7=*Sprite\Sprite 
  *DestDDS.IDirectDrawSurface7=GetCurrentBuffer() 
  
  *SpriteDDS\GetColorKey(#DDCKEY_SRCBLT,ColorKey.DDCOLORKEY);Gibt die transparente Farbe (im passendem PixelFormat) des Sprites zurück
  TransColor=ColorKey\dwColorSpaceLowValue
  
  
  SpriteDDSD2.DDSURFACEDESC2 
  DestDDSD2.DDSURFACEDESC2 
  
  SpriteDDSD2\dwSize=SizeOf(DDSURFACEDESC2) 
  DestDDSD2\dwSize=SizeOf(DDSURFACEDESC2) 
  
  *SpriteDDS\Lock(0,SpriteDDSD2,#DDLOCK_WAIT,0);schließt den Sprite- 
  *DestDDS\Lock(0,DestDDSD2,#DDLOCK_WAIT,0);und Rendering-Buffer, damit man direkt auf den Speicher zugreifen kann.
  
  
  SrcPitch=SpriteDDSD2\lPitch 
  DestPitch=DestDDSD2\lPitch 
  
  SrcAddr=SpriteDDSD2\lpSurface 
  DestAddr=DestDDSD2\lpSurface 
  
  PixelFormat=GetPixelFormat() 
  
  
  x=Sqr(Pow((*Sprite\Width+1)/2,2)+Pow((*Sprite\Height+1)/2,2))
  
  If XPos-x>=0 And YPos-x>=0 And XPos+x<=ScreenWidth And YPos+x<=ScreenHeight ;Kann das Bild komplett dargestellt werden ?
    
    ;======================================================================   
    
    If PixelFormat=#PB_PixelFormat_8Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l&$FF
          If Color<>TransColor
            PokeW(DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2)*DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1),Color+Color<<8) ;Zeichnet den Pixel
          EndIf
          
          *SrcPtr+1 
        Next 
      Next    
      
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_15Bits Or PixelFormat=#PB_PixelFormat_16Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*2 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l&$FFFF
          If Color<>TransColor
            PokeL(DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2)*DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*2,Color+Color<<16) ;Zeichnet den Pixel
          EndIf
          
          *SrcPtr+2 
        Next 
      Next    
    EndIf 
    
    
    If PixelFormat=#PB_PixelFormat_24Bits_RGB Or PixelFormat=#PB_PixelFormat_24Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*3 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l&$FFFFFF 
          
          If Color<>TransColor
            Addr=DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2) *DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*3 ;Zeichnet den Pixel
            PokeW(Addr,Color) 
            PokeL(Addr+2,Color>>16|Color<<8) 
          EndIf
          
          *SrcPtr+3 
        Next 
      Next    
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_32Bits_RGB Or PixelFormat=#PB_PixelFormat_32Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*4 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Color=*SrcPtr\l&$FFFFFF
          If Color<>TransColor
            Addr=DestAddr+(((x-SpriteWidth2)*Sin)>>11+Yv2)*DestPitch+(((x-SpriteWidth2)*Cos)>>11+Yv1)*4 ;Zeichnet den Pixel
            PokeL(Addr,Color) 
            PokeL(Addr+4,Color) 
          EndIf
          
          *SrcPtr+4 
        Next 
      Next    
      
    EndIf 
    ;======================================================================   
    
    
    
  Else
    
    ;======================================================================   
    
    If PixelFormat=#PB_PixelFormat_8Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FF
            If Color<>TransColor
              PokeW(DestAddr+Yp*DestPitch+Xp,Color+Color<<8) ;Zeichnet den Pixel
            EndIf
            
          EndIf 
          *SrcPtr+1 
        Next 
      Next    
      
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_15Bits Or PixelFormat=#PB_PixelFormat_16Bits 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*2 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FFFF
            If Color<>TransColor
              PokeL(DestAddr+Yp*DestPitch+Xp*2,Color+Color<<16) ;Zeichnet den Pixel
            EndIf
            
          EndIf 
          *SrcPtr+2 
        Next 
      Next    
    EndIf 
    
    
    If PixelFormat=#PB_PixelFormat_24Bits_RGB Or PixelFormat=#PB_PixelFormat_24Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*3 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FFFFFF
            
            If Color<>TransColor
              Addr=DestAddr+Yp*DestPitch+Xp*3 ;Zeichnet den Pixel
              PokeW(Addr,Color) 
              PokeL(Addr+2,Color>>16|Color<<8) 
            EndIf
            
          EndIf 
          *SrcPtr+3 
        Next 
      Next    
    EndIf 
    
    If PixelFormat=#PB_PixelFormat_32Bits_RGB Or PixelFormat=#PB_PixelFormat_32Bits_BGR 
      
      For y=StartY To EndY 
        *SrcPtr.Long=SrcAddr+y*SrcPitch+StartX*4 ;Berechnet die Startadresse
        
        Yv1=((y-SpriteHeight2)*NSin)>>11+XPos 
        Yv2=((y-SpriteHeight2)*Cos)>>11+YPos 
        For x=StartX To EndX  
          
          Xp=((x-SpriteWidth2)*Cos)>>11+Yv1 ;Berechnet die Position des Pixels
          Yp=((x-SpriteWidth2)*Sin)>>11+Yv2 
          
          If Xp>=0 And Xp<ScreenWidth And Yp>=0 And Yp<=ScreenHeight 
            
            Color=*SrcPtr\l&$FFFFFF
            If Color<>TransColor
              Addr=DestAddr+Yp*DestPitch+Xp*4 ;Zeichnet den Pixel
              PokeL(Addr,Color) 
              PokeL(Addr+4,Color) 
            EndIf
            
          EndIf 
          *SrcPtr+4 
        Next 
      Next    
      
    EndIf 
    ;======================================================================     
    
    
  EndIf
  
  *SpriteDDS\UnLock(0) ;Öffnet den Sprite-Buffer und den Rendering-Buffer wieder.
  *DestDDS\UnLock(0) 
  ProcedureReturn -1 
EndProcedure 




;Beispiel:
InitSprite() 
InitKeyboard() 
InitMouse()

OpenScreen(800,600,16,"PutRotatedSprite()/PutRotatedTransSprite()") 


;Achtung:
;Das Sprite sollte im Hauptspeicher erstellt werden, da dort der direkte Speicherzugriff schneller ist. 
LoadSprite(1,"D:\Purebasic\examples\sources\data\Geebee2.bmp",#PB_Sprite_Memory);Pfad anpassen !


;ClipSprite(1,20,20,100,100)
TransparentSpriteColor(1,255,0,255)

MouseLocate(400,300)

Repeat 
  ExamineKeyboard() 
  Angle+1 
  
  ClearScreen(128,128,128) 
  
  ExamineMouse()
  
  PutRotatedTransSprite(1,MouseX(),MouseY(),Angle)

  FlipBuffers() 
  
Until KeyboardPushed(#PB_Key_Escape) 
Gruß
Stefan
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Ist echt cool ... schade das man ASM nicht von heute auf morgne lernen kann :lol: ... sonnst würd ich versuchen das zu optimieren -_-

Das was du gecodet hast ist nämlich trotzallem nicht für welche, denen es auf die geschwindigkeit ankommt. Denn hier ist die Sprite3D() Lib viel um einiges schneller ... eigentlich schade :D

Ab schnell was geschrieben, was das ganze austestet :wink: ... einfach über oder unter das Beispiel Kopieren und austesten <)

Code: Alles auswählen

;Geschwindigkeitstest 
#AnzDreh = 5 ; Anzahl der drehungen um die eigene Axe
#ScreenWidth = 1024 ;Auflösung des TestScreens
#ScreenHeight = 768
#ScreenDepth = 32

InitSprite() 
InitSprite3D()
InitKeyboard() 
InitMouse() 

OpenScreen(#ScreenWidth, #ScreenHeight, #ScreenDepth,"PutRotatedSprite()/PutRotatedTransSprite()") 

;Achtung: 
;Das Sprite sollte im Hauptspeicher erstellt werden, da dort der direkte Speicherzugriff schneller ist. 
SpritePfad.s = "E:\Purebasic\examples\sources\data\Geebee2.bmp" ;Pfad anpassen ! 
LoadSprite(1, SpritePfad, #PB_Sprite_Memory)
LoadSprite(0, SpritePfad, #PB_Sprite_Texture)

TransparentSpriteColor(1,255,0,255) 
TransparentSpriteColor(0,255,0,255) 

CreateSprite3D(1, 0)

Timer = ElapsedMilliseconds()
For angle = 0 To 360 * #AnzDreh
  ClearScreen(0, 0, 0) 
  PutRotatedTransSprite(1, 300, 300, angle)
  FlipBuffers(0) 
Next
Time1 = ElapsedMilliseconds() - Timer

Timer = ElapsedMilliseconds()
For angle = 0 To 360 * #AnzDreh
  ClearScreen(0, 0, 0)
  Start3D()
    RotateSprite3D(1, angle, 0)
    DisplaySprite3D(1, 300, 300)
  Stop3D()
  FlipBuffers(0)
Next
Time2 = ElapsedMilliseconds() - Timer

CloseScreen()
Ergebnis.s = "Auflösung: Width: "+Str(#ScreenWidth)+" Height: "+Str(#ScreenHeight)+" Depth: "+Str(#ScreenDepth)+Chr(13)+Chr(10)+Chr(13)+Chr(10)
Ergebnis   + "PutRotateTransSprite(): "+Str(Time1)+" ms"+Chr(13)+Chr(10)+"RotateSprite3D(): "+Str(Time2)+" ms"+Chr(13)+Chr(10)
If Time1 > Time2
  Ergebnis + "RotateSprite3D() ist "+StrF(Time1/Time2, 2)+" mal schneller als PutRotateTransSprite()"
Else
  Ergebnis + "PutRotateTransSprite() ist "+StrF(Time2/Time1, 2)+" mal schneller als RotateSprite3D()"
EndIf  

MessageRequester("Ergebnis bei "+Str(#AnzDreh)+" Drehungen von 360°", Ergebnis)
Ergebnis war bei mir das Sprite3D ca. 4 mal schneller ist ... schade
Aber vielleicht kann das ja wer Optimieren <) ... bis ich die zeit find für ASM dauert leider noch ne weile :cry:

MFG PMV

Edit: Im Code DisplaySprite3D() und Stop3D() hinzugefügt
Zuletzt geändert von PMV am 11.12.2004 22:23, insgesamt 2-mal geändert.
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Stefan
Beiträge: 125
Registriert: 29.08.2004 10:51
Kontaktdaten:

Beitrag von Stefan »

@PMV
Dein Speedtest ist so nicht richtig.
1.)
In einem Speedtest solltest du Befehle, die nicht benötigt werden weglassen.
2.)
Du hast DisplaySprite3D() vergessen.

Code: Alles auswählen

;Debugger Deaktivieren !!!

;Geschwindigkeitstest 
#AnzDreh = 5 ; Anzahl der drehungen um die eigene Axe 
#ScreenWidth = 1024 ;Auflösung des TestScreens 
#ScreenHeight = 768 
#ScreenDepth = 32 

InitSprite() 
InitSprite3D() 
InitKeyboard() 
InitMouse() 

OpenScreen(#ScreenWidth, #ScreenHeight, #ScreenDepth,"PutRotatedSprite()/PutRotatedTransSprite()") 

;Achtung: 
;Das Sprite sollte im Hauptspeicher erstellt werden, da dort der direkte Speicherzugriff schneller ist. 
SpritePfad.s = "D:\Purebasic\examples\sources\data\Geebee2.bmp" ;Pfad anpassen ! 
LoadSprite(1, SpritePfad, #PB_Sprite_Memory) 
LoadSprite(0, SpritePfad, #PB_Sprite_Texture) 

TransparentSpriteColor(1,255,0,255) 
TransparentSpriteColor(0,255,0,255) 

CreateSprite3D(1, 0) 

Timer = ElapsedMilliseconds() 
For angle = 0 To 360 * #AnzDreh 
  ;ClearScreen(0, 0, 0) 
  PutRotatedTransSprite(1, 300, 300, angle) 
  ;FlipBuffers(0) 
Next 
Time1 = ElapsedMilliseconds() - Timer 

Timer = ElapsedMilliseconds() 
For angle = 0 To 360 * #AnzDreh 
  ;ClearScreen(0, 0, 0) 
  Start3D() 
  RotateSprite3D(1, angle, 0) 
  DisplaySprite3D(1,300,300)
  Stop3D()  
  ;FlipBuffers(0) 
Next 
Time2 = ElapsedMilliseconds() - Timer 


CloseScreen() 
Ergebnis.s = "Auflösung: Width: "+Str(#ScreenWidth)+" Height: "+Str(#ScreenHeight)+" Depth: "+Str(#ScreenDepth)+Chr(13)+Chr(10)+Chr(13)+Chr(10) 
Ergebnis   + "PutRotateTransSprite(): "+Str(Time1)+" ms"+Chr(13)+Chr(10)+"RotateSprite3D(): "+Str(Time2)+" ms"+Chr(13)+Chr(10) 
If Time1 > Time2 
  Ergebnis + "RotateSprite3D() ist "+StrF(Time1/Time2, 2)+" mal so schnell wie PutRotatedTransSprite()" 
Else 
  Ergebnis + "PutRotatedTransSprite() ist "+StrF(Time2/Time1, 2)+" mal so schnell wie RotateSprite3D()" 
EndIf  

MessageRequester("Ergebnis bei "+Str(#AnzDreh)+" Drehungen von 360°", Ergebnis)
Meine Ergebnisse:
Rechner 1 (AMD Duron 1000 MHz + GeForce 4 MX 440):
RotateSprite3D() ist 9.05 mal so schnell wie PutRotatedTransSprite()

Rechner 2 (Intel Celeron 2400 MHz + Intel(R) 82845G Graphics Controller):
RotateSprite3D() ist 2.57 mal so schnell wie PutRotatedTransSprite()

Gruß
Stefan
Antworten