Rotate 2D Sprite

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Rotate 2D Sprite

Post by BackupUser »

Code updated for 5.20+. Code broken as StartDrawing() doesn't return DC anymore. RotateSprite() is now built-in in PureBasic.

Restored from previous forum. Originally posted by Mischa.

Hi!

This is just for fun! :wink:

Code: Select all

Procedure RotateSpriteEx(source,target,angle.f,scale) 
  s.f=Sin(6.28318531/3600*angle):c.f=Cos(6.28318531/3600*angle)
  bitmap=CreateCompatibleBitmap_(GetDC_(0),SpriteWidth(source),SpriteHeight(source))
  dc=CreateCompatibleDC_(GetDC_(0))
  obj=SelectObject_(dc,bitmap)
  sid=SpriteOutput(source)
  workdc=StartDrawing(sid)
  BitBlt_(dc,0,0,SpriteWidth(source),SpriteHeight(source),workdc,0,0,13369376)
  transcolor=Point(SpriteWidth(source)-1,0);<-----transparent color upper-right pixel in sourcesprite
  StopDrawing()
  mx=SpriteWidth(source)/2:my=SpriteHeight(source)/2
  radius.f=Sqr(mx*mx + my*my)+1
  
  If scale=0
    If SpriteWidth(target)=0
      CreateSprite(target,SpriteWidth(source),SpriteHeight(source),0)
      TransparentSpriteColor(2, transcolor)
      cl=1
    EndIf
    mx2=mx:my2=my
  Else
    If IsSprite(target)=0
      CreateSprite(target,radius*2,radius*2,0)
      TransparentSpriteColor(2, transcolor)
      cl=1
    EndIf
    mx2=radius:my2=radius:diffmx=mx2-mx:diffmy=my2-my
  EndIf
  
  max=SpriteWidth(target):may=SpriteHeight(target)
  
  If StartDrawing(SpriteOutput(target))
    Box(x, y, max, may,transcolor)
    For y=0 To SpriteHeight(source)-1
      For x=0 To SpriteWidth(source)-1
        RotateX.f = ((x - mx) * c - (y - my) * s) + mx + diffmx
        RotateY.f = ((x - mx) * s + (y - my) * c) + my + diffmy
        If RotateX>=0 And RotateX<max And RotateY>=0 And RotateY<may
          color=GetPixel_(dc,x,y)
          If RotateX>1 And RotateX<SpriteWidth(target)-1 And RotateY>1 And RotateY<SpriteHeight(target)-1
            Plot(RotateX,RotateY,color)
          EndIf
          If angle<>0 And angle<>900 And angle<>1800 And angle<>2700 And angle<>3600
            If RotateX>1 And RotateX<SpriteWidth(target)-1 And RotateY>0 And RotateY<SpriteHeight(target)-1
              Plot(RotateX,RotateY,color);<--This is my very complex
            EndIf
          EndIf
        EndIf
      Next x
    Next y
    StopDrawing()
  EndIf
  DeleteObject_(bitmap):DeleteObject_(obj):DeleteDC_(dc)
EndProcedure



If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or OpenScreen(1024,768,32,"Rotate")=0
  MessageRequester("Error", "Can't open DirectX 7 Or later", 0):End
EndIf

LoadSprite(1, #PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp");<--You should use this first (You can find it in 'PureBasic\Examples\Sources\Data')
TransparentSpriteColor(1, RGB(255,0,255))

Repeat
  ExamineMouse():ExamineKeyboard()
  ClearScreen(RGB(100,50,50))
  DisplayTransparentSprite(1,100,100)
  If count<3650
    If GetTickCount_()-zeit > 10
      
      RotateSpriteEx(1,2,count,1)
      ;RotateSprite(source,target,angle,scale)
      ;source - Number of existing sprite
      ;target - Number of (new)targetsprite
      ;angle  - 0 - 3600 tenth-degree
      ;scale  - 0 = target dimensions are same as source
      ;         1 = target dimension depends on rotation-radius
      
      count+50
      zeit=GetTickCount_()
    EndIf
  EndIf
  DisplayTransparentSprite(2,300+count/20,100+count/20)
  If StartDrawing(ScreenOutput())
    DrawText(10, 500, "Angle= "+Str((count-50)/10)+" Degree")
    StopDrawing()
  EndIf
  FlipBuffers()
  Sleep_(1)
Until KeyboardPushed(#PB_Key_Escape)
End
Have a nice day,
Mischa
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

I found a lot of little bugs which I have fixed.

Code: Select all

Procedure RotateSprite(source,target,angle.f,scale)  
  s.f=Sin(6.28318531/3600*angle):c.f=Cos(6.28318531/3600*angle)
  bitmap=CreateCompatibleBitmap_(GetDC_(0),SpriteWidth(source),SpriteHeight(source))
  dc=CreateCompatibleDC_(GetDC_(0))
  obj=SelectObject_(dc,bitmap)
  sid=SpriteOutput(source)
  workdc=StartDrawing(sid)
    BitBlt_(dc,0,0,SpriteWidth(source),SpriteHeight(source),workdc,0,0,13369376)
    transcolor=Point(SpriteWidth(source)-1,0);<-----transparent color upper-right pixel in sourcesprite 
  StopDrawing()
  mx=SpriteWidth(source)/2:my=SpriteHeight(source)/2
  radius.f=Sqr(mx*mx + my*my)+1
  If scale=0
    If SpriteWidth(target)=0
      CreateSprite(target,SpriteWidth(source),SpriteHeight(source),0)
      TransparentSpriteColor(2,Red(transcolor),Green(transcolor),Blue(transcolor))
      cl=1
    EndIf
    mx2=mx:my2=my
  Else
    If IsSprite(target)=0
      CreateSprite(target,radius*2,radius*2,0)
      TransparentSpriteColor(2,Red(transcolor),Green(transcolor),Blue(transcolor))
      cl=1
    EndIf
    mx2=radius:my2=radius:diffmx=mx2-mx:diffmy=my2-my
  EndIf
  max=SpriteWidth(target):may=SpriteHeight(target)
  sid=SpriteOutput(target)
  workdc=StartDrawing(sid)
    Box(x, y, max, may,transcolor)
    For y=0 To SpriteHeight(source)-1
      For x=0 To SpriteWidth(source)-1
        RotateX.f = ((x - mx) * c - (y - my) * s) + mx + diffmx
        RotateY.f = ((x - mx) * s + (y - my) * c) + my + diffmy
        If RotateX>=0 And RotateX<max And RotateY>=0 And RotateY<may
          color=GetPixel_(dc,x,y)
          If RotateX>1 And RotateX<SpriteWidth(target)-1 And RotateY>1 And RotateY<SpriteHeight(target)-1
             Plot(RotateX,RotateY,color)
          EndIf 
          If angle<>0 And angle<>900 And angle<>1800 And angle<>2700 And angle<>3600
            If RotateX>1 And RotateX<SpriteWidth(target)-1 And RotateY>0 And RotateY<SpriteHeight(target)-1
              Plot(RotateX,RotateY,color);<--This is my very complex
            EndIf 
          EndIf
        EndIf 
      Next x
    Next y
  StopDrawing()
  DeleteObject_(bitmap):DeleteObject_(obj):DeleteDC_(dc)
EndProcedure



If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or OpenScreen(1024,768,32,"Rotate")=0
  MessageRequester("Error", "Can't open DirectX 7 Or later", 0):End
EndIf

LoadSprite(1,"PureBasic\Examples\Sources\Data\GeeBee2.bmp",0);<--You should use this first (You can find it in 'PureBasic\Examples\Sources\Data')
TransparentSpriteColor(1,255,0,255)

Repeat
    ExamineMouse():ExamineKeyboard()
    ClearScreen(100,50,50)
    DisplayTransparentSprite(1,100,100)
    If count<3650
      If GetTickCount_()-zeit > 10
      
        RotateSprite(1,2,count,1)
        ;RotateSprite(source,target,angle,scale)
        ;source - Number of existing sprite
        ;target - Number of (new)targetsprite
        ;angle  - 0 - 3600 tenth-degree
        ;scale  - 0 = target dimensions are same as source
        ;         1 = target dimension depends on rotation-radius
   
        count+50
        zeit=GetTickCount_()
      EndIf
    EndIf
    DisplayTransparentSprite(2,300+count/20,100+count/20)
    StartDrawing(ScreenOutput())
      Locate(10, 500):DrawText("Angle= "+Str((count-50)/10)+" Degree")
    StopDrawing()
    FlipBuffers()
    Sleep_(1)
Until KeyboardPushed(#PB_Key_Escape)
End
Post Reply