lundi, février 08, 2010

{ using decrease(v0 by 4 to 100) ...

Quand j'ai commencé à réimplémenter le comportement de l'appleman pour la version DS de Bilou, j'avais dans l'idée de lui permettre un "boost de vitesse" pour prendre Bilou en chasse tout en gardant son côté lourdaud, ç.à.d. en limitant le temps pendant lequel la chasse en question pouvait durer. Jusqu'ici, seul le premier aspect était programmé, et je viens assez facilement d'ajouter le deuxième. Au niveau du gamescript, ça se limite à la ligne qui figure dans le titre (dans la description d'un état) et une transition supplémentaire "courir->marcher on event".

The appleman 'revived' on the NintendoDS through a small animation that showed him "walking, shocked, running, slowing down, walking again". So far, it was mostly running ahead until it encountered a wall or a cliff -- not very compatible with its clumpsy nature. A small additional line in the gamescript and a supporting "controller" class in the C++ code base did the trick in half the time I need to relate it, so let us check the code which speak for itself:

Au niveau du game engine, celà passe par la définition d'un contrôleur supplémentaire qui diminue une des variables (ici v0, la vitesse horizontale) jusqu'à atteindre un seuil donné (100, la vitesse de marche de l'appleman au repos). A ce moment un "évènement" est généré et le moteur de jeu parcours les transitions associées avec l'état actuel.

iThought DecreaseController::think(s16 gob[8], GameObject *g) {
iThought me = NONE;
if (gob[varno]<0) {
gob[varno]+=step;
if (gob[varno]>-threshold) {
gob[varno]=-threshold; me=EVENT;
}
} else {
gob[varno]-=step;
if (gob[varno]<threshold) {
gob[varno]=threshold; me=EVENT;
}
}

return combine(me, gob, g);
}
auquel se rajoute un petit code de parsing :
iGobController* GobDecreaseFactory::create(char* args) {
int v=0, s=1, t=1;
siscanf(args,"v%u by %i to %i",&v, &s, &t);
return new DecreaseController(v,s,t);
}
Rien de bien extraordinaire: un code relativement simple pour une fonction relativement simple. D'où le choix de cet exemple pour vous montrer un peu plus comment je m'y prends. C'est ce que j'aime dans l'approche "micro-contrôleurs enchaînés" où je n'ai plus besoin de surcharger la signification du code C++ pour traiter tel ou tel cas un peu particulier comme je le faisais au début du projet. J'aime assez bien le côté "auto-explicite" et très "BASIC" de la liste d'arguments "v0 by 4 to 100" plutôt que (0,4,100) comme je l'utilisais jusqu'ici. Attendez-vous à voir ça se généraliser dans les gamescripts

That's all the beauty of chained micro-controllers approach I implemented this summer: no need to clutter a generic "walking" behaviour with something like "oh, btw, some guys would need to slow down" or with "btw, v4 is a speed decrementor and v5 a speed target for the walking behaviour". Opting for a BASIC-like encoding of arguments (instead of the typical 0,4,100) is the final stylish touch ... Now I'm one step closer from having berrybats chasing you if you approach the vines carelessly. I just wish I'd be able to provide these "supplemental C++ classes" through plug-ins I could upload by WiFi to the game engine. Maybe I'm wishing too much ^^".

Voilà, voilà. Pas vraiment lié aux problèmes d'escalade mentionnés ce week-end, si ce n'est que decrease(...) pourrait aussi être utile pour les berrybats qui poussent sur ces lianes envahissantes.

1 commentaire:

sylvainulg a dit…

hmm ... quand je définis
using dpad
using stopper
using momentum(256,64)
using decrease (v6 by 1 to 0)

pour Bilou, tout va bien, mais avec
using decrease (v6 by 1 to 0)
using dpad
using stopper
using momentum(256,64)

il arrive que Bilou se "gèle" à l'arrêt, incapable de repartir à moins qu'on ne le blesse ... à creuser.