lundi, juillet 13, 2009

Les plate-formes


Le prochain "gros challenge" pour mon moteur de jeu (sur lequel je cogite actuellement, en tout cas), c'est sans hésitation les plate-formes. Tous ces objets mobiles, assenceurs, radeaux, etc. qui tout en ayant leur comportement propre altèrent celui du personnage ou agissent comme des parois solides. Bref tout une série d'objets qui vont venir perturber les belles règles de gestion des collisions du moteur de jeu.
Technically speaking, the next challenge for my game engine is platforms. Those moving objects you'll find in any decent platformer that have their own pattern and that alter the player's behaviour (and sometimes ennemies' as well) to create interesting levels and gaming experience. It's still very sketchy in my mind, in "look for use cases" stage that happens to take place by drawing gaming moments in this project -- fairly funnier than rationale UML, if you ask ;)

J'en suis encore fort au stade "conceptuel", qui est franchement sympa dans ma manière de travailler, puisqu'il s'agit de "mises en situations" à coup de crayon pour voir si la solution que j'ébauche tient suffisamment compte des différents aspects. Du style "non, on ne peut pas lier définitivement un contrôleur à une plate-forme, parce qu'il pourrait y avoir aussi des petits vers sur les champignon-ascenseurs".

Après deux ou trois tentatives peu convaincantes, j'en arrive à la conclusion que mon système "un contrôleur par état" est un peu limitatif. De la même manière que j'essaie de faire de la composition de micro-programme dans mes recherches sur les protocoles réseaux, pourquoi ne pas faire de la composition de contrôleurs dans le moteur de jeu ?

Encore trop tôt pour commencer à faire des changements dans le code, mais on dirait bien que ce genre de mécanisme qui transforme la fonction de contrôle unique en "lire_le_pad -> pousser_un_objet -> suivre_une_pente -> marcher" s'appliquerait aussi bien aux objets déplaçables ou aux pentes fixes (en plus des plate-formes mobiles). Le même micro-comportement "marcher" pourrait prendre comme "input" la lecture du pad directionnel ou la position relative de Bilou par rapport à un appleman ...

Plein de choses intéressantes, donc, que je continuerai à creuser dès que j'aurai un peu dompté la forêt vierge qui me sert de jardin.

The thinking about supporting moving platforms also questions the way i'm coding controllers, that is, a large chunk of code that does everything a specific state needs, including reading Dpad, adjusting speeds, checking that the current move is possible and make it possible if speeds need to be aligned to avoid entering walls. Such an approach doesn't let me easily alter behaviour due to a lift or a pushable ennemy.

Instead, i'll investigate the option of a chain of controllers, each of them doing only a simple action such as reading the pad, or updating speeds according to momentum. It could also be "zero speed if character pushes into the moving block's direction" or "prevent the character from falling as long as he's on a platform". Still a bit early to change all the code base, but ...

3 commentaires:

cyborgjeff a dit…

agréable comme réflexion :)

Uldéric a dit…

Ah les plate-formes, une bonne prise de tête pour trouver la méthode à utiliser.

Pour les micro-comportements, j'ai des doutes sur leur application à tout les élements du jeu. Par exemple, "suivre une pente", si jamais un ennemi à besoin lui aussi de suivre une pente, il faudra re-coder une variante pour cette entité en particulier ?

Je n'ai pas encore implémenté la gestion des plate-formes dans mon jeu mais j'ai une petite idée de la méthode que je vais utiliser pour les implémenter.

Mon moteur physique c'est séparé en deux parties, les collisions avec la map (avec des test points) et les collisions avec des corps (principalement des AABB). Le problème est que pour que le héros entre en collision avec une plateforme, il me faut relier les deux moteurs. Pour faire ça, j'ai pensé à ajouter une partie dans la fonction GetMapPixel(x, y). Dans celle-ci, il me faudra itérer parmi tout les corps solides de la map et de retourner un pixel noir si jamais il y a un corps à cet endroit. Ainsi, toutes les entités du monde pourront se déplacer indifféremment sur la map et sur les plate-formes.

Le seul souci est d'évaluer l'impact que cela aura sur les performances, en effet, pour chaque test point, il faudra itérer parmi tout les body à l'écran. Ce qui pourrait se révéler être gourmand.

sylvainulg a dit…

Justement, l'intérêt des micro-comportements, c'est qu'ils décrivent une action élémentaire, qui peut être partagée par un grand nombre d'entité. Le déplacement du personnage enchaine "lire-le-pad" puis "suivre une pente" alors qu'un ennemi enchaînerait plutôt "se déplacer vers le héro" puis "suivre une pente".

Dans les derniers développements, j'ai fini par laisser tomber l'approche dont tu parles pour GetMapPixel() au profit d'un "masque d'actions impossibles". Pour qu'un objet puisse tomber, par exemple, il faut que gob->cando(FALLTHRU) renvoie true. Si je détecte la collision perso-plateforme, je peux faire hero->setmask(~FALLTHRU) de sorte que lors de l'évaluation des comportements, cando(FALLTHRU) renvoie toujours faux.

Mais bon, je détaillerai un peu plus quand j'aurai codé ça.