Sprite Scrolling

Share your advanced PureBasic knowledge/code with the community.
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Sprite Scrolling

Post by Fig »

Procedure to scroll a sprite any direction and any speed you want.
Works with transformed, rotated sprites. Should be apply before zoomsprite though.
[Escape] to quit.

Do not consider code below, See last code posts.

Code: Select all

If InitSprite() = 0 Or InitKeyboard() = 0:MessageRequester("Error", "Can't open the sprite system", 0):End:EndIf
If OpenWindow(0, 0, 0,800,600, "Scroll Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf    
LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")

Procedure Scroll(sprite.i,StepX.i,StepY.i)
   If StartDrawing(SpriteOutput(sprite))
      Buffer.i= DrawingBuffer()
      Pitch.i= DrawingBufferPitch()
      If StepX>0
         StepX<<2
         *Dest=AllocateMemory(StepX)
         For y = 0 To SpriteHeight(sprite)-1
            *debut = Buffer+Pitch*y
            CopyMemory(*debut,*Dest,StepX)
            CopyMemory(*debut+StepX,*debut,pitch-StepX)
            CopyMemory(*Dest,*debut+Pitch-StepX,StepX)
         Next y
         FreeMemory(*dest)
      ElseIf StepX<0
         StepX=Abs(StepX)
         StepX<<2
         *Dest=AllocateMemory(StepX)
         For y = 0 To SpriteHeight(sprite)-1
            *debut = Buffer+Pitch*y
            CopyMemory(*debut+pitch-StepX,*Dest,StepX)
            CopyMemory(*debut,*debut+StepX,pitch-StepX)
            CopyMemory(*Dest,*debut,StepX)
         Next y
         FreeMemory(*dest)
      EndIf
      If StepY>0
         *Dest=AllocateMemory(pitch*StepY)
         *debut = Buffer
         CopyMemory(*debut,*Dest,pitch*StepY)
         CopyMemory(*debut+pitch*StepY,*debut,pitch*(SpriteHeight(sprite)-StepY))
         CopyMemory(*Dest,*debut+pitch*(SpriteHeight(sprite)-StepY),pitch*StepY)
         FreeMemory(*dest)
      ElseIf StepY<0
         StepY=Abs(StepY)
         *debut = Buffer
         *Dest=AllocateMemory(pitch*StepY)
         CopyMemory(*debut+pitch*(SpriteHeight(sprite)-StepY),*Dest,pitch*StepY)
         CopyMemory(*debut,*debut+pitch*StepY,pitch*(SpriteHeight(sprite)-StepY))
         CopyMemory(*Dest,*debut,pitch*StepY)
         FreeMemory(*dest)
      EndIf 
      StopDrawing()
   EndIf
EndProcedure

Repeat
   WindowEvent()
   ExamineKeyboard()
   FlipBuffers()
   ClearScreen(#Black)
   ;RotateSprite(0,0.1,#PB_Relative)
   If time.d<ElapsedMilliseconds():stepx=Random(4)-2:stepy=Random(4)-2:time=ElapsedMilliseconds()+3000:EndIf
   Scroll(0,stepx,stepy)
   DisplaySprite(0,ScreenWidth()/2-SpriteWidth(sprite)/2,ScreenHeight()/2)
Until KeyboardPushed(#PB_Key_Escape)
Last edited by Fig on Sat Jul 08, 2017 9:53 am, edited 4 times in total.
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Sprite Scrolling

Post by RSBasic »

Nice Image
Image
Image
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Sprite Scrolling

Post by wilbert »

On MacOS it doesn't work.
Moving the StopDrawing() to the end of the procedure makes it scroll.
Apparently on MacOS you can't use the pointer returned by DrawingBuffer() anymore after calling StopDrawing() .
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: Sprite Scrolling

Post by Fig »

I changed the procedure, thank your for your feedbacks. :D
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Sprite Scrolling

Post by Demivec »

Thanks for the scrolling code and example. It works well.

Here's a shorter version of the Scroll procedure with a few other things thrown in:

Code: Select all

Procedure Scroll(sprite.i, StepX.i, StepY.i)
  Protected SpriteW, SpriteH, y, Buffer, Pitch, *Dest, *debut
  
  If StartDrawing(SpriteOutput(sprite))
    SpriteW = OutputWidth(): SpriteH = OutputHeight()
    StepX = (StepX + SpriteW) % SpriteW
    StepY = (StepY + SpriteH) % SpriteH
    
    If StepX = 0 And StepY = 0: StopDrawing(): ProcedureReturn: EndIf
    
    Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    If StepX <> 0
      StepX << 2 ;assumes 32 bit format for sprite colors
      *Dest = AllocateMemory(StepX)
      For y = 0 To SpriteH - 1
        *debut = Buffer + Pitch * y
        CopyMemory(*debut, *Dest, StepX)
        CopyMemory(*debut + StepX, *debut, Pitch - StepX)
        CopyMemory(*Dest, *debut + Pitch - StepX, StepX)
      Next y
      FreeMemory(*dest)
    EndIf
    
    If StepY <> 0
      If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY
        StepY = SpriteH - StepY ;reverse the Y value
      EndIf
      *Dest = AllocateMemory(Pitch * StepY)
      *debut = Buffer
      CopyMemory(*debut, *Dest, Pitch * StepY)
      CopyMemory(*debut + Pitch * StepY, *debut, Pitch * (SpriteH - StepY))
      CopyMemory(*Dest, *debut + Pitch * (SpriteH - StepY), Pitch * StepY)
      FreeMemory(*Dest)
    EndIf  
    StopDrawing()    
  EndIf
EndProcedure
This version puts in a safety check for scrolling more than the sprite's width or height, eliminates the need for separate code for negative or positive scroll values and avoids doing any unnecessary scrolling if a scroll value is zero. It also checks the drawing buffer pixel format to see if it in 'Reverse Y' format and adjusts the Step Y value if needed to account for this. This version also allows using ZoomSprite() and RotateSprite() before it is called.

This version should be safer and keeps many errors in check, handles zoom and seems to be, according to my simple speed tests about the same speed as the routine that you posted, Fig. :)

Here's the procedure included with your test code:

Code: Select all

Procedure Scroll(sprite.i, StepX.i, StepY.i)
  Protected SpriteW, SpriteH, y, Buffer, Pitch, *Dest, *debut
  
  If StartDrawing(SpriteOutput(sprite))
    SpriteW = OutputWidth(): SpriteH = OutputHeight()
    StepX = (StepX + SpriteW) % SpriteW
    StepY = (StepY + SpriteH) % SpriteH
    If StepX = 0 And StepY = 0: StopDrawing(): ProcedureReturn: EndIf
    Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    If StepX <> 0
      StepX << 2 ;assumes 32 bit format for sprite colors
      *Dest = AllocateMemory(StepX)
      For y = 0 To SpriteH - 1
        *debut = Buffer + Pitch * y
        CopyMemory(*debut, *Dest, StepX)
        CopyMemory(*debut + StepX, *debut, Pitch - StepX)
        CopyMemory(*Dest, *debut + Pitch - StepX, StepX)
      Next y
      FreeMemory(*dest)
    EndIf
    If StepY <> 0
      If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY
        StepY = SpriteH - StepY ;reverse the Y value
      EndIf
      *Dest = AllocateMemory(Pitch * StepY)
      *debut = Buffer
      CopyMemory(*debut, *Dest, Pitch * StepY)
      CopyMemory(*debut + Pitch * StepY, *debut, Pitch * (SpriteH - StepY))
      CopyMemory(*Dest, *debut + Pitch * (SpriteH - StepY), Pitch * StepY)
      FreeMemory(*Dest)
    EndIf  
    StopDrawing()    
  EndIf
EndProcedure


CompilerIf  #PB_Compiler_IsMainFile
  If InitSprite() = 0 Or InitKeyboard() = 0: MessageRequester("Error", "Can't open the sprite system", 0): End: EndIf
  If OpenWindow(0, 0, 0, 800, 600, "Scroll Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf
  If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf    
  ;}
  
  LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
  Define sw = SpriteWidth(0), sh = SpriteHeight(0) ;save original sprite size values for random selection later
  Define time.d, stepx, stepy
  
  Repeat
    WindowEvent()
    ExamineKeyboard()
    FlipBuffers()
    ClearScreen(#Black)
    
    RotateSprite(0, 0.1, #PB_Relative)
    If time.d < ElapsedMilliseconds()
     ZoomSprite(0, Random(sw * 3, 2), Random(sh * 3, 2))
     stepx = Random(4) - 2: stepy = Random(4) - 2: time = ElapsedMilliseconds() + 3000
   EndIf

    Scroll(0, stepx, stepy)
    DisplaySprite(0, ScreenWidth() / 2 - SpriteWidth(sprite) / 2,ScreenHeight() / 2)
    
  Until KeyboardPushed(#PB_Key_Escape)
CompilerEndIf
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: Sprite Scrolling

Post by Fig »

Foxy !
Then, let's make it totaly bulletproof by adding different pixelformat support.
I hope Fred may consider making this native to pb...

Code: Select all

Procedure Scroll(sprite.i, StepX.i, StepY.i)
  Protected SpriteW, SpriteH, y, Buffer, Pitch, PixelFormat, *Dest, *debut
  If StartDrawing(SpriteOutput(sprite))
    SpriteW = OutputWidth(): SpriteH = OutputHeight()
    StepX = (StepX + SpriteW) % SpriteW
    StepY = (StepY + SpriteH) % SpriteH
    If StepX = 0 And StepY = 0: StopDrawing(): ProcedureReturn: EndIf
    Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    If StepX <> 0
    PixelFormat = DrawingBufferPixelFormat() & ~#PB_PixelFormat_ReversedY
    If PixelFormat >= #PB_PixelFormat_32Bits_RGB
       StepX <<2
    ElseIf PixelFormat >= #PB_PixelFormat_24Bits_RGB
       StepX * 3
    ElseIf PixelFormat >= #PB_PixelFormat_15Bits
       StepX <<1
    EndIf
      *Dest = AllocateMemory(StepX)
      For y = 0 To SpriteH - 1
        *debut = Buffer + Pitch * y
        CopyMemory(*debut, *Dest, StepX)
        CopyMemory(*debut + StepX, *debut, Pitch - StepX)
        CopyMemory(*Dest, *debut + Pitch - StepX, StepX)
      Next y
      FreeMemory(*dest)
    EndIf
    If StepY <> 0
      If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY
        StepY = SpriteH - StepY ;reverse the Y value
     EndIf
      *Dest = AllocateMemory(Pitch * StepY)
      *debut = Buffer
      CopyMemory(*debut, *Dest, Pitch * StepY)
      CopyMemory(*debut + Pitch * StepY, *debut, Pitch * (SpriteH - StepY))
      CopyMemory(*Dest, *debut + Pitch * (SpriteH - StepY), Pitch * StepY)
      FreeMemory(*Dest)
    EndIf  
    StopDrawing()    
  EndIf
EndProcedure


CompilerIf  #PB_Compiler_IsMainFile
  If InitSprite() = 0 Or InitKeyboard() = 0: MessageRequester("Error", "Can't open the sprite system", 0): End: EndIf
  If OpenWindow(0, 0, 0, 800, 600, "Scroll Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf
  If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf    
  ;}
  
  LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
  Define sw = SpriteWidth(0), sh = SpriteHeight(0) ;save original sprite size values for random selection later
  Define time.d, stepx, stepy
  
  Repeat
    WindowEvent()
    ExamineKeyboard()
    FlipBuffers()
    ClearScreen(#Black)
    
    RotateSprite(0, 0.1, #PB_Relative)
    If time.d < ElapsedMilliseconds()
       ZoomSprite(0, Random(sw * 3, 2), Random(sh * 3, 2))
       stepx = Random(4) - 2: stepy = Random(4) - 2: time = ElapsedMilliseconds() + 3000
    EndIf

    Scroll(0, stepx, stepy)
    DisplaySprite(0, ScreenWidth() / 2 - SpriteWidth(sprite) / 2,ScreenHeight() / 2)
    
  Until KeyboardPushed(#PB_Key_Escape)
CompilerEndIf
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Sprite Scrolling

Post by Demivec »

Fig wrote:Then, let's make it totaly bulletproof by adding different pixelformat support.
Excellent.

I suggest using a slightly different format for the pixel format comparisons that is modeled after the entry for DrawingBufferPixelFormat() in the help file.

Instead of:

Code: Select all

PixelFormat = DrawingBufferPixelFormat() & ~#PB_PixelFormat_ReversedY
If PixelFormat >= #PB_PixelFormat_32Bits_RGB
   StepX <<2
ElseIf PixelFormat >= #PB_PixelFormat_24Bits_RGB
   StepX * 3
ElseIf PixelFormat >= #PB_PixelFormat_15Bits
   StepX <<1
EndIf
use:

Code: Select all

 PixelFormat = DrawingBufferPixelFormat()
If PixelFormat & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
  StepX <<2
ElseIf PixelFormat & (#PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR)
  StepX * 3
ElseIf PixelFormat & #PB_PixelFormat_15Bits
  StepX <<1
EndIf
This will remove dependencies on the values of the constants and make things a little clearer.


Here is the updated code:

Code: Select all

Procedure Scroll(sprite.i, StepX.i, StepY.i)
  Protected SpriteW, SpriteH, y, Buffer, Pitch, PixelFormat, *Dest, *debut
  If StartDrawing(SpriteOutput(sprite))
    SpriteW = OutputWidth(): SpriteH = OutputHeight()
    StepX = (StepX + SpriteW) % SpriteW
    StepY = (StepY + SpriteH) % SpriteH
    If StepX = 0 And StepY = 0: StopDrawing(): ProcedureReturn: EndIf
    Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    If StepX <> 0
      PixelFormat = DrawingBufferPixelFormat()
      If PixelFormat & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
        StepX <<2
      ElseIf PixelFormat & (#PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR)
        StepX * 3
      ElseIf PixelFormat & #PB_PixelFormat_15Bits
        StepX <<1
      EndIf
      *Dest = AllocateMemory(StepX)
      For y = 0 To SpriteH - 1
        *debut = Buffer + Pitch * y
        CopyMemory(*debut, *Dest, StepX)
        CopyMemory(*debut + StepX, *debut, Pitch - StepX)
        CopyMemory(*Dest, *debut + Pitch - StepX, StepX)
      Next y
      FreeMemory(*dest)
    EndIf
    If StepY <> 0
      If PixelFormat & #PB_PixelFormat_ReversedY
        StepY = SpriteH - StepY ;reverse the Y value
      EndIf
      *Dest = AllocateMemory(Pitch * StepY)
      *debut = Buffer
      CopyMemory(*debut, *Dest, Pitch * StepY)
      CopyMemory(*debut + Pitch * StepY, *debut, Pitch * (SpriteH - StepY))
      CopyMemory(*Dest, *debut + Pitch * (SpriteH - StepY), Pitch * StepY)
      FreeMemory(*Dest)
    EndIf  
    StopDrawing()    
  EndIf
EndProcedure


CompilerIf  #PB_Compiler_IsMainFile
  If InitSprite() = 0 Or InitKeyboard() = 0: MessageRequester("Error", "Can't open the sprite system", 0): End: EndIf
  If OpenWindow(0, 0, 0, 800, 600, "Scroll Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf
  If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf    
  ;}
  
  LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
  Define sw = SpriteWidth(0), sh = SpriteHeight(0) ;save original sprite size values for random selection later
  Define time.d, stepx, stepy
  
  Repeat
    WindowEvent()
    ExamineKeyboard()
    FlipBuffers()
    ClearScreen(#Black)
    
    RotateSprite(0, 0.1, #PB_Relative)
    If time.d < ElapsedMilliseconds()
       ZoomSprite(0, Random(sw * 3, 2), Random(sh * 3, 2))
       stepx = Random(4) - 2: stepy = Random(4) - 2: time = ElapsedMilliseconds() + 3000
    EndIf

    Scroll(0, stepx, stepy)
    DisplaySprite(0, ScreenWidth() / 2 - SpriteWidth(sprite) / 2,ScreenHeight() / 2)
    
  Until KeyboardPushed(#PB_Key_Escape)
CompilerEndIf
@Edit: updated code with wilbert's observation regarding operator priorities
Last edited by Demivec on Sun Jul 09, 2017 6:25 am, edited 1 time in total.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Sprite Scrolling

Post by wilbert »

Demivec wrote:use:

Code: Select all

PixelFormat = DrawingBufferPixelFormat()
If PixelFormat & #PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR
  StepX <<2
ElseIf PixelFormat & #PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR
  StepX * 3
ElseIf PixelFormat & #PB_PixelFormat_15Bits
  StepX <<1
EndIf
This will remove dependencies on the values of the constants and make things a little clearer.
Since the AND and OR operator have the same priority, it should be

Code: Select all

PixelFormat = DrawingBufferPixelFormat()
If PixelFormat & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
  StepX <<2
ElseIf PixelFormat & (#PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR)
  StepX * 3
ElseIf PixelFormat & #PB_PixelFormat_15Bits
  StepX <<1
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Sprite Scrolling

Post by Demivec »

wilbert wrote:Since the AND and OR operator have the same priority, it should be
Code:
PixelFormat = DrawingBufferPixelFormat()
If PixelFormat & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
  StepX <<2
ElseIf PixelFormat & (#PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR)
  StepX * 3
ElseIf PixelFormat & #PB_PixelFormat_15Bits
  StepX <<1
EndIf
Thanks for pointing that out, I've updated the previous post with your suggestion.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: Sprite Scrolling

Post by walbus »

Interesting !
Last edited by walbus on Fri Jul 21, 2017 9:36 am, edited 2 times in total.
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: Sprite Scrolling

Post by Fig »

Demivec, I suggest you change

Code: Select all

PixelFormat = DrawingBufferPixelFormat()
place in the code, or PixelFormat always equals 0 if StepX equals 0...

The corrected code would be:

Code: Select all

Procedure Scroll(sprite.i, StepX.i, StepY.i)
  Protected SpriteW, SpriteH, y, Buffer, Pitch, PixelFormat, *Dest, *debut
  If StartDrawing(SpriteOutput(sprite))
    SpriteW = OutputWidth(): SpriteH = OutputHeight()
    StepX = (StepX + SpriteW) % SpriteW
    StepY = (StepY + SpriteH) % SpriteH
    If StepX = 0 And StepY = 0: StopDrawing(): ProcedureReturn: EndIf
    Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    PixelFormat = DrawingBufferPixelFormat()
    If StepX <> 0
      If PixelFormat & (#PB_PixelFormat_32Bits_RGB | #PB_PixelFormat_32Bits_BGR)
        StepX <<2
      ElseIf PixelFormat & (#PB_PixelFormat_24Bits_RGB | #PB_PixelFormat_24Bits_BGR)
        StepX * 3
      ElseIf PixelFormat & #PB_PixelFormat_15Bits
        StepX <<1
      EndIf
      *Dest = AllocateMemory(StepX)
      For y = 0 To SpriteH - 1
        *debut = Buffer + Pitch * y
        CopyMemory(*debut, *Dest, StepX)
        CopyMemory(*debut + StepX, *debut, Pitch - StepX)
        CopyMemory(*Dest, *debut + Pitch - StepX, StepX)
      Next y
      FreeMemory(*dest)
    EndIf
    If StepY <> 0
      If PixelFormat & #PB_PixelFormat_ReversedY
        StepY = SpriteH - StepY ;reverse the Y value
      EndIf
      *Dest = AllocateMemory(Pitch * StepY)
      *debut = Buffer
      CopyMemory(*debut, *Dest, Pitch * StepY)
      CopyMemory(*debut + Pitch * StepY, *debut, Pitch * (SpriteH - StepY))
      CopyMemory(*Dest, *debut + Pitch * (SpriteH - StepY), Pitch * StepY)
      FreeMemory(*Dest)
    EndIf  
    StopDrawing()    
  EndIf
EndProcedure


CompilerIf  #PB_Compiler_IsMainFile
  If InitSprite() = 0 Or InitKeyboard() = 0: MessageRequester("Error", "Can't open the sprite system", 0): End: EndIf
  If OpenWindow(0, 0, 0, 800, 600, "Scroll Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf
  If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0) = 0: MessageRequester("Error", "Can't open windowed screen!", 0): EndIf    
  ;}
  
  LoadSprite(0, #PB_Compiler_Home + "examples/sources/Data/PureBasic.bmp")
  Define sw = SpriteWidth(0), sh = SpriteHeight(0) ;save original sprite size values for random selection later
  Define time.d, stepx, stepy
  
  Repeat
    WindowEvent()
    ExamineKeyboard()
    FlipBuffers()
    ClearScreen(#Black)
    
    RotateSprite(0, 0.1, #PB_Relative)
    If time.d < ElapsedMilliseconds()
       ZoomSprite(0, Random(sw * 3, 2), Random(sh * 3, 2))
       stepx = Random(4) - 2: stepy = Random(4) - 2: time = ElapsedMilliseconds() + 3000
    EndIf

    Scroll(0, stepx, stepy)
    DisplaySprite(0, ScreenWidth() / 2 - SpriteWidth(sprite) / 2,ScreenHeight() / 2)
    
  Until KeyboardPushed(#PB_Key_Escape)
CompilerEndIf
I dont' think we will go any further on this topic so I 'd like to thank every body, especialy Demivec. :idea:
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
Post Reply