|
| Animations lancées dans le fond pendant le jeu | |
| | Auteur | Message |
---|
Gob Adepte de la Grande Tasse Bleue
Nombre de messages : 123
Date d'inscription : 08/10/2021
| Sujet: Animations lancées dans le fond pendant le jeu Lun 18 Déc 2023 - 9:48 | |
| Hello, je n'arrive pas à lancer des anims dans le fond de façon efficace. La fonction eNoblock permet de garder la main pendant qu'une anim tourne mais permet aussi de lancer l'anim suivante en même temps, ce qui doit être problématique. Par exemple, suite à un timer, je veux lancer deux animations à la suite de deux persos, mais il ne lance pas la seconde, même si je met un timer par perso. Comment gérer au mieux des animations de fond ? |
| | | Clique Adepte de la Grande Tasse Bleue
Nombre de messages : 106
Date d'inscription : 11/05/2022
| Sujet: Re: Animations lancées dans le fond pendant le jeu Sam 23 Déc 2023 - 17:31 | |
| De ce que j'ai compris, la fonction de eNoblock est de laisser le script se poursuivre. À la différence de eBlock, qui (j'imagine) met en place un écouteur d'event qui fera attendre que l'animation se termine avant de laisser poursuivre le script. Je mentionne ça, parce que ça peut être une source d'incompréhension entre ce qu'on croit faire, et comment le script est réellement parcouru par la machine. Là comme tu emploie deux timers, j'imagine que ça peut être une erreur assez fréquente, où l'un ou les deux sont réinitialisés à chaque boucle du script. J'ai trouvé ce post qui donne un exemple : https://adventuregamestudio.1fr1.net/t1756-faire-bouger-des-persos-en-fond-pendant-que-le-joueur-joue#29670 - Code:
-
// Tu crée alors ton timer: function room_Load() { SetTimer(1, 50); //(1 correspond au numéro du compteur, et 50 à la période de répétition que tu veux) }
// ensuite tu sélectionne l'event Repeatdly execute et tu tapes: function room_RepExec() { if (IsTimerExpired(1) == true) { cPerso.Animate.... // (là tu tapes ce que tu veux faire en arrière plan) SetTimer(1,50); // ( et tu réinitialise le compteur) } } Pour que ce timer fonctionne, il faut qu'il soit lancé une première fois hors de la fonction "Repeatdly execute", ce qui est fait ici dans la fonction "room_Load()". Quand ce timer 1 est terminé la clause dans la fonction "Repeatdly execute" peut s’exécuter. Comme celui qui a écrit cet exemple n'utilise qu'un seul timer et qu'il veut le faire boucler, il réinitialise ce timer dans cette clause. Maintenant, si toi tu veux jongler avec 2 timers différents, ça peut devenir plus complexe, et faut bien comprendre comment/pourquoi. Si les 2 persos bouclent indépendamment l'un de l'autre, il s'agirait juste doubler cet exemple : - Code:
-
// On crée 2 timer: function room_Load() { SetTimer(1, 50); SetTimer(2, 75); }
function room_RepExec() { if (IsTimerExpired(1) == true) { cPerso_1.Animate.... SetTimer(1, 50); // ( réinitialise le compteur 1) } // les deux clauses "if" devront être séparées (je crois) if (IsTimerExpired(2) == true) { cPerso_2.Animate.... SetTimer(2, 75); // ( réinitialise le compteur 2) } } Note: dans la fonction "room_Load()" la valeur de durée des timers peut être différente de celles dans la fonction "room_RepExec()". Dans la fonction "room_Load()" on l'initialise, donc la durée pourrait être mise à zéro à 1 pour que l'animation se produise presque immédiatement lorsqu'on entre dans la room. Dans la fonction "room_RepExec()" on ré-initialise, donc la durée de ce timer doit tenir compte de la durée de l'animation + le délai éventuel que tu voudrais ajouter. Par exemple, s'il faut 40 pour le le perso avance d'un point A à B, et que tu veux qu'il marque un temps d'arrêt de 10, alors 40+10 = 50. Maintenant je complique : comme j'ai dit que le perso va d'un point A à B, alors si je veux boucler, je pourrai avoir besoin de 2 compteurs pour ce même perso. Il devra aller du point A à B, et je devrai le ramener au point A avant de boucler. ça donnerai ceci : - Code:
-
function room_Load() { SetTimer(1, 1); // Je le met à 1, l'évènement se déclenchera presque immédiatement SetTimer(2, 75); }
function room_RepExec() { if (IsTimerExpired(1) == true) { cPerso_1.walkTo(point B); // (à vérifier : je connais pas la fonction pour marcher d'un point à l'autre) SetTimer(3, 50); // Note que j'initialise un autre timer } else if (IsTimerExpired(3) == true) { cPerso_1.walkTo(point A); // (à vérifier) SetTimer(1, 50); // Je réinitialise le 1er timer }
if (IsTimerExpired(2) == true) { cPerso_2.Animate.... SetTimer(2, 75); // ( réinitialise le compteur 2) } } Comme tu veux que ça se déroule en arrière-plan, sans bloquer les interactions du joueur (utiliser eNoBlock), alors je crois qu'il te faut bien tout timer, puisque aucune animation ou mouvement ne sera "bloquante" dans le script, il faudrait donc tout séquencer. Est-ce que tu peux publier un extrait de ton code, et préciser ce que tu veux faire exactement ? Si tu peux décrire dans l'ordre la succession d'animations (le résultat attendu), ça aiderait bien. Par exemple : - Code:
-
- Entrée (dans la room) - Le perso 1 avance du point A au point B - Le perso 1 arrive au point B - Le perso 2 avance du point C au point D - Le perso 2 arrive au point D - Le perso 1 avance du point B au point A - Le perso 1 arrive au point A - Le perso 2 avance du point D au point C - Le perso 2 arrive au point C - boucler à l'étape 2...
Dernière édition par Clique le Dim 24 Déc 2023 - 9:02, édité 2 fois (Raison : Doc : Pass TIMEOUT as 0 to disable a currently running timer.) |
| | | Gob Adepte de la Grande Tasse Bleue
Nombre de messages : 123
Date d'inscription : 08/10/2021
| Sujet: Re: Animations lancées dans le fond pendant le jeu Sam 23 Déc 2023 - 20:01 | |
| Hello, merci pour ta réponse. Je m'en suis sorti à peu près car j'ai des persos dans la pièce qui comportent un groupe de gens, donc je lance, après timer, une longue anim qui comprend 2 ou 3 persos. Enchainer 2 anims n'est pas possible à cause du eNoBlock. Bidouiller avec deux timers pour que deux persos s'enchainent me parait bien galère. D'autant que pendant le jeu, quand on fait une action, les timers s'arrètent (ou du moins leurs conséquences), les anims d'arrière plan aussi, tout se décalerait je pense. |
| | | Clique Adepte de la Grande Tasse Bleue
Nombre de messages : 106
Date d'inscription : 11/05/2022
| Sujet: Re: Animations lancées dans le fond pendant le jeu Dim 24 Déc 2023 - 9:01 | |
| Erratum : Je vois dans la doc de SetTimer : https://adventuregamestudio.github.io/ags-manual/Globalfunctions_General.html#settimer - Citation :
- Pass TIMEOUT as 0 to disable a currently running timer.
Initialiser des timers à zéro est un truc que je faisais dans un autre langage, mais à priori dans AGS il est nécessaire qu'il soit > 0. Erratum 2 : J'avais écris elseif au lieu de else if
Je pose ça là pour complément d'info : https://adventuregamestudio.github.io/ags-manual/GameEventsOrder.html#game-events-order - Game events order a écrit:
- (..)
Following is a sequence of actions which happen in a normal game loop:
- repeatedly_execute_always function is called (if found in script).
- (since AGS 3.6.0) Game cursor position update; GUI focus is updated, depending on a new cursor position.
- Reaction to player's input (keyboard, mouse, and so on); not every action is immediate though, some things will be scheduled and put into the event queue, which is processed much later.
- Main game update: almost everything in the game is updated: characters, room objects, animations, and so forth.
- late_repeatedly_execute_always function is called (if found in script).
- Non-blocking screen shaking update (see ShakeScreenBackground).
- (prior to AGS 3.6.0) Game cursor position update; GUI focus is updated, depending on a new cursor position.
- Game is drawn on screen.
- All the scheduled events are executed. Strictly speaking, the order of execution is undefined. Commonly repeatedly_execute goes first, but that's rather a coincidence and is not recommended to rely upon. Other events include: on_key_press, on_mouse_click, on_event, and so forth (see their respective page for details).
C'est la description d'un cycle de la boucle du script principal. En gros, voici comment un timer devrait fonctionner. Note que la valeur "timeout" correspond à un nombre de tick = nombre de cycles. Ce n'est pas une unité de temps (en secondes). Normalement le jeu a une cadence de 40 ticks/sec. Dans ce cas, on peut dire qu'un timer fixé à 40 va durer 1 seconde, mais faut comprendre que c'est approximatif. En réalité le timer est un compteur qui se réduit de 1 à chaque cycle. En résumé, un timer dans AGS, c'est rien de plus qu'une variable globale à laquelle on définit un nombre (entier), auquel on soustrait 1 à chaque cycle tant que sa valeur est > 0. Je comprenais pas pourquoi le timeout n'était pas listé parmi les Event (dans AGS). Ben du coups c'est logique : c'est pas un event, c'est juste un simple compteur. Du coups, je comprends que mon 3e exemple de script risque de bug. Une fois qu'un timer est expiré il le reste et donc la clause de contrôle if (IsTimerExpired(1) == true) { va s'exécuter 40x par seconde après expiration. Par conséquent, réinitialiser le 3e timer à 50 (à chaque cycle). Je corrige ça à toutes fins utiles. - Code:
-
function room_Load() { SetTimer(1, 1); // Je le met à 1, l'évènement se déclenchera presque immédiatement SetTimer(2, 75); SetTimer(3, 0); // Je le met à 0 volontairement }
function room_RepExec() { if (IsTimerExpired(1) == true && IsTimerExpired(3) == false) { cPerso_1.walkTo(point B); // (à vérifier : je connais pas la fonction pour marcher d'un point à l'autre) SetTimer(3, 50); // Je réinitialise le 3e timer } else if (IsTimerExpired(1) == false && IsTimerExpired(3) == true) { cPerso_1.walkTo(point A); // (à vérifier) SetTimer(1, 50); // Je réinitialise le 1er timer } // éventualité où mes 2 timers auraient été désynchronisés // (je sais pas comment, mais au cas où ça arriverait) else if (IsTimerExpired(1) == true && IsTimerExpired(3) == true) { // Je les remet à leur valeur initiale dans la fonction room_Load() SetTimer(1, 1); SetTimer(3, 0); }
if (IsTimerExpired(2) == true) { cPerso_2.Animate.... SetTimer(2, 75); // ( réinitialise le compteur 2) } } Je comprends complètement cette galère. En fait, cette galère consiste à bien comprendre le cycle du script principal. À savoir où et quand les actions se produisent, les unes par rapport aux autres. Pour ma part (dans d'autres langages) j'ai mis du temps à m'y faire, mais en vrai si on a bien le cycle en tête c'est pas si complexe. Il n'y a rien qui passe à la trappe. Si c'est comme ça qu'on le perçois, ça signifie qu'on a mal organisé le truc, ou oublié d'initialiser/réinitialiser... ça demande de savoir (se) débugger, faire des tests. C'est comme des énigmes à résoudre, et pour les pires du genre où on s'acharne des heures, souvent la solution c'est le petit truc duquel on a le nez dessus depuis le début sans y prêter attention. Donc hésites pas à publier des bouts de ton code dans le forum. C'est la différence entre ce que tu essaies de faire et le résultat attendu qu'il s'agit de résoudre. Un regard extérieur peut aider à discerner le petit truc qui cloche. |
| | | Clique Adepte de la Grande Tasse Bleue
Nombre de messages : 106
Date d'inscription : 11/05/2022
| Sujet: Re: Animations lancées dans le fond pendant le jeu Dim 24 Déc 2023 - 9:48 | |
| J'ai oublié de caler ça : https://adventuregamestudio.github.io/ags-manual/Character.html#character-functions-and-propertiesSelon le cas, au lieu d'employer des timers (qui est un peu bidouille) il peut être mieux d'examiner certaines propriétés des objets/personnages utilisés dans la séquence. Par exemple, au lieu de contrôler un timer : - Code:
-
if (IsTimerExpired(1) == true) { On pourrait contrôler si un personnage animé a atteint un certain sprite de sa séquence (Dans le cas où c'est une View et une animation spécifique) - Code:
-
if( cPerso_1.View == 2 && cPerso_1.Frame >= 10 ) { Si le perso est dans sa View n°2 et a atteint (ou dépassé) la Frame n°10. L'intérêt c'est de caler l'action directement sur l'animation, plutôt que d'employer un timer comme intermédiaire. Ou bien on pourrait tester si le perso a atteint une position X/Y dans la scène. - Code:
-
if( cPerso_1.x = 50 && cPerso_1.y == 140) { Voir même contrôler les deux. Par exemple : le perso 1 se déplace à un endroit, exécute une animation sur place. En gros, la complexité de la chose, c'est d'établir une timeline de la séquence et ces points clés (même principe que le montage d'une animation). On en détermine les différentes étapes, et pour lancer chacune d'entre elles on vérifie que l'étape précédente est terminée ou dépassée. Pour simplifier une partie du contrôle, on pourrait stocker le point d'étape dans une var globale (ou sinon de la scène/Room). - Code:
-
int step; // à vérifier : comment déclarer la variable
function room_Load() { step = 0; // initialise la première étape //Juste pour préciser que dans cet exemple j'ai besoin que le point A soit aux coordonnées de départ de mon perso, puisque je veux boucler dessus. A.x = cPerso_1.x; A.y = cPerso_1.y; }
function room_RepExec() { if (step == 0) { cPerso_1.Walk(B.x, B.y, eNoBlock, eAnywhere); //Note : eAnywhere sinon il faudra bien s'assurer que la walkable areas permette au perso de se positionner sur ces coordonnées précises. step = 1; //MAJ du point d'étape } else if (step == 1) { // Attends que le perso arrive à destination //Si le perso 1 a atteint le point B if(cPerso_1.x == B.x && cPerso_1.y == B.y ) { step = 2; //MAJ } } else if (step == 2) { cPerso_1.setView(2); cPerso_1.Animate.... step = 3; //MAJ } else if (step == 3) { // Attends que le perso arrive à destination //Si le perso 1 a terminé son animation if(cPerso_1.View == 2 && cPerso_1.Frame >= 10 ) { step = 4; //MAJ } } else if (step == 4){ cPerso_1.Walk(A.x, A.y, eNoBlock, eAnywhere); step = 5; //MAJ } else if (step == 5){ //Si le perso 1 a atteint le point A if(cPerso_1.x == A.x && cPerso_1.y == A.y ) { step = 0; // MAJ: Réinitialise le point d'étape pour boucler du début } } } |
| | | Contenu sponsorisé
| Sujet: Re: Animations lancées dans le fond pendant le jeu | |
| |
| | | | Animations lancées dans le fond pendant le jeu | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |