[RESOLU] sprite et animation (+ieurs exemples)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

[RESOLU] sprite et animation (+ieurs exemples)

Message par blendman »

salut

voilà, j'utilise cette procédure pour mes animations de sprite3D :

Code : Tout sélectionner

Procedure DisplayAnimsprite(idsprite,xx,yy,xprevious,yprevious,framecurrent,frameNb,mode)
; un timer pour l'animation
 If T.l < ElapsedMilliseconds()+ 50
    T = ElapsedMilliseconds()
    framecurrent + 1/(#FPS_LIMIT/#speedroom)
  EndIf
   
  If framecurrent>frameNb-1
    framecurrent = 0
  EndIf 
    
  If mode = 1    
    If  xprevious = xx  And  yprevious  = yy
      DisplaySprite3D((idsprite+4),xx,yy)
    ElseIf  (xprevious <> xx  Or  yprevious <> yy)    
      DisplaySprite3D((idsprite)+framecurrent,xx,yy) 
    EndIf 
  ElseIf mode = 0    
      DisplaySprite3D((idsprite),xx,yy)
  EndIf
   
  ProcedureReturn
EndProcedure
et pour l'utiliser sur un monstre (un mob), je fais ceci :

Code : Tout sélectionner

DisplayAnimsprite(*mob\Id,Position\x,Position\y,*mob\previous\x ,*mob\previous\y,*mob\frameCurrent,12,1)
Je voudrais que *mob\frameCurrent s'actualise dans la procédure, mais visiblement, ça ne marche pas.
Savez-vous comment je pourrais faire ce genre de chose ?

J'ai essayé en remplaçant par une macro (même fonction) mais ça donne la même chose.
En gros, mon animation n'est pas jouée.

j'ai testé en remplaçant framecurrent par une variable globale et là, ça marche.
Mais je voudrais incrémenter par sprite et non pour tous en même temps, sinon, ça crée des soucis :).

Une idée de mon erreur ?
Merci
Dernière modification par blendman le jeu. 28/avr./2011 10:37, modifié 1 fois.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: sprite et animation

Message par Le Soldat Inconnu »

Il faut passer par des pointeurs pour actualiser un paramètre passer en arguments à une procedure

regarde ce sujet par exemple :
http://www.purebasic.fr/french/viewtopi ... t=pointeur
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
case
Messages : 1547
Inscription : lun. 10/sept./2007 11:13

Re: sprite et animation

Message par case »

mon système que j'ai développé pour puredash
chaque sprite peut avoir un nombre de frames different, et un timer different.

Code : Tout sélectionner

InitSprite()
Structure timer
   ticks.i     ; combien de millisecondes
   timebomb.i  ; ancienne valeur du timer 
   trigger.i   ; flag
EndStructure
Structure sprite
   name.s
   frame.b     ; frame actuelle
   maxframe.b  ; frame max 
   timer.i     ; timer utilisé 
EndStructure
;
; declaration des procedures
;
Declare createtimer(ticks)
Declare updatetimers()
Declare displaymob(id,x,y)
;
;
;
Global NewList sprites.sprite() ; cree une liste contenant les sprites
Global NewList timers.timer() ; cree une liste pour les timers
;
; fenetre pour une sortie...
Global main=OpenWindow(#PB_Any,0,0,640,480,"test")
OpenWindowedScreen(WindowID(main),0,0,640,480,0,0,0)
; creation des sprites fictifs
AddElement(sprites())
sprites()\name="titi"            ; nom du mob
sprites()\frame=0                ; frame actuelle
sprites()\maxframe=9             ; max frame avant de revenir a la frame 0
sprites()\timer=createtimer(500)  ; nombre de milliseconds pour changer de frame
; 
AddElement(sprites())
sprites()\name="troll"
sprites()\frame=0
sprites()\maxframe=5
sprites()\timer=createtimer(1000) 
;
AddElement(sprites())
sprites()\name="reaper"
sprites()\frame=0
sprites()\maxframe=40
sprites()\timer=createtimer(1000) ; meme duree que le mob 2 ils partagent le même timer
;
ForEach sprites()
   Debug sprites()\name
   Debug sprites()\frame
   Debug sprites()\maxframe
   Debug sprites()\timer
   
Next
Repeat
   ev=WaitWindowEvent(0)
   updatetimers() ; met a jour les timers
   ClearScreen(0) ; efface l'ecran
   displaymob(0,10,10) ; titi
   displaymob(1,100,40) ; troll
   displaymob(2,0,100) ; reaper
   FlipBuffers()
Until ev=#PB_Event_CloseWindow
End
Procedure createtimer(ticks)   ; creation d'un timer personalisé
   
   ForEach timers()               ; verifie si un timer avec le même tempo existe...
      If timers()\ticks=ticks     ; oui
         ProcedureReturn ListIndex(timers()) ;on renvoie son index
      EndIf
   Next        
      ;                           ; non creation d'un nouveau timer
      AddElement(timers())        ; ajout d'un timer
      timers()\ticks=ticks        ; tempo du timer en milliseconds
      timers()\timebomb=ElapsedMilliseconds() ; nombre de millisecond systeme actuel
      timers()\trigger=0           ; activé ou pas      
      ProcedureReturn ListIndex(timers())
    
EndProcedure
Procedure updatetimers()
   ForEach timers()
      timers()\trigger=0 ; on eteind le flag
      If ElapsedMilliseconds()-timers()\timebomb>=timers()\ticks
         TIMERS()\timebomb=ElapsedMilliseconds()
         timers()\trigger=1
      EndIf
   Next
EndProcedure
Procedure displaymob(id,x,y)
   SelectElement(sprites(),id)             ; selection du bon sprite
   SelectElement(timers(),sprites()\timer) ; selectionne son timer   
   ;
   If timers()\trigger=1                   ; declechement du timer
      sprites()\frame +1                   ; frame +1
      If sprites()\frame>sprites()\maxframe; depassement des frames du sprite
         sprites()\frame=0                 ; retour au debut
      EndIf
   EndIf
   StartDrawing(ScreenOutput())
      DrawText(x,y,sprites()\name)
      DrawText(x,y+16,Str(sprites()\frame))
   StopDrawing()
EndProcedure
ImageImage
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: sprite et animation

Message par blendman »

Le soldat inconnu : j'ai regardé, et j'ai testé diverses solution (@framecurrent, @*framecurrent, etc..) mais rien n'a marché :P

Case : merci pour ton exemple, je pense que je vais faire pareil.
Bonne idée la liste de timer, je n'y avais pas pensé.

Je vais tester ça et je te dirai si ça a marché ;).

Encore merci

EDIT : j'ai regardé, mais visiblement, tu utilisé une unique structures pour tes sprites, mais moi, j'en utilise plusieurs, car j'ai des objets animés et d'autres non animés, des mobs qui ont leur structures, les player ont aussi leur structures, etc...
Donc, il faut que je comprenne comment je peux convertir ta méthode à mon système :p.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: sprite et animation

Message par Fig »

Pour ne pas te compliquer la vie, utilise la même structure pour les objets animés ou non, à moins que la mémoire soit vraiment cruciale, cela ne devrait pas te poser de problème. (du reste tu pourrais changer d'avis et vouloir quand même animer tes sprites... Les arbres par exemple pourraient pousser ou les feuilles se balancer au rythme du vent etc...)
Je n'ai pas essayé le code mais si il n'y a pas d'animation mets le maxframe à 0, cela devrait fonctionner...
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
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: sprite et animation

Message par blendman »

Fig a écrit :Pour ne pas te compliquer la vie, utilise la même structure pour les objets animés ou non, à moins que la mémoire soit vraiment cruciale, cela ne devrait pas te poser de problème. (du reste tu pourrais changer d'avis et vouloir quand même animer tes sprites... Les arbres par exemple pourraient pousser ou les feuilles se balancer au rythme du vent etc...)
Je n'ai pas essayé le code mais si il n'y a pas d'animation mets le maxframe à 0, cela devrait fonctionner...
le problème c'est que je ne peux pas car j'ai déjà conçu mon code avec des structures différentes, et je ne me vois pas ré-écrire ou corriger 1000 lignes (minimum) de codes :p (j'en ai déjà 6500).
En plus, c'est assez compliqué, car j'ai des animations qui sont lancées en boucle dès la création de la map, ou ponctuellement (en boucle infinies, limitée à une certain nombre de fois, ou ne tournant qu'une fois, et ce la en fonction de divers évènements)

Bref, un vrai casse-tête :).

Il faut que je trouve une autre solution.
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: sprite et animation

Message par Cool Dji »

Salut Blendman,

Souvent, c'est plus efficace de réécrire des procédures afin que tout soit clean plutôt que de trainer des structures avec lesquelles tu dois sans cesse bricoler (facile à dire, je sais :mrgreen: )
Only PureBasic makes it possible
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: sprite et animation

Message par Fig »

lol j'ai failli écrire cela et puis je me suis ravisé.... Je ne veux pas le décourager... :mrgreen:

Bon déja essaye avec cela: (sinon il joue l'animation systématiquement)

Code : Tout sélectionner

if Elapsedmilliseconds()-T>=50
Le 50 est le délais de l'animation pour tes sprites... Il serait pertinent de faire une variable contenant le délai de ton sprite, et de l'intégrer à la structure du sprite... Ca te permettra de faire des animations de vitesse différente.

Ensuite, T doit dépendre de chacun des sprites... Tu dois donc l'intégrer à ta structurede sprite....
Passe le en paramètre de ta procédure par exemple...

Bon Procedurereturn à la fin n'est pas nécessaire puisque tu arrive en fin de procedure avec endprocedure.

bon courage !! :wink:
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: sprite et animation

Message par djes »

Il y a deux façons de faire un timing dans un jeu :

Soit on se base sur le framerate, et le flipbuffers(). Dans ce cas, chaque passage équivaut à une fraction de temps (par exemple 1/60ème de sec) qu'il suffit de compter pour faire des animations. C'est précis, c'est carré, par contre il faut que la machine suive la cadence, ou réduire celle-ci (en affichant une frame sur deux, 1/30ème sec). Dans tous les cas, il faut essayer de garder une cadence fixe, en prévoyant dès le départ l'affichage maximal.

Soit on se base sur un timer, et on détache le décompte de la boucle d'affichage.

La deuxième est plutôt efficace en 3D, et permet de faire des timeslices inférieurs à la durée d'une frame. On n'affiche que quand une image est prête. En 2D par contre, ça donne des animations pas très fluides, avec des sauts ; il vaut mieux choisir la première.

Dans les deux cas, il faut savoir si l'on gère les interactions avec les joueurs séparément de la boucle principale. C'est très important, car tout le moteur de déplacement en dépend, et c'est un vrai casse-tête en réseau!
comtois
Messages : 5191
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: sprite et animation

Message par comtois »

un exemple

Code : Tout sélectionner

Structure sMob
  Id.l
  Previous.Point
  frameCurrent.l
EndStructure

Procedure DisplayAnimsprite(*framecurrent.long)
  *framecurrent\l = 56
EndProcedure

Procedure ProcedureTruc(*Mob.sMob)
 DisplayAnimsprite(@*Mob\frameCurrent)
EndProcedure

Procedure Modif(*Ptr.sMob)
    *Ptr\frameCurrent = 82
EndProcedure

Procedure Main()
  Define Mob.sMob
  ;Premier cas, la modif se fait dans la procédure appelée
  Modif(@Mob)
  Debug Mob\frameCurrent
  ;Second cas, on appelle une procédure qui elle même en appelle une autre pour faire la modif
  ProcedureTruc(@Mob)
  Debug Mob\frameCurrent
EndProcedure

Main()
Dernière modification par comtois le mer. 27/avr./2011 12:22, modifié 1 fois.
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.
comtois
Messages : 5191
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: sprite et animation

Message par comtois »

blendman a écrit :le problème c'est que je ne peux pas car j'ai déjà conçu mon code avec des structures différentes, et je ne me vois pas ré-écrire ou corriger 1000 lignes (minimum) de codes :p (j'en ai déjà 6500).
En plus, c'est assez compliqué, car j'ai des animations qui sont lancées en boucle dès la création de la map, ou ponctuellement (en boucle infinies, limitée à une certain nombre de fois, ou ne tournant qu'une fois, et ce la en fonction de divers évènements)

Bref, un vrai casse-tête :).
C'est pour ça qu'il est très important d'écrire ce que l'on veut faire avant de se lancer dans un gros projet. Aligner du code bout à bout n'est pas la bonne solution, tôt ou tard ça coince. :)
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.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: sprite et animation

Message par Backup »

comtois a écrit : C'est pour ça qu'il est très important d'écrire ce que l'on veut faire avant de se lancer dans un gros projet. :)
ou de bien connaitre les "pieges"
et de prevoir une porte de sortie

perso j'aurai fait qu'une structure
mais pour l'anim j'aurai décidé d'un nombre d'images d'animation Max (a 15 par ex)

et dans la structure j'aurai utilisé un Tableau Static

Code : Tout sélectionner

Structure sprite
    x.i ; position en x
    Y.i ; position en Y
    vie.b ; vivant/mort
    pas_x.i ; deplacement en X
    pas_y.i ; deplacement en y
    anim[15]  ; animation (image) en cours
EndStructure
apres libre a toi d'utiliser ou pas les 15 images possible (animé ou pas animé) :)

une structure, pour un sprite, moi je vois ça comme son Squelette
ou comme son code génétique :)

chaque sprite se voit attribuer sa "fiche genetique" (sa structure) :)
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: sprite et animation

Message par blendman »

FIG : j'ai commencé à modifier tout cela en fonction de tes remarques. Je vais faire des tests pour voir si ça marche ;).

djes a écrit :Dans les deux cas, il faut savoir si l'on gère les interactions avec les joueurs séparément de la boucle principale. C'est très important, car tout le moteur de déplacement en dépend, et c'est un vrai casse-tête en réseau!
eh ben, déjà que ce n'es tpas évident alors que je suis en mode offline, lorsque je vais passer en réseau, ça va être coton :).


Sinon, j'ai aussi commencé à intégrer la technique de Case. Finalement, comme j'utilise des structures qui "extends" une autre structure, j'ai pu le faire sans devoir ré-écrire tout mon code :D. En testant son exemple, j'ai trouvé que ça fonctionnait vraiment pas mal du tout et c'est très simple au final.

Une question : ma liste d'objet animé risque de changer, car des monstres peuvent apparaitre, alors qu'ils n'étaient pas présent, ou disparaitre, ou d'autres joueurs peuvent aussi s'ajouter sur la carte par la suite, voire des sorts animés , etc...

Dans l'exemple de Case c'est facile d'accéder aux éléments de la liste, mais dans mon cas, j'ai beaucoup plus que 3 éléments et la liste n'est pas fixes :).

Alors, comment par exemple puis-je sélectionner dans la liste l'élément mob5 pour changer son animation ou son maxframe sans connaitre son id ?
(ici -> SelectElement(sprites(),id)

Merci ;).

EDIT :

Comtois : je n'avais pas vu ton message ;).
Comme je disais, en fait j'utilise au final des extends de structures.
Je vais regarder ton exemple pour voir si je m'en servir aussi.

Dobro : le tableau static, ça va aussi me servir :).

EDIT 2 :

bon, j'ai réussi, je crois :).

Voici la technique :

Je crée un timer /boucle générale (technique djes N°1)

Code : Tout sélectionner

Procedure timerAnim(frameNb)
  ; T est la variable globale que j'utilise en tant que timer pour la frame courante d'animation
  ; FrameU est aussi une variable gloable (un float)
; frameNb :  c'est le nombre de frame pour ce timer

  If T.l < ElapsedMilliseconds()+ 50
    T = ElapsedMilliseconds()
    FrameU + 1
  EndIf
     
  If FrameU > frameNb -1
    FrameU = 0
  EndIf
EndProcedure
Puis, j'ai cette procédure (toujours la même, mais je l'ai corrigée)

Code : Tout sélectionner

Procedure DisplayAnimsprite(idsprite,xx,yy,xprevious,yprevious,NumAnim,frameNb,frameCurrent,framedepart,mode.i=0)
 
; NumAnim = le numéro d'animation pour l'objet ou l'entité (mob, player.sort..). Par exemple 1 = marche, 2 = course, 3 =lance un sort, 4 = combat à l'épée..
; frameNb : le nombre d'image pour cette animation
; mode : si l'anim est jouée ou non
; framecurrent : c'est le numero de la frame courrante. ça ne marche pas.
; framedepart : c'est la frameU de départ, pour le moment je ne m'en sers pas, mais par la suite, j'en aurai besoin pour que l'animation débute en 0 à n'importe quelle frameU


frameActual = Round(FrameU,0) ; variable temporaire nécessaire pour convertir de float à integer (necessaire pour le modulo)
frameCurrent = frameActual  % frameNb ; le modulo magique : on garde comme numero de frame ce qui reste :)

  If mode = 1    ; si on a plusieurs images dans l'animation
    If  xprevious = xx  And  yprevious  = yy ; ça, je pense l'enlever car c'est lié au déplacement.
      DisplaySprite3D((idsprite+4),xx,yy)
    ElseIf  (xprevious <> xx  Or  yprevious <> yy)   
      DisplaySprite3D((idsprite)+frameCurrent,xx,yy)
    EndIf
  ElseIf mode = 0   
    DisplaySprite3D((idsprite),xx,yy)
  EndIf   
EndProcedure
Dans celle-ci, j'utilise un modulo pour récupérer la frame courrante pour mon animation, en fonction du nombre d'image de cette même animation :-)

Voiloutch. pour le moment, j'ai testé et ça fonctionne bien.
J'ai testé avec un personnage (animation par évènement souris (clic and go)), un feu (animation en boucle constante) et des mobs (pas d'animation, mais changement d'image en fonction de la direction).

Je testerai avec d'autres éléments.

Bien sûr, il faut que les structures de mes entités sprites aient les paramètres suivants :

Code : Tout sélectionner

structure sprites
NumAnim
frameNb
frameCurrent
framedepart
; autres paramètres...
endstructure
Du coup, je peux utiliser n'importe quelles structures avec cette procédure :).

Si besoin, je peux faire un petit exemple simple pour voir comment ça marche, mais c'est pas mal, ça évite d'utiliser de slistes de timer(), même si l'idée des timers est sympa aussi car très fonctionnel ;).

En tout cas, merci à vous tous pour l'aide :D.
Avatar de l’utilisateur
Fortix
Messages : 559
Inscription : mar. 30/mai/2006 17:03

Re: [RESOLU] sprite et animation (+ieurs exemples)

Message par Fortix »

Saluts,

existe t il une version avec Thread?
Avatar de l’utilisateur
Fortix
Messages : 559
Inscription : mar. 30/mai/2006 17:03

Re: [RESOLU] sprite et animation (+ieurs exemples)

Message par Fortix »

Saluts,

existe t il une version avec Thread?
Répondre