state12 :anim15 {
using stopper
}
state13 :anim6 {
using gravity(24,1536);
testpoint off (16,32)
}
state12->state13 on done [t] (v4 0 = 200 * 500 + ~ :1)
state13->state12 on fail [t] (v4 1 + 4 % :4 0 :1)
[
square brackets]
) and an action that alters the object before it enters its new state.
Voilà donc à la fois un "mockup" futuriste de l'éditeur de monstres sur DS et le genre de script que je bricole en attendant pour quand-même avoir des monstres qui se balladent dans mes niveaux. Histoire que vous suiviez :
- Funghi a deux états: au sol (
12
) ou en saut (13
). Ca me permet notamment d'avoir une animation spécifique à l'état "au sol" et synchroniser la "déformation" du sprite avec la collision au sol (chose dont le RSD Game-Maker était incapable). - Comme tous les objets que j'ai jusqu'à présent, Funky Funghi respecte la convention que
v0
est la vitesse horizontale etv1
la vitesse verticale. A priori, ces valeurs sont gérées par le contrôleur et utilisées par la classe SimpleGob pour mettre les coordonnées à jour. Elles sont aussi accessibles dans la machine d'état (:1
signifie "écrire la valeur dansv1
) - Chaque "gob" possède 12 compteurs sous son entier contrôle. Funghi utilise le premier d'entre-eux (
v4
) pour compter ses rebonds. "v4 1 + 4 % :4
" est une expression post-fixée (pensez 'calculatrice HP' qui doit se lire "prendv4
, ajoute 1, calcule le reste de la division par 4 et stocke le résultat dansv4
à nouveau". Ce calcul est effectué chaque fois que Funghi entre en contact avec le sol.
2 3 +
, as on a HP calculator). Hopefully, the existence of predicates allow me to compensate the lack of conditional expressions in actions by multiple transitions, each with a predicate and a separate action. See the code below, it's actually clearer (sort of) with similar efficiency.
A la fin de l'animation "déformation", la nouvelle vitesse verticale est définie. "500 ~ :1
" donnerait à chaque fois la même implusion (~
est utilisé ici pour prendre l'opposé d'un nombre, donc v1
reçoit -500 ... eh non, je n'ai pas implémenté les constantes négatives. Sue me).
Pas d'expressions conditionnelles genre "si(test, réussi, échec)" comme on en trouverait dans Excel ici (ou test?réussi:échec pour les programmeurs); c'est une restriction délibérée, et sans doute la plus contraignante de mon évaluateur d'expressions jusqu'ici. Or, je dois décider de fixer la vitesse après rebond à 700 ou 500 selon qu'on est au 4eme saut ou pas. Ma première approche était de tenir compte du fait que v4 0 =
teste la valeur du compteur de rebonds et laisse 0 ou 1 sur la pile selon le résultat, et de jouer sur la multiplication absorbante : t 200 * 500 +
vaut 700 quand t=1 et 500 quand t=0. D'où v4 0 = 200 * 500 + ~ :1
.
En fait, il y a plus simple puisqu'à défaut d'expressions conditionnelles, j'ai séparé prédicats et actions. Rien ne m'empèche donc de réécrire la machine d'état sous la forme suivante:
Alors oui, bien sûr, c'est horrible à relire. L'idée n'est évidemment pas d'obliger l'utilisateur final de GEDS à écrire des expressions de ce genre-là, mais plutôt de se donner un "langage intermédiaire" (un bytecode, quoi) comme résultat d'un éditeur de monstres plus graphique.state12->state13 on done [v4 0 =] (700 ~ :1) state12->state13 on done [t] (500 ~ :1) state13->state12 on fail [t] (v4 1 + 4 % :4 0 :1)
J'aurai donc quand-même mis un an entre "l'idée sur papier" et le protoype qui tient la route pour la définition des contrôleurs (bon, j'ai fait d'autres trucs entre-temps, évidemment). Et l'intégration des "test de possibilité de déplacements" dans le contrôleur (reléguant les testpoints au rang de sophistication optionnelle) n'est pas la moindre des décisions.
bon, 15 ans plus tard, l'éditeur graphique de comportements sur DS n'est toujours qu'un doux rêve :P
ReplyDelete