Monday, December 02, 2013

The art of Blading

For g88 release, carrying bladors was functionally correct, but still a bit cheap, as the carried blador could move through walls, ceilings and such. It would be an acceptable simplification of physic rules in-game if that did not meant you could "throw" it while it overlap solid structures, which would let it "stuck" there as soon as regular physics takes over to let it be thrown away. I want the game to feel professional, and demonstrate that a simple scripting approach does not imply half-baked behaviours. It's thus time to prove it.

Un taille-crayon qui passe à travers tout pour qu'on puisse le lancer n'importe où, ce n'est pas très réaliste, mais c'est acceptable dans un jeu vidéo. Un taille-crayon qui reste bloqué dans un mur quand on le lance, ça, ça fait tache. Surtout quand le joueur aurait théoriquement dû pouvoir le ramasser et l'emporter plus loin. Premier pas pour corriger ça, interdire à mon taille-crayon de passer à travers les murs (ce qui demandait un réglage spécifique du contrôleur freemove). Résultat: Blador suit maintenant Bilou "de son mieux", ce qui amène parfois des résultats curieux comme un saut quantique à travers un mur contre lequel il est resté scotché pendant 15 secondes lorsque Bilou émerge enfin d'un passage secret.

The first step is to make blador using freemove(1) instead of using freemove(0) when carried. Freemove is the controller that allows free movement typical from airborne ennemies such as the berrybat. The only thing it does before validating the desired movement is checking that you cando(m) where m describe some properties of the environment - like being something you can MOVETHRU. 0 is considered as a special case where you can always do what you want -- perfect for ghosts or sparkles that will fall of the screen. So now, blador can't get into walls, but curious things occur when Bilou gets into narrow passages where Blador cannot follow: Blador just sits where it is, and if at some point Bilou reaches a new position where Blador could fit above its head, Blador gets quantumagically teleported to that new location (yes, again).

Pour corriger ça, il faut que Bilou puisse être informé de la situation du Dumblador qu'il transporte. En '97 j'avais donc pensé augmenter mon "ulitmate game maker" d'un système de messagerie entre les personnages. En fait, ici, on va faire beaucoup plus simple: tout comme l'encrier possède une zone-test (hitbox) qui repousse Bilou lorsque celui-ci l'approche, le Dumblador transporté va disposer de murs invisibles qui empècheront Bilou de s'en éloigner de trop tant qu'il le transporte. Eh oui: c'est aussi simple que ça.

Enfin, presque. Il y a quand-même une subtilité dans le cas du saut. Si je me contente de forcer Bilou à faire du sur-place au milieu d'un saut juste parce qu'un taille crayon a la tête dans le plafond, ça fout en l'air la crédibilité de la physique du jeu pour donner un effet Badman/RSD Game-Maker carrément pathétique. Il faudra donc que je traite cette collision aussi du côté de Bilou en forçant une remise à zéro de la vitesse, exactement comme le contrôleur "gravity" l'aurait fait si on s'était vraiment retrouvé directement dans un mur.

I like how Bilou/Blador distance is stretched or squished when colliding the environment, but I need more control over it. And that's just a perfect fit for the "repel" action introduced with solid inkjets. To avoid having Bilou going too far away from the carried Blador in a narrow tunnel, I just need some repelling-areas acting as virtual walls at appropriate distance from its position.
The same approach allows Blador to take some room between Bilou and the ceiling, but here I need some additional action. "Repelling" simply adjusts coordinates and does not affect speed. The result was that Bilou would keep floating along the ceiling as if he virtually kept jumping. Even weirder: he might have resumed moving up as soon as he'd have moved away from what was blocking Blador (just as in Badman II, actually).
To avoid this, Bilou needs to react on the collision and clear vertical speed. Additional tests are needed to ensure the blocking object (active GOB) is indeed over Bilou's head and that he's still moving upwards. The center-to-center distance (dy) is available through GobScript wf variable read and is positive when the active object is above the passive object (and yes, the sign of dx and dy is related to passive/active roles as the distance is defined only once, and then reused in both passive and active objects transitions).


Il me reste donc "simplement" à corriger l'ordre d'affichage de Bilou et du dumblador (tant qu'à faire, prenons-le en mode "hotte de père Noël" plutôt que "Sac de courses devant le nez") et à m'assurer que les mains de Bilou apparaissent sur le taille-crayon pendant qu'on transporte le crayon.

It leaves me with one last aspect to fix: having Bilou's hand properly shown as grabbing the blador while it is carried, knowing that hands will have to be aligned with blador rather than with Bilou if we want to keep stretch/squish.

5 comments:

cyborgjeff said...

C'est bizarre, j'ai parfois l'impression que les choses sont fort complexes dans toutes tes méthodes de gestions des ennemis. Bien entendu, je ne connais au fond que ce que l'on faisait avec GameMaker qui était franchement pas terribles... mais je me demande comment fonctionnait la gestion des ennemis dans un Zool, Sonic, Mario, Moktar, Keen... ou maintenant.

Ils semblent tous relativement bien comprendre où ils peuvent aller et ne pas aller, s'ils peuvent ou pas tomber des plateformes...

Par exemple, si je prends un de tes crayons qui se promène sur les plateformes en haut. Ils ont des infos qui les limites aux déplacements sur la plateforme en question. Si dans l'éditeur tu réduits la plate-forme, ou que tu fais un trou au milieu, comment se comporte ton crayon ?

Si par je ne sais qu'elle action, Bilou arrive à faire tomber le crayon dans les plateformes du bas, comment va-t-il se déplacer ?

bon, tu en as déjà probablement parlé à d'autres endroits, mais voyant toute la recherche que tu fais à ce sujet, je me pose la question !

PypeBros said...

J'admets volontiers que les choses sont complexes dans mon approche, notamment parce que je fais des monstres sophistiqués et que je ne les fais pas avec du code brut.
Dans Keen, par exemple, quand tu assomes un ennemi, tu l'assomes pour de bon. Il n'y a non plus aucun ennemi-sauteur qui font partie des plus complexes à gérer.

Dans Mario, les ennemis ne deviennent actifs qu'une fois qu'ils sont assez proches de la caméra. Dans les Mario où le retour en arrière est autorisé, l'ennemi revient "magiquement" à sa position d'origine si on le fait sortir de l'écran puis qu'on revient à son origine.

Le crayon sur sa plate-forme élevée n'a pas a priori d'infos sur sa plate-forme. Tout simplement, quand il s'approche d'un bord, il fait demi-tour. (le test reste à faire en live, puisque pour l'instant, les crayons sont assomés définitivement, contrairement aux taille-crayons). Il s'adaptera donc aux modifications de l'éditeur ou à une nouvelle plate-forme s'il tombe et se réveille dessus, de même que les gommes qui évitent normalement de sauter dans les trous peuvent être amenées à changer de plate-forme lorsque Bilou transforme le niveau.

Dans Rayman, il y a un type de bloc "mur invisible pour ennemis" qui est régulièrement utilisé pour que les plate-formes ou que les anti-toons restent en place.

Au niveau du porté d'objets, Moktar utilisait deux raccourcis commodes pour éviter toute cette complexité: les caisses réagissaient avec un temps de retard (partant légèrement vers l'arrière du personnage quand il se met en mouvement, puis revenant à leur place lorsqu'il s'arrète -- même problème qu'avec les plate-formes de Zool, donc). En plus, la caisse qui est portée au-dessus de la tête du perso est lancée à hauteur de regard et passe à travers tout là où les taille-crayons de Bilou sont interrompus par les murs. Si tu te souviens bien, par contre, il était possible dans Moktar de déposer certains objets "à cheval" sur un mur (les boules-sauteuses, notamment) produisant alors des effets assez curieux. C'est la bagarre contre ce genre d'effet indésirables qui rend les choses parfois curieusement difficiles à gérer.

PypeBros said...

Au passage, si on s'est émerveillé sur le fait que les "vorticons" assomés (en fait, les slugs) tombaient des plate-formes quand on les désactivaient, ça marchait beaucoup moins bien quand le-dit slug était encore actif.

PypeBros said...

Par curiosité, j'ai été jeter un oeil du côté d'OpenTitus ... On est pas loin des 400 lignes de code pour gérer les objets à transporter, auxquelles il faut rajouter le support de chaque type d'ennemi dans le jeu. Il s'agit ici de code machine, pas de structures de données interprétées, donc impossible d'ajouter de nouveaux types d'ennemis même avec un éditeur de jeu adapter: on ne peut que changer le costume des comportements déjà existant (transformer une boule de feu en goutte de pétrole, p.ex.)

cyborgjeff said...

oki, je comprends mieux toute la réflexion et l'approche face à ces éléments !