Réorientation des Sprites

Il y a un point gênant qui traînait depuis un moment du fait que ce monstre était difficile à cerner. Le problème est que chaque POC (preuve de concept) doit être intégré proprement une fois validé, mais pour certains d’entre eux vous ne voyez pas toujours la portée de ce vous venez de faire, les impactes et incidences, ça vous arrive souvent que quand vous y êtes confronté, ce qui a été mon cas.

Premièrement je dois vous informer que j’ai divisé Element en Element et SpriteElement, car si on pense 3D, Element tel qu’il était ne convenait pas, et il doit rester la base, du coup nous avions pas mal de contenu spécifique aux POC et monde 2D (pour le POC iso), donc en résumé j’ai sorti tout le spécifique 2D dans SpriteElement, sur lequel vient s’accrocher à son tour IsoElement qui l’étend plus encore. Element quant à lui est une identité multi-dimensionnel correspondant à la fois à la 2D et à la 3D, soit XYZ (z = précédemment elevationFactor en 2D), le delta de chaque pour les animations notamment et les interactions qui ne dépendent pas de la dimension.

SpriteElement va alors se compléter avec la gestion des spriteRefs, l’orientation (on va y revenir), l’alpha que j’ai ajouté en refondant le titre pour maximiser l’usage de la librairie TARS, le getSize, les positions d’interactions, des get/set Coord adaptés au monde 2D, ce qui concerne les animations, l’update et le draw du/des sprites (spriteRefs encore) du SpriteElement et le isTouch. Pensez 2D plate, pas encore iso, donc on a des méthodes que l’IsoElement va remplacer car il induit une notion de représentation que SpriteElement n’a pas encore. Ainsi on a sous forme d’étage une complétion structurelle cohérente.

Pour les curieux, IsoElement contient des méthodes comme le draw, isTouch et l’update comme cités avant mais remplacées, ainsi qu’une fonction de rotation, c’est tout. 🙂 Simple, basique, toussa.

Pour revenir à l’orientation, la problématique est simple, le POC se déroule en isométrique avec 4 directions, résumées sous la forme NESW (North, East, South, West), vous aurez compris 😉 (j’espère). Du coup, vu que nous traitons en interne des caractères ‘n’, ‘e’, ‘s’ et ‘w’, comment savoir qui est à l’est du nord de l’objet ? Comment connaître la coordonnée au nord de l’objet ? Au final 2 questions qui deviendront 5 réponses, on en reparle plus tard. En gros, pendant plusieurs mois, suite au développement du déplacement et de la réorientation, le code était dans l’actuel SpriteElement et anciennement dans Element.

Si maintenant je vous demande, avec TARS, de faire un jeu de plateforme 2D latéral ce que je viens de vous dire déconnera plein tube car vous avez un 2D isométrique en dur dans Element, hors à la base c’est l’idée, « être capable de tout ».

« Être capable de tout »

TARS

On a donc un soucis connu, le système d’orientation n’a pas sa place à cet endroit. On peut même imaginer un personnage se déplaçant en 8 directions sur un environnement isométrique en 4 directions, tout à fait réaliste. Donc on se trouve au niveau de Element comme dit, on sait qu’on est au bon endroit mais pas de la bonne manière, ni de manière flexible/variable.

Je vous passe la réflexion interminable, la solution est un service sur mesure, donc une Factory (une classe qui vous donne la bonne selon critère). J’ai donc crée SpriteFactoryService qui donne accès à SpriteOrientationSystem (lol) basé sur un critère simple : combien de direction veux-tu pour cet Element, que j’ai nommé SpriteOrientationType et vous donne accès à une liste du style SO0, SO2, SO4, etc. En gros, une image plate, une image plate qui va à gauche ou droite, une image ayant 4 directions quelque soit le système de rendu, 2D haut, 2D iso, etc. Le résultat nous donnera une classe SpriteOrientation0, SpriteOrientation4, etc.

On a donc l’actuel SpriteElement qui demande ce fameux service et selon sa configuration passée au type de l’Element, on a la DTD qui donne des infos générales et s’initialise. On peut désormais avoir un SpriteElement en 2 directions à côté d’un autre en 4 directions etc. C’est la même classe, avec un service sur mesure. Le tout est cadenassé par une interface bien sur (modèle à respecter), ce qui garanti que SpriteElement peut travailler avec n’importe quel système de SpriteOrientation.

Je vous ai épargné beaucoup de détails car au final c’est +17 fichiers qui ont été impactés, adaptés, corrigés et nettoyés. Une aventure difficile mais dont je suis content d’être sorti avec une certaine élégance dans le résultat.

Après ces développements et tentatives de diminuer les TODOs présents, de +40 on est passé à 31, ce qui permet de respirer un peu et de voir de l’avancement, même si rien de nouveau en visuel.

À propos de visuel, l’éditeur avait un peu avancé avant tout ça, voici une capture. En gros, le chargement de scène fonctionne, la suppression d’un Element aussi, la rotation selon molette de souris et si l’Element le permet, fonctionne. J’ai également ajouté la notion des Zones du gridBlock que vous voyez sous la forme BCTNESW avec le C de ‘center’ sélectionné et j’ai ajouté une sélection, que vous voyez en fuchsia pointillé, fonctionnelle mais ne rend pas encore la sélection sur base du filtre de Zones.

Évidemment, tout ceci a permis de découvrir des problèmes, d’amender certains points pour les rendre accessible ou carrément meilleur.

J’avais tenté une sélection multiple d’objets du catalogue pour préparer un pinceau dynamique mais la manière n’était pas optimale. L’idée sera plutôt d’avoir un onglet spécifique aux outils permettant en leur sein d’avoir des options à choisir, via des listes et autres. Par exemple, vu qu’on est un éditeur pour HeroQuest, on peut imaginer un outil « création de pièce » avec en option, « quel mur et sol voulez vous« , on peut sélectionner plusieurs sols et jouer sur un aléatoire de style et de rotation si coché par exemple. Je pense que c’est une meilleure approche.

Je vais déjà tenter de faire un ajout simple puis on verra les outils plus avancés. Quand je dis « tenter », le truc n’est pas compliqué, mais il faut penser à beaucoup de chose avant de se lancer et de devoir recommencer. Ce qui a donné tous ces développements depuis la dernières fois en gros, même si parfois très indirect.

L’idée futur proche reste la diminution des TODOs pour être stable et propre et l’ajout dans l’éditeur. Vu que nous sommes en DEV nous utilisons un dataProvider Fake (faux) qui renvoie des données brutes stockées localement en JSON (et non venant d’un serveur comme cela sera à terme), ce qui veut aussi dire que la partie sauvegarde du résultat de l’éditeur ne peut pas se faire. J’imagine passer par la console pour avoir une sortie texte brute à mettre moi-même dans un fichier local, ce n’est que temporaire et pour contrôler de toutes façons. On sait ce que temporaire signifie…

On est de plus en plus proche d’un résultat exploitable pour commencer le POC du jeu HeroQuest comme dit, il faudra penser la mécanique manquante des actions au sein d’une Scene déplaçant le joueur d’une Scene à une autre, maîtriser d’un point de vue macro l’ensemble du processus de jeu au delà des limites des Scenes. Typiquement le joueur arrive en début de donjon et doit aller à la fin, le fait de toucher la case ou d’interagir avec le fait quitter le donjon pour aller en zone neutre avant d’attaquer un nouveau donjon. Le tout sans perdre l’état du joueur, ses découvertes et équipements.

Et là je n’ai pas encore parlé de la problématique organisationnelle que ceci est un POC dans un POC, la librairie TARS se doit d’être séparée dans un module spécifique, versionné et récupérable au travers d’un projet NPM propre. Ce qui n’a pas l’air évident du tout.

Que ça soit en mode « player » ou en « editor » on a encore du boulot. 🙂