Page 1 sur 2
Scrolling d'un sprite
Publié : jeu. 06/juil./2017 10:57
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)
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 14:15
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.
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 15:16
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...
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 16:24
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)
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 16:32
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.
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.

Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 16:44
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.
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.

Moi non plus, c'était histoire de montrer une autre façon de faire, à chacun de choisir la méthode qui lui convient

Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 18:00
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.

0 pour pas de scroll dans la direction en question. Positif ou négatif pour un sens ou l'autre verticalement et/ou horizontalement.
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 20:15
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 .....
Re: Scrolling d'un sprite
Publié : jeu. 06/juil./2017 22:02
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.
Re: Scrolling d'un sprite
Publié : ven. 07/juil./2017 16:37
par Tonio
Merci du partage Fig
Re: Scrolling d'un sprite
Publié : sam. 08/juil./2017 9:56
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
Re: Scrolling d'un sprite
Publié : sam. 08/juil./2017 10:39
par Mindphazer
Et là ça fonctionne nickel sur Mac !

(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

)
Re: Scrolling d'un sprite
Publié : sam. 08/juil./2017 22:20
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.
Re: Scrolling d'un sprite
Publié : dim. 09/juil./2017 8:51
par Fig
Bein tu update pas à chaque tour de boucle dans ce cas là... Mais je suis sûr que tu y a
S pensé, non ?
Comme de toute façon un écran n'affichera pas les déplacements de fraction de pixels, hein...
Waw c'est beau en tout cas !! Elles sont de qui ces images ? (je les piquerai bien moi...)
Re: Scrolling d'un sprite
Publié : dim. 09/juil./2017 9:42
par djes
Fig a écrit :Comme de toute façon un écran n'affichera pas les déplacements de fraction de pixels, hein...

À ta place, je ne serais pas aussi sûr de moi !
