Animation de sprites

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
plabouro472
Messages : 47
Inscription : sam. 23/juil./2022 10:17

Animation de sprites

Message par plabouro472 »

Animation de sprites

PB : 6.30
Os : Windows 11

Après leurs avoir donnés des trajectoires à suivre, nous allons leurs donner de l'animation et un point de référence.
Il peut être positionner n'importe ou à l'intérieure du sprite mais aussi à l'extérieur.

Les opérations de positionnement, Zooms et Rotations se feront par rapport à ce point de référence ou HotSpot.
La rotation se fait dans le sens trigo contrairement à l'instruction "RotateSprite" qui tourne dans le sens horaire.
Le zoom se mesure en pourcentage de la taille d'origine du Sprite.
L'animation peut revenir en arrière ou reprendre au début après la dernière image, ceci dans les deux sens.
l'image de départ peut être n'importe laquelle des images de la palette.

Les propriétés de chacun des Sprites seront stockés dans une variable structurée.

Structure PointFloat
x.f
y.f
EndStructure

Structure Spr
IdSprite .i ; Identifiant du Sptire ( chargé/créé )
SprTaille .PointFloat ; Taille du Sprite ( Largeur,Hauteur )
HotSpot .PointFloat ; Points de référence du Sprite ( X,Y )
SprPos .PointFloat ; Position du Sprite à l'écran ( X,Y )
VitPos .PointFloat ; Vitesse de déplacement ( X,Y )
SprZoom .f ; Zoom du Sprite ( 1 = 100% de sa taille)
VitZoom .f ; Vitesse de Zoom ( +-0.02 = +-2% )
SprAngle .f ; Angle du Sprite en degré
VitAngle .f ; Vitesse angulaire en degré ( Positif = sens trigo )
AnimNo .b ; N° du Sprite à Clipper, dans la palette
AnimInc .b ; Incrémentation de position dans la palette ( +1/-1 )
AnimNoMax .b ; N° du dernier Sprite dans la palette
AnimRaz .a ; Reprend au 1er Sprite ( #True/#False )

EndStructure

Pour la démo, deux hélicoptères ( vraiment trééééééés..... basic ), se déplacent en sens inverse avec rotation et zoom.
Le point de référence du sprite 1 est centré horizontalement et verticalement.
Le point de référence du sprite 2 est positionné en bas et au milieu.
Le point de référence des sprites sera positionné sur la position d'affichage de celui-ci, materialisée par un axe traversant l'écran.

Une boite de dialogue temporise pour un affichage pas à pas.

Code : Tout sélectionner

 

; ******************************
; Animation de Sprites
; PB : 6.30
; Os : Windows 11
; ******************************



; ******************************
; ** Palette animation helico **
; ** **
; 20 pixels de large
; 22 Pixels de haut
; 10 images alignées horizontalement ( N° de 0 à 9 )
DataSection
 DataPalette_Helico_20x22:
 Data .a 6 ; Palette de 6 couleurs
 Data .l $00000000 , $00FEF0F0 , $00FF8000 , $00FFF000 , $00FF8072 , $00150088
 DataImage_Helico_20x22:
 Data .a 05 , 11 ; Nombre de données de la table ( X , Y ) 
 Data .a 04 , 02 ; Dimension des pixels ( X , Y ) 
 Data_Helico: ; Données de l"hélico
 Data .a $01,$01,$01,$01,$01
 Data .a $00,$00,$01,$00,$00
 Data .a $00,$00,$01,$00,$00
 Data .a $00,$02,$02,$02,$00
 Data .a $02,$02,$02,$02,$02
 Data .a $02,$03,$03,$03,$02
 Data .a $02,$03,$01,$03,$02
 Data .a $02,$03,$01,$03,$02
 Data .a $02,$03,$03,$03,$02
 Data .a $04,$04,$02,$04,$04
 Data .a $00,$04,$04,$04,$00
EndDataSection
Dim MesCouleurs .l ( 1 )
Restore DataPalette_Helico_20x22 ; Chargement de la palette de couleurs
Read .a N
ReDim MesCouleurs( N - 1 )
For I = 0 To N -1
 Read .l MesCouleurs( I )
Next
Restore DataImage_Helico_20x22 ; Dessin de l'hélico
Read .a Larg
Read .a Haut
Read .a LargPix
Read .a HautPix
PaletteHelico = CreateImage( #PB_Any , Larg * LargPix * 10 , Haut * HautPix , 32 )
StartDrawing ( ImageOutput( PaletteHelico ) )
 For N = 0 To 9 ; 10 images alignées horizontalement
 Restore Data_Helico:
 For Y = 0 To Haut - 1
 For X = 0 To Larg - 1
 Read .a C
 Box( N*20 + X*LargPix , Y*HautPix , LargPix , HautPix , MesCouleurs( C ) )
 Next
 Next
 Box( N*20 , 0 , N , HautPix , #Black ) ; Les pales
 Box( N*20 + 20 - N , 0 , N , HautPix , #Black )
 Next
StopDrawing() 
FreeArray( MesCouleurs() )
; Sauvegarde sur disque
; SaveImage( PaletteHelico , GetCurrentDirectory() + "Palette_Helico_20x22.bmp" , #PB_ImagePlugin_BMP )


Structure PointFloat
 x.f
 y.f
EndStructure
Structure Spr
 IdSprite .i ; Identifiant du Sptire ( chargé/créé )
 SprTaille .PointFloat ; Taille du Sprite ( Largeur/Hauteur )
 HotSpot .PointFloat ; Points de référence du Sprite ( X,Y )
 SprPos .PointFloat ; Position du Sprite à l'écran ( X,Y )
 VitPos .PointFloat ; Vitesse de déplacement ( X,Y )
 SprZoom .f ; Zoom du Sprite ( 1 = 100% de sa taille)
 VitZoom .f ; Vitesse de Zoom ( +-0.02 = +-2% )
 SprAngle .f ; Angle du Sprite en degré
 VitAngle .f ; Vitesse angulaire en degré ( Positif = sens horaire )
 AnimNo .b ; N° du Sprite à Cliper dans la palette
 AnimInc .b ; Incrémentation de position dans la palette ( +1/-1 )
 AnimNoMax .b ; N° du dernier Sprite dans la palette
 AnimRaz .a ; Reprend au 1er Sprite ( #True/#False ) 

EndStructure 
 
 
#ScreenWidth = 800
#ScreenHeight = 600
#Tempo = 25
Attente.i = 5000

Procedure AfficheAxes ( *This.Spr , _C.l ) ; Dessin de l'axe
 With *This\SprPos
 StartDrawing ( ScreenOutput() )
 Line ( \x , 0 , 1 , #ScreenHeight , _C )
 Line ( 0 , \y , #ScreenWidth , 1 , _C )
 Circle ( \x , \y , 2 , _C )
 StopDrawing()
 EndWith
EndProcedure
Procedure CalculePositionSuivante ( *This.Spr )
 With *This
 \SprPos\x + \VitPos\x
 \SprPos\y + \VitPos\y
 \SprZoom + \VitZoom
 If \SprZoom < 1 : \SprZoom = 1: EndIf
 
 \SprAngle + \VitAngle
 If \SprAngle > 360 : \SprAngle - 360 : EndIf
 If \SprAngle < 0 : \SprAngle + 360 : EndIf
 
 \AnimNo + \AnimInc
 If \AnimRaz ; L'animation reprend au début
 If \AnimNo > \AnimNoMax : \AnimNo = 0 : EndIf
 If \AnimNo < 0 : \AnimNo = \AnimNoMax : EndIf
 Else ; L'animation reprend en arrière
 If \AnimNo = \AnimNoMax Or \AnimNo = 0 : \AnimInc = -\AnimInc : EndIf
 EndIf 
 
 EndWith
EndProcedure
Procedure AfficheSptite ( *This.Spr )
 Protected .f TmpHotSpotx , TmpHotSpoty
 Protected .f HotSpotLong , HotSpotAngle
 Protected .f DeltaX , DeltaY
 Protected .f DemiX , DemiY

 With *This
 ; Calcule du HotSpot en tenant compte de la rotation ( Sens Trigo )
 DemiX = \SprTaille\x / 2 
 DemiY = \SprTaille\y / 2 
 DeltaX = \HotSpot\x - DemiX
 DeltaY = - ( \HotSpot\y - DemiY )
 HotSpotLong = Sqr( ( DeltaX * DeltaX ) + (DeltaY * DeltaY ) )
 HotSpotAngle = ATan2( DeltaX , DeltaY ) + Radian( \SprAngle )
 TmpHotSpotx = ( DemiX + ( Cos( HotSpotAngle ) * HotSpotLong ) ) * \SprZoom
 TmpHotSpoty = ( DemiY - ( Sin( HotSpotAngle ) * HotSpotLong ) ) * \SprZoom

 ClipSprite ( \IdSprite , \AnimNo * \SprTaille\x , 0 , \SprTaille\x , \SprTaille\y )
 ZoomSprite ( \IdSprite , \SprTaille\x * \SprZoom , \SprTaille\y * \SprZoom )
 RotateSprite ( \IdSprite , -\SprAngle , #PB_Absolute )
 
 DisplayTransparentSprite( \IdSprite , \SprPos\x - TmpHotSpotx , \SprPos\y - TmpHotSpoty )
 EndWith
EndProcedure

InitSprite()
OpenWindow ( 0 , 100 , 100 , #ScreenWidth , #ScreenHeight , "Sprite..." , #PB_Window_SystemMenu )
OpenWindowedScreen ( WindowID(0) , 0 , 0 , #ScreenWidth , #ScreenHeight , #True , 0 , 0 )


#SpriteWidth = 20
#SpriteHeight = 22
#SpriteNoMax = 9 ; Numéro du dernier sprite dans la palette

; ********************************
; *** Initialise le Sprite N°1 ***
; ********************************
MonSprite1 .Spr
; ; Chargement depuis le disque
; MonSprite1\IdSprite = LoadSprite( #PB_Any , GetCurrentDirectory() + "Palette_Helico_20x22.bmp" , #PB_Sprite_AlphaBlending )

; ou Chargement depuis une image
MonSprite1\IdSprite = CreateSprite( #PB_Any , 10 * #SpriteWidth , #SpriteHeight , #PB_Sprite_AlphaBlending )
StartDrawing ( SpriteOutput( MonSprite1\IdSprite ) )
 DrawingMode ( #PB_2DDrawing_AllChannels )
 DrawImage ( ImageID( PaletteHelico ) , 0 , 0 )
StopDrawing ( )

TransparentSpriteColor( MonSprite1\IdSprite , RGB( 0,0,0 ) )
; Les propriétées
MonSprite1\SprTaille\x = #SpriteWidth
MonSprite1\SprTaille\y = #SpriteHeight
MonSprite1\HotSpot\x = #SpriteWidth / 2
MonSprite1\HotSpot\y = #SpriteHeight / 2
MonSprite1\SprPos\x = 200
MonSprite1\SprPos\y = 200
MonSprite1\VitPos\x = 2
MonSprite1\VitPos\y = 0
MonSprite1\SprZoom = 5.00 ; 5 fois sa taille ( 500% )
MonSprite1\VitZoom = -0.02 ; réduit sa taille de 2%
MonSprite1\SprAngle = 0
MonSprite1\VitAngle = -1 ; <0 = Sens Trigo
MonSprite1\AnimNo = 5 ; Image de départ
MonSprite1\AnimInc = 1
MonSprite1\AnimNoMax = #SpriteNoMax
MonSprite1\AnimRaz = #False



; ********************************
; *** Initialise le Sprite N°2 ***
; ********************************
MonSprite2 .Spr
; ; Chargement depuis le disque
; MonSprite2\IdSprite = LoadSprite( #PB_Any , GetCurrentDirectory() + "Palette_Helico_20x22.bmp" , #PB_Sprite_AlphaBlending )

; ou Chargement depuis une image
MonSprite2\IdSprite = CreateSprite( #PB_Any , 10 * #SpriteWidth , #SpriteHeight , #PB_Sprite_AlphaBlending )
StartDrawing ( SpriteOutput( MonSprite2\IdSprite ) )
 DrawingMode ( #PB_2DDrawing_AllChannels )
 DrawImage ( ImageID( PaletteHelico ) , 0 , 0 )
StopDrawing ( )

TransparentSpriteColor( MonSprite2\IdSprite , RGB( 0,0,0 ) )
; Les propriétées
MonSprite2\SprTaille\x = #SpriteWidth
MonSprite2\SprTaille\y = #SpriteHeight
MonSprite2\HotSpot\x = #SpriteWidth / 2
MonSprite2\HotSpot\y = #SpriteHeight
MonSprite2\SprPos\x = 480
MonSprite2\SprPos\y = 300
MonSprite2\VitPos\x = -2
MonSprite2\VitPos\y = 0
MonSprite2\SprZoom = 1.50
MonSprite2\VitZoom = 0.03
MonSprite2\SprAngle = 45
MonSprite2\VitAngle = 2 ; >0 = Sens Horaire
MonSprite2\AnimNo = 0 ; Image de départ
MonSprite2\AnimInc = 1
MonSprite2\AnimNoMax = #SpriteNoMax
MonSprite2\AnimRaz = #True



; ********************************
; *** Boucle d'animation ***
; ********************************
For j= 0 To 180
 
 Event = WindowEvent()
 Select Event 
  Case #PB_Event_CloseWindow
   End 
 EndSelect
 
 If MessageRequester( "" , "Poursuivre ?" , #PB_MessageRequester_YesNo ) = #PB_MessageRequester_No
  Attente = 1
  Break
 EndIf
 
 ClearScreen ( RGB( 127 , 127 , 127 ) )
 
 AfficheSptite ( @MonSprite1 )
 AfficheSptite ( @MonSprite2 )
 AfficheAxes ( @MonSprite1 , RGB( 255 , 0 , 0 ) )
 AfficheAxes ( @MonSprite2 , RGB( 0 , 255 , 0 ) )
 CalculePositionSuivante ( @MonSprite1 )
 CalculePositionSuivante ( @MonSprite2 )
 
 FlipBuffers ( )
 Delay ( #Tempo ) 
 
Next
 
Delay ( Attente )
FreeSprite ( #PB_All ) 
CloseScreen ( )
 
 
Avatar de l’utilisateur
Mindphazer
Messages : 735
Inscription : mer. 24/août/2005 10:42

Re: Animation de sprites

Message par Mindphazer »

Bonjour et merci pour ce code

Pour info, cela fonctionne très bien sur MacOS :D
Bureau : Win11 64bits
Maison : Macbook Pro M4 16" SSD 512 Go / Ram 24 Go - iPad Air 128 Go (pour madame) - iPhone 17 Pro Max 256 Go
Répondre