à faire :
mettre en page ailleurs que dans un simple post
illustrer
commenter les fonctions d'animation
créer un exemple convaincant
expliquer l'essentiel en gros...
voila le média lié au code

et voila le code qui fait office de brouillon, pas rédigé (ou en out cas à l'arrache) donc faut pas trop faire gaffe ^^
Code : Tout sélectionner
;tuto anim version pas rédigée...
;on commence par des initialisations....
InitSprite()
InitMouse()
OpenWindow(1, 100, 100, 640, 480, #PB_Window_TitleBar|#PB_Window_MinimizeGadget, "test anims")
OpenWindowedScreen(WindowID(), 0, 0, 640, 480, 0, 0, 0)
ReleaseMouse(1)
;on va utiliser un seul sprite pour créer des animations...
;le sprite contient 3 images par ligne et 4 lignes
;on dit que le pitch du buffer est de 3 frames
;numérotation des frames avec l'exemple de alex
; 0 1 2
; 3 4 5
; 6 7 8
; 9 10 11
;aussi l'animation a une vitesse, on va la définir
;par la durée d'affichage d'une frame à l'écran
;chaque animation possède un nombre de frames à jouer
;et on va stocker chaque frame à la suite...
;si on récapitule notre structure anim devrai
;ressembler un peu à ca
Structure buffer
sprite.l
pitch.l
count.l
width.l
height.l
EndStructure
Structure animation
buffer.buffer
speed.l
count.l
list.l
EndStructure
;sauf que ca on va pas le dire à l'utilisateur
;sinon ca va être lourd pour lui à utiliser
;donc on est gentil on va lui créer des fonctions
Procedure.l CreerAnimation(sprite.l, pitch.l, count.l, width.l, height.l, speed.l)
If pitch<1 Or count<pitch Or width<1 Or height<1 Or speed<1
ProcedureReturn 0
EndIf
*ptr.animation = AllocateMemory(SizeOf(animation))
If *ptr=0
ProcedureReturn 0
EndIf
*ptr\buffer\sprite = sprite
*ptr\buffer\pitch = pitch
*ptr\buffer\count = count
*ptr\buffer\width = width
*ptr\buffer\height = height
*ptr\speed = speed
*ptr\count = 0
*ptr\list = 0
ProcedureReturn *ptr
EndProcedure
;avec cette fonction on crée nos quatres animations
;alex qui marche dans chaque direction
#SPRITE_ALEX = 1
#VITESSE_ALEX = 300 ;ms, c'est une durée... pas vraiment une vitesse
UsePNGImageDecoder()
LoadSprite(#SPRITE_ALEX, "alex.png")
DefType.l alex_haut, alex_droite, alex_bas, alex_gauche
alex_haut = CreerAnimation(#SPRITE_ALEX, 3, 12, 48, 64, #VITESSE_ALEX)
alex_droite = CreerAnimation(#SPRITE_ALEX, 3, 12, 48, 64, #VITESSE_ALEX)
alex_bas = CreerAnimation(#SPRITE_ALEX, 3, 12, 48, 64, #VITESSE_ALEX)
alex_gauche = CreerAnimation(#SPRITE_ALEX, 3, 12, 48, 64, #VITESSE_ALEX)
If alex_haut=0 Or alex_droite=0 Or alex_bas=0 Or alex_gauche=0
MessageRequester("Erreur", "L'animation n'a pas été créée")
End
EndIf
;super, on a créé nos 4 animations, à partir d'un unique sprite
;mais bon on a pas de quoi jouer une animation, et puis surtout
;comment l'anim devine-t-elle les frames à jouer ?
;bon bah c'est partit pour une nouvelle fonction...
Procedure AjouterImage(*ptr.animation, frame.l)
If *ptr=0 Or frame<0 Or *ptr\count<0
ProcedureReturn 0
EndIf
If *ptr\count=0
*ptr\list = AllocateMemory(SizeOf(long))
If *ptr\list=0
ProcedureReturn 0
EndIf
*ptr\count = 1
PokeL(*ptr\list, frame)
Else
size.l = *ptr\count*SizeOf(long)
*new_list.l = AllocateMemory(size+SizeOf(long))
If *new_list=0
ProcedureReturn 0
EndIf
CopyMemory(*ptr\list, *new_list, size)
FreeMemory(*ptr\list)
*ptr\list = *new_list
*ptr\count + 1
PokeL(*ptr\list+size, frame)
EndIf
ProcedureReturn 1
EndProcedure
;maintenant on étudie les quatres animations... elles sont découpées
;en 4 mouvements... d'abord la position 'debout' (au milieu), ensuite
;la position 'pied droit' (à gauche), puis on repasse en position 'debout'
;et enfin la dernière on change de pied (à gauche)...
;pour la première animation ca donne les frames : 1, 0, 1, 2
AjouterImage(alex_haut, 1)
AjouterImage(alex_haut, 0)
AjouterImage(alex_haut, 1)
AjouterImage(alex_haut, 2)
AjouterImage(alex_droite, 4)
AjouterImage(alex_droite, 3)
AjouterImage(alex_droite, 4)
AjouterImage(alex_droite, 5)
AjouterImage(alex_bas, 7)
AjouterImage(alex_bas, 6)
AjouterImage(alex_bas, 7)
AjouterImage(alex_bas, 8)
AjouterImage(alex_gauche, 10)
AjouterImage(alex_gauche, 9)
AjouterImage(alex_gauche, 10)
AjouterImage(alex_gauche, 11)
;c'est bien beau mais on ne sait toujours pas comment afficher nos images
;donc encore une fois on va pas laisser l'utilisateur sans outil pour
;afficher son animation... encore une procédure
Procedure AfficherAnimation(*ptr.animation, x.l, y.l, begin.l)
If *ptr=0 Or *ptr\count<1 Or *ptr\buffer\pitch<1 Or IsSprite(*ptr\buffer\sprite)=0
ProcedureReturn 0
EndIf
frame.l = (ElapsedMilliseconds()-begin) / *ptr\speed
If frame<0 Or frame>*ptr\count Or *ptr\buffer\width<1 Or *ptr\buffer\height<1
ProcedureReturn 0
EndIf
frame = PeekL(*ptr\list + frame*4)
xx.l = (frame % *ptr\buffer\pitch) * *ptr\buffer\width
yy.l = (frame / *ptr\buffer\pitch) * *ptr\buffer\height
ClipSprite(*ptr\buffer\sprite, xx, yy, *ptr\buffer\width, *ptr\buffer\height)
DisplayTransparentSprite(*ptr\buffer\sprite, x, y)
ProcedureReturn 1
EndProcedure
Procedure BouclerAnimation(*ptr.animation, x.l, y.l, begin.l)
If *ptr=0 Or *ptr\count<1 Or *ptr\buffer\pitch<1 Or IsSprite(*ptr\buffer\sprite)=0
ProcedureReturn 0
EndIf
frame.l = (ElapsedMilliseconds()-begin) / *ptr\speed
frame % *ptr\count
If frame<0 Or frame>*ptr\count Or *ptr\buffer\width<1 Or *ptr\buffer\height<1
ProcedureReturn 0
EndIf
frame = PeekL(*ptr\list + frame*4)
xx.l = (frame % *ptr\buffer\pitch) * *ptr\buffer\width
yy.l = (frame / *ptr\buffer\pitch) * *ptr\buffer\height
ClipSprite(*ptr\buffer\sprite, xx, yy, *ptr\buffer\width, *ptr\buffer\height)
DisplayTransparentSprite(*ptr\buffer\sprite, x, y)
ProcedureReturn 1
EndProcedure
;maintenant on va afficher nos animations... en boucle pour pas se
;casser la tête...
Repeat
FlipBuffers(0)
ClearScreen(0, 0, 0)
;on affiche les anims
BouclerAnimation(alex_haut, 10, 10, 0)
BouclerAnimation(alex_droite, 100, 10, 0)
BouclerAnimation(alex_bas, 10, 100, 0)
BouclerAnimation(alex_gauche, 100, 100, 0)
;on affiche le sprite d'origine
ClipSprite(#SPRITE_ALEX, 0, 0, 288, 256)
DisplayTransparentSprite(#SPRITE_ALEX, 630-288, 470-256)
event = WindowEvent()
Until event=#PB_Event_CloseWindow
