Scrolling d'un sprite

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Scrolling d'un sprite

Message par Fig »

J'en ai eu besoin pour mon projet et je trouve cela élégant.
Ca ajoute une petite animation à peu de frais sur un sprite statique sur un écran.
Pas essayé sur de large sprites mais il n'y a pas de raison que ça ne fonctionne pas sur un gros parallaxe.

Code : Tout sélectionner

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)
   DisplaySprite(0,0,0)
   Scroll(0,-6,3)
Until KeyboardPushed(#PB_Key_Escape)
Dernière modification par Fig le ven. 07/juil./2017 8:39, modifié 10 fois.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Scrolling d'un sprite

Message par falsam »

Merci fig. Ca répond en plus partiellement à une question que j'ai posé ici http://www.purebasic.fr/french/viewtopi ... =2&t=16198

L'idéal serait d'avoir une procédure ScrollSprite(Sprite, StepX, StepY) permettant de scroller un sprite verticalement et/ou horizontalement en précisant le pas vertical et horizontal.

Si c'est possible, merci de ce plus.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Scrolling d'un sprite

Message par djes »

Il faut dire pour la petite histoire (même si on ne peut pas grand chose aux choix de microsoft qui traîne de biens gros boulets depuis le début) qu'avant le passage à dx9, polux faisait ça avec des copysprite() ou des grabs ou des clips, et c'était facile et hyper rapide (plusieurs parallaxes superposés...) ; maintenant, c'est une autre histoire, il faut penser complètement différemment. Mais bon, les bécanes sont suffisamment puissantes pour ne pas avoir trop à se fatiguer...
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Scrolling d'un sprite

Message par comtois »

Je n'ai pas testé, ta méthode est plus rapide qu'avec ClipSprite() ?

Code : Tout sélectionner

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")

Width = SpriteWidth(0)
Procedure Clamp(*x.integer, limite)
  If *x\i > limite
    *x\i = 0
  EndIf  
EndProcedure

x=0
Repeat
   WindowEvent()
   ExamineKeyboard()
   FlipBuffers()
   ClearScreen(#Black)
   ClipSprite(0,x,0,Width-x,SpriteHeight(0))
   DisplayTransparentSprite(0,0,0)
   ClipSprite(0,0,0,x,SpriteHeight(0))
   DisplayTransparentSprite(0,Width-x,0)
   Clamp(@x, Width)
   x + 1
Until KeyboardPushed(#PB_Key_Escape)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Scrolling d'un sprite

Message par Fig »

Je ne sais pas si c'est plus rapide, mais pour la procedure clamp() on peut la remplacer avantageusement par un modulo, je pense.

Code : Tout sélectionner

x%width
Pour ma part, je préfère que le sprite entier soit modifié plutôt que de l'afficher en deux fois, mais c'est chacun qui voit ce qu'il préfère, en l’occurrence je ne suis pas sectaire. :D
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Scrolling d'un sprite

Message par comtois »

Fig a écrit :Je ne sais pas si c'est plus rapide, mais pour la procedure clamp() on peut la remplacer avantageusement par un modulo, je pense.

Code : Tout sélectionner

x%width
Entièrement d'accord, bon c'est du vite fait.
Pour ma part, je préfère que le sprite entier soit modifié plutôt que de l'afficher en deux fois, mais c'est chacun qui voit ce qu'il préfère, en l’occurrence je ne suis pas sectaire. :D
Moi non plus, c'était histoire de montrer une autre façon de faire, à chacun de choisir la méthode qui lui convient :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Scrolling d'un sprite

Message par Fig »

falsam a écrit :Merci fig. Ca répond en plus partiellement à une question que j'ai posé ici http://www.purebasic.fr/french/viewtopi ... =2&t=16198
L'idéal serait d'avoir une procédure ScrollSprite(Sprite, StepX, StepY) permettant de scroller un sprite verticalement et/ou horizontalement en précisant le pas vertical et horizontal.
Si c'est possible, merci de ce plus.
Voila, tu as la fonction ScrollSprite(Sprite, StepX, StepY), j'ai modifié le premier code. Ca fonctionne pas mal je trouve. :wink:
0 pour pas de scroll dans la direction en question. Positif ou négatif pour un sens ou l'autre verticalement et/ou horizontalement.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Scrolling d'un sprite

Message par falsam »

Hey mais c'est pas mal du tout cette procédure. Elle est bien plus stable que la mienne. Je teste ça avec un code plus concret .....
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Scrolling d'un sprite

Message par Fig »

Le comportement est intéressant avec transformsprite: ça fonctionne.
Avec rotatedSprite aussi.

Par contre avec zoomsprite, il faut effectuer la translation alors que le sprite a sa dimension d'origine.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Tonio
Messages : 95
Inscription : ven. 07/avr./2017 14:49
Localisation : Sud Est

Re: Scrolling d'un sprite

Message par Tonio »

Merci du partage Fig
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Scrolling d'un sprite

Message par Fig »

Bulletproof and shorter by Demivec.

Code : Tout sélectionner

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
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
Mindphazer
Messages : 635
Inscription : mer. 24/août/2005 10:42

Re: Scrolling d'un sprite

Message par Mindphazer »

Et là ça fonctionne nickel sur Mac ! :P
(la première version du premier code ne fonctionnait pas, je crois que tu l'as modifiée suite à ce que t'avait dit Wilbert sur le forum anglais :) )
Bureau : Win10 64bits
Maison : Macbook Pro M1 14" SSD 512 Go / Ram 16 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Scrolling d'un sprite

Message par falsam »

J'ai suivit les débats sur ce forum ainsi que sur le forum Anglophone. Fig et Demivec bravo c'est du beau travail.

J'ai quand même un souci avec la vitesse de défilement qui même réglée à 1 reste encore trop rapide dans le cadre d'une application utilisant un system de paralax comme vous allez avec cet exemple mettant en jeu 3 scroll-layer.

http://falsam.com/download/purebasic/ScrollSprite.zip

J'espére que vous aurez une solution à me proposer. Merci.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Scrolling d'un sprite

Message par Fig »

Bein tu update pas à chaque tour de boucle dans ce cas là... Mais je suis sûr que tu y aS pensé, non ?
Comme de toute façon un écran n'affichera pas les déplacements de fraction de pixels, hein... :mrgreen:

Waw c'est beau en tout cas !! Elles sont de qui ces images ? (je les piquerai bien moi...)
Dernière modification par Fig le dim. 09/juil./2017 13:12, modifié 1 fois.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Scrolling d'un sprite

Message par djes »

Fig a écrit :Comme de toute façon un écran n'affichera pas les déplacements de fraction de pixels, hein... :mrgreen:
À ta place, je ne serais pas aussi sûr de moi ! :mrgreen:
Répondre