En y réfléchissant, je pense avoir trouvé une idée pour déplacer l'ombre seulement quand on change de frame dans l'animation de marche.
Bon, échec complet : l'ombre prend régulièrement du retard sur le personnage quand elle marche.
Et quand elle s'arrête, l'ombre se retrouve parfois posée à côté.
Je trouve pas de méthode autre qu'une boucle pour caler précisément la position de l'ombre sur celle du personnage.
Si l'un de vous a une idée (pas trop compliquée sinon je ne pourrai pas la mettre en oeuvre), elle est la bienvenue.
En attendant, j'ai modifié le code de ma boucle pour l'améliorer (j'espère) :
La grosse différence, c'est que j'ai ajouté une boucle dans ma boucle pour la mettre en pause tant que le personnage n'a pas repris sa marche.
Donc en résumé :
Quand le personnage marche, l'ombre s'aligne toutes les 10 ms sur sa position.
Quand le personnage s'arrête, l'ombre correspondante s'affiche (SetSprite) puis la boucle se met en pause jusqu'à ce qu'on recommence à marcher.
Donc SetSprite et SetSprite(null) ne sont exécutés qu'une seule fois quand nécessaire et pas toutes les 10 ms.
Ca devrait éviter le risque dont parle conceptgame avec les SetSprite.
Vous en pensez quoi ?
C'est mieux ? C'est pire ?
En fait c'est l'idée même de faire une boucle que je trouve étrange. Car la boucle sert à "corriger" l'erreur de position constante de l'ombre qui est due aux déplacements de Mizuka. Du coup, ne vaut-il mieux pas prévenir que guérir et donc, au lieu de devoir toujours corriger l'ombre, tout simplement faire en sorte qu'elle se déplace réellement en même temps que Mizuka ?
Tu as le switch case qui te permet d'orienter ton ombre par rapport à l'orientation de Mizuka, mais tu as du coup forcément le même pour Mizuka elle-même. Tu ne peux pas ordonner à deux éléments (ombre et Mizu) de se déplacer là où le joueur clique ? Si les deux éléments débutent à la même position, et bougent à la même vitesse pour aller au même endroit, ils seront constamment en train de se suivre comme s'ils n'en formaient qu'un, mais restent en réalité indépendants (ce qui permet de faire par exemple varier l'opacité de l'ombre uniquement, etc). Et même en s'arrêtant en cours de route si on désigne une autre position, ils vont continuer à se suivre.
En gros, si Mizuka va en X et Y, l'ombre va en X et Y-3 dans la même série d'instruction de déplacement. Et au pire du pire, si tu as peur que l'ombre s'éloigne, c'est au moment où Mizuka s'arrête que là tu fais une correction, au cas où vraiment par malheur celle-ci s'était décalée. Mais tu n'as qu'une correction à faire, et pas 100 à la seconde.
Après je ne dis tout ça que vu de loin et surtout dans la logique algorithmique globale. Je ne sais pas si d'autres actions sur le reste du code sont faciles à faire et j'imagine que la répartition des bouts de code étant du scripting, il y'a du code un peu partout et non regroupé en un bloc.
L'idée est bien de minimiser le nombre de rendus au minimum. Pour moi, il y a deux choses qui peuvent être améliorées:
- éviter de repositionner l'ombre en permanence. Elle a juste besoin d'être repositionnée lorsque la position de Mizuka est différente. Pas vraiment besoin de la latence de 10ms.
Du genre, if(shadow_miz.X!=actor.X || shadow_miz+3!=actor.Y) alors repositionner. Pour certains moteurs de rendu, bouger un sprite même c'est sur la même position va refaire le rendu ce qui est inutile.
- Seulement changer la direction de l'ombre lorsque celle de Mizuka est modifiée. Tu l'as fait partiellement mais ce n'est pas encore optimal.
Enfin si ce script est appelé à chaque boucle du moteur de Wintermute, tu n'as pas besoin du while.
@Seldell: Sur le principe, je suis d'accord avec toi. Cependant suivant le moteur de jeu, ce genre de choses peut donner des résultats indésirables dans la gestion des collisions, comme des sprites qui font des bonds.
Je ne sais pas si c'est le cas pour Wintermute.
Concept : si tout est fait par rapport à Mizuka en tant que sprite principal gérant les collisions, l'ombre ne devrait pas être impactée puisque n'étant qu'une image sans hitbox. Non ? Donc si Mizuka s'arrête, l'ombre s'arrêta aussi... A moins que l'ombre, elle, continue à bouger jusqu'au point, contrairement à Mizuka ? Y'a pas moyen d'avoir une espèce d'alerte quand Mizuka s'arrête en rencontrant un obstacle, dans laquelle on signale l'arrêt à l'ombre pour se synchroniser ?
La grosse difficulté, c'est que Mizuka ne se déplace pas avec une vitesse moyenne (par ex : 30px par seconde).
Quand on crée le sprite, à chaque frame, on calcule où se situera le pied porteur par rapport à sa position dans la frame précédente.
Voici en exemple de combien elle se déplace quand elle marche en profil face vers la droite :
frame 1 : x+37, y+12
frame 2 : x+92, y+54
frame 3 : x+38, y+8
frame 4 : x+85, y+20
...
Ca me semble compliqué : pour homogénéiser, il faudrait que je configure l'ombre avec les mêmes données, c'est-à-dire le déplacement frame par frame dans les 8 directions...
Puis espérer que le pathfinding des deux éléments soient le même alors même que leurs coordonnées de départ et d'arrivé sont sensiblement différentes (y+3).
Bref tout ça, c'est peut-être un peu trop compliqué pour moi...
J'ai une préférence pour la boucle car elle me semble infaillible.
Ha punaise oui, je ne prenais pas du tout en compte le pathfinding en effet... Je considérais des déplacements en ligne droite. Oui du coup ça semble compliqué, tu as raison... La boucle est sans doute plus simple.
L'idée est bien de minimiser le nombre de rendus au minimum. Pour moi, il y a deux choses qui peuvent être améliorées:
- éviter de repositionner l'ombre en permanence. Elle a juste besoin d'être repositionnée lorsque la position de Mizuka est différente. Pas vraiment besoin de la latence de 10ms.
Du genre, if(shadow_miz.X!=actor.X || shadow_miz+3!=actor.Y) alors repositionner. Pour certains moteurs de rendu, bouger un sprite même c'est sur la même position va refaire le rendu ce qui est inutile.
- Seulement changer la direction de l'ombre lorsque celle de Mizuka est modifiée. Tu l'as fait partiellement mais ce n'est pas encore optimal.
Enfin si ce script est appelé à chaque boucle du moteur de Wintermute, tu n'as pas besoin du while.
Très bonnes idées !
Je vois ce que tu veux dire et ça me semble parfaitement approprié !
Aujourd'hui je fais un break (j'ai l'impression d'être enfermé dans une boucle, maintenant !) mais je teste ça dès demain.
Je posterai le code pour savoir si c'est OK.
Merci à tous pour vos conseils et vos commentaires !
La grosse difficulté, c'est que Mizuka ne se déplace pas avec une vitesse moyenne (par ex : 30px par seconde).
Quand on crée le sprite, à chaque frame, on calcule où se situera le pied porteur par rapport à sa position dans la frame précédente.
Voici en exemple de combien elle se déplace quand elle marche en profil face vers la droite :
frame 1 : x+37, y+12
frame 2 : x+92, y+54
frame 3 : x+38, y+8
frame 4 : x+85, y+20
...
Ca me semble compliqué : pour homogénéiser, il faudrait que je configure l'ombre avec les mêmes données
Comment est codé ce déplacement irrégulier du sprite?
Perso, tu temps où je codais un peu (ça remonte ^^), j'utilisais des tableau pour ce genre de chose, par exemple:
Après il ne reste qu'à utiliser une routine simple du genre:
Dans ce type de procédé, rajouter une ombre fonctionnant selon les mêmes décalages x/y me parait simple car tu as déjà toutes les données dans le tableau, et ce tableau permet de prendre en compte toute les particularités que tu veux par frame tout en utilisant toujours la même ligne de code (juste en faisant varier la variable qui correspond à la frame en cours par une "bête" incrémentation).
Bon après c'est une idée peut-être idiote vue depuis Wintermute, ou alors idiote tout court parce que je n'ai pas saisi les enjeux ^^.
(Ça fait 10 ans que je n'ai pas taper un code je crois bien, alors j'uis ptêt à coté de la plaque.... :P)
En fait il y a même une autre subtilité que j'intégrais très souvent dans ce genre de cas:
en 4ème colonne du tableau tu mets le numéro de ligne correspondant à la frame suivante (donc 2 pour la frame 1, 3 pour la frame 2, etc. ...mais 1 pour la frame 8), ça permet de virer le si frame_d_animation > 8, alors frame_d_animation = 1
et de le remplacer par un simple: frame_d_animation = tableau_d_anim [ frame_d_anim ; 4]
En fait quand je codais je m'efforçais de virer à peu près tous les if possibles en utilisant ce genre de technique, parce que si on se laisse aller à la "facilité" que représente les conditions, on finit parfois par avoir des if en cascade avec des temps d'exécution de routine qui deviennent incontrôlables, et de toute façon inutilement longs.
Bon, échec complet : l'ombre prend régulièrement du retard sur le personnage quand elle marche.
Et quand elle s'arrête, l'ombre se retrouve parfois posée à côté.
Je trouve pas de méthode autre qu'une boucle pour caler précisément la position de l'ombre sur celle du personnage.
Si l'un de vous a une idée (pas trop compliquée sinon je ne pourrai pas la mettre en oeuvre), elle est la bienvenue.
En attendant, j'ai modifié le code de ma boucle pour l'améliorer (j'espère) :
La grosse différence, c'est que j'ai ajouté une boucle dans ma boucle pour la mettre en pause tant que le personnage n'a pas repris sa marche.
Donc en résumé :
Quand le personnage marche, l'ombre s'aligne toutes les 10 ms sur sa position.
Quand le personnage s'arrête, l'ombre correspondante s'affiche (SetSprite) puis la boucle se met en pause jusqu'à ce qu'on recommence à marcher.
Donc SetSprite et SetSprite(null) ne sont exécutés qu'une seule fois quand nécessaire et pas toutes les 10 ms.
Ca devrait éviter le risque dont parle conceptgame avec les SetSprite.
Vous en pensez quoi ?
C'est mieux ? C'est pire ?
Merci Edryl !
En fait c'est l'idée même de faire une boucle que je trouve étrange. Car la boucle sert à "corriger" l'erreur de position constante de l'ombre qui est due aux déplacements de Mizuka. Du coup, ne vaut-il mieux pas prévenir que guérir et donc, au lieu de devoir toujours corriger l'ombre, tout simplement faire en sorte qu'elle se déplace réellement en même temps que Mizuka ?
Tu as le switch case qui te permet d'orienter ton ombre par rapport à l'orientation de Mizuka, mais tu as du coup forcément le même pour Mizuka elle-même. Tu ne peux pas ordonner à deux éléments (ombre et Mizu) de se déplacer là où le joueur clique ? Si les deux éléments débutent à la même position, et bougent à la même vitesse pour aller au même endroit, ils seront constamment en train de se suivre comme s'ils n'en formaient qu'un, mais restent en réalité indépendants (ce qui permet de faire par exemple varier l'opacité de l'ombre uniquement, etc). Et même en s'arrêtant en cours de route si on désigne une autre position, ils vont continuer à se suivre.
En gros, si Mizuka va en X et Y, l'ombre va en X et Y-3 dans la même série d'instruction de déplacement. Et au pire du pire, si tu as peur que l'ombre s'éloigne, c'est au moment où Mizuka s'arrête que là tu fais une correction, au cas où vraiment par malheur celle-ci s'était décalée. Mais tu n'as qu'une correction à faire, et pas 100 à la seconde.
Après je ne dis tout ça que vu de loin et surtout dans la logique algorithmique globale. Je ne sais pas si d'autres actions sur le reste du code sont faciles à faire et j'imagine que la répartition des bouts de code étant du scripting, il y'a du code un peu partout et non regroupé en un bloc.
Trop de stress pour un si petit renard.
L'idée est bien de minimiser le nombre de rendus au minimum. Pour moi, il y a deux choses qui peuvent être améliorées:
- éviter de repositionner l'ombre en permanence. Elle a juste besoin d'être repositionnée lorsque la position de Mizuka est différente. Pas vraiment besoin de la latence de 10ms.
Du genre, if(shadow_miz.X!=actor.X || shadow_miz+3!=actor.Y) alors repositionner. Pour certains moteurs de rendu, bouger un sprite même c'est sur la même position va refaire le rendu ce qui est inutile.
- Seulement changer la direction de l'ombre lorsque celle de Mizuka est modifiée. Tu l'as fait partiellement mais ce n'est pas encore optimal.
Enfin si ce script est appelé à chaque boucle du moteur de Wintermute, tu n'as pas besoin du while.
Conceptgame
@Seldell: Sur le principe, je suis d'accord avec toi. Cependant suivant le moteur de jeu, ce genre de choses peut donner des résultats indésirables dans la gestion des collisions, comme des sprites qui font des bonds.
Je ne sais pas si c'est le cas pour Wintermute.
Conceptgame
Concept : si tout est fait par rapport à Mizuka en tant que sprite principal gérant les collisions, l'ombre ne devrait pas être impactée puisque n'étant qu'une image sans hitbox. Non ? Donc si Mizuka s'arrête, l'ombre s'arrêta aussi... A moins que l'ombre, elle, continue à bouger jusqu'au point, contrairement à Mizuka ? Y'a pas moyen d'avoir une espèce d'alerte quand Mizuka s'arrête en rencontrant un obstacle, dans laquelle on signale l'arrêt à l'ombre pour se synchroniser ?
Trop de stress pour un si petit renard.
La grosse difficulté, c'est que Mizuka ne se déplace pas avec une vitesse moyenne (par ex : 30px par seconde).
Quand on crée le sprite, à chaque frame, on calcule où se situera le pied porteur par rapport à sa position dans la frame précédente.
Voici en exemple de combien elle se déplace quand elle marche en profil face vers la droite :
frame 1 : x+37, y+12
frame 2 : x+92, y+54
frame 3 : x+38, y+8
frame 4 : x+85, y+20
...
Ca me semble compliqué : pour homogénéiser, il faudrait que je configure l'ombre avec les mêmes données, c'est-à-dire le déplacement frame par frame dans les 8 directions...
Puis espérer que le pathfinding des deux éléments soient le même alors même que leurs coordonnées de départ et d'arrivé sont sensiblement différentes (y+3).
Bref tout ça, c'est peut-être un peu trop compliqué pour moi...
J'ai une préférence pour la boucle car elle me semble infaillible.
Ha punaise oui, je ne prenais pas du tout en compte le pathfinding en effet... Je considérais des déplacements en ligne droite. Oui du coup ça semble compliqué, tu as raison... La boucle est sans doute plus simple.
Trop de stress pour un si petit renard.
Très bonnes idées !
Je vois ce que tu veux dire et ça me semble parfaitement approprié !
Aujourd'hui je fais un break (j'ai l'impression d'être enfermé dans une boucle, maintenant !) mais je teste ça dès demain.
Je posterai le code pour savoir si c'est OK.
Merci à tous pour vos conseils et vos commentaires !
Comment est codé ce déplacement irrégulier du sprite?
Perso, tu temps où je codais un peu (ça remonte ^^), j'utilisais des tableau pour ce genre de chose, par exemple:
Après il ne reste qu'à utiliser une routine simple du genre:
Dans ce type de procédé, rajouter une ombre fonctionnant selon les mêmes décalages x/y me parait simple car tu as déjà toutes les données dans le tableau, et ce tableau permet de prendre en compte toute les particularités que tu veux par frame tout en utilisant toujours la même ligne de code (juste en faisant varier la variable qui correspond à la frame en cours par une "bête" incrémentation).
Bon après c'est une idée peut-être idiote vue depuis Wintermute, ou alors idiote tout court parce que je n'ai pas saisi les enjeux ^^.
(Ça fait 10 ans que je n'ai pas taper un code je crois bien, alors j'uis ptêt à coté de la plaque.... :P)
En fait il y a même une autre subtilité que j'intégrais très souvent dans ce genre de cas:
en 4ème colonne du tableau tu mets le numéro de ligne correspondant à la frame suivante (donc 2 pour la frame 1, 3 pour la frame 2, etc. ...mais 1 pour la frame 8), ça permet de virer le
si frame_d_animation > 8, alors frame_d_animation = 1
et de le remplacer par un simple:
frame_d_animation = tableau_d_anim [ frame_d_anim ; 4]
En fait quand je codais je m'efforçais de virer à peu près tous les if possibles en utilisant ce genre de technique, parce que si on se laisse aller à la "facilité" que représente les conditions, on finit parfois par avoir des if en cascade avec des temps d'exécution de routine qui deviennent incontrôlables, et de toute façon inutilement longs.
Pages