Showing posts with label platforms. Show all posts
Showing posts with label platforms. Show all posts

Saturday, August 15, 2026

Le fight club, version cflags

Last summer, I started reworking collisions in my game engine. The idea was to be able to define groups, so that e.g. collision-based communications between a stunned blador and its feet would never interfere with a bouncy branch and things it bounces away. Sure, there was way to do that already, by assigning them separate collision flags, but I've long ran out of these, forcing me to make weird groups and combinations.

Oui, parce que bon, ça fait maintenant un moment que j'ai ouvert la branche "new-cflags" dans laquelle on a la possibilité de définir des groupes de collision, et je m'en suis même servi pour gérer les portes, mais si je veux permettre à un appleman de rebondir contre les autres applemen tout en passant "à travers" les petits vers, je me retrouve devant un imbroglio avec la question épineuse "je le mets où, mon nouveau flag ? et est-ce que ça coince ?"

With recent work on the appleman, I wanted to make a distinction between "weapon-sensitive area, from a light object" and "weapon-sensitive area, from a heavy objects", but I wouldn't know how to encode it anymore. So far, the groups had only been used to implement the doors, but felt like it was time to define a new group, to deal with every collision that deals damage to entities in the game... which I finally decided to call the "fight" group.

Alors c'était l'occasion de se demander "et si en fait on faisait un groupe pour toutes ces actions qui retirent des points de vie à un des objets ?". Petit à petit, hein, en vérifiant qu'on ne casse rien (et donc, forcément avec une vidéo Screenshot Saturday où tout d'un coup, on passe à travers les branches au lieu de rebondir et à travers les pommes sans qu'elles ne se doutent de rien...)

Un nouveau G_FIGHT donc (j'ai un peu chipoté pour trouver le nom du groupe puis le Fight Club s'est rappelé à mon bon souvenir, tel une évidence inévitable). Peu à peu, les différents scripts-personnages sont convertis en nettoyant les vieilleries comme les scripts avec des valeurs numériques plutôt que des combinaisons de symboles. Puis arrive le moment crucial de réactiver la branche-qui-rebondit, et là, je me rends compte que garder dans G_FIGHT l'action principale F_STOMP, celle que Bilou utilise jouer à Super Mario assommant un goomba, ça ne va pas marcher. ça va imposer aux zones de collision destinées à être de simples plate-formes de faire partie du Fight Club alors qu'elles n'ont même pas de "points de vie". D'autant plus problématiques qu'on a aussi des flags du type F_PLATFORM pour, par exemple, empiler des taille-crayons sans qu'ils n'infligent de dommages.

It wasn't that straightforward ... I mostly broke everything first and then repaired things one after another. Last week, for instance, only the woodworm would still interact with Bilou. but now the code is cleaner and I think everything is repaired ... I may to a bit more time travelling to check the blador / tiled pencils interaction ... it looks like it isn't working as good as it did previously.

Then a few things just did not resume working, like jumping higher when you press the JUMP button while bouncing on a branch ... mostly because some hit areas needed to be duplicated and transition depending on them needed to be reassigned to the new area. Current GobScript doesn't make that easy to refactor. 

Ah, and yeah, below is a snippet of what the area collisions look like now.   

Heureusement, j'avais prévu de garder une portion des flags "neutres" (CFLAGS_LONE_FLAGS), valables qu'il y ait accord sur les groupes ou non. On pourra donc mettre la branche dans le groupe G_GROUND (qui n'existe pas encore) dont F_PLATFORM ferait partie et lui ajouter un "ah, oui, on prend F_STOMP aussi, même si ça ne fait pas vraiment partie du groupe". Certaines des zones de collisions ont dû être dédoublée (une avec G_FIGHT, l'autre sans), un petit défaut dans la réécriture quand ça arrive et on se retrouve avec des branches qui ne rebondissent plus aussi bien qu'avant ... un petit schéma, un peu de ddd et ça se remet en place. Le code pour tester deux zones de collisions ressemble donc maintenant à


 cflags GobArea::test(const GobArea *o, GameObject *g, cflags mask, GobCollision* gc) const {
     if (o==this) return 0;
     cflags group = mask & CFLAGS_GROUP_MASK;
-    if (group && (flags & CFLAGS_GROUP_MASK) != group) return 0;
+    if ((flags & CFLAGS_GROUP_MASK) != group) mask &= ~CFLAGS_IN_GROUP_FLAGS;
     if ((mask & flags & CFLAGS_EXPR_MASK)==0) return 0;
 
     // congratulations: you may compare coordinates, now.
     

edit: there was one last thing I had spotted that wouldn't work as expected: sticking dumbladors on pencil spikes. Especially, the dumblador might still wake up. So I dug the good old SchoolRush and checked what happened. Verdict: the dumblador *might* wake up there too, but it looks like it's much more unlikely to happen due to terrain geometry.

Friday, October 25, 2024

Hanging around in the ICE ...

Good thing with the German express trains is that they provide unlimited power and some WiFi. Your trip might not go as you expected, but at least you've got time to sit, think and check your code base to plan what you'll do in your homebrew project afterwards.

Among those "what's next", some are already done now, like "converting furblock to treebump"... which it did not need after all.

For some time, I have this little note in my notebook... Because many of the levels in the design book expect that we could hook and hang to some objects. I'd like it to be stylish, with swinging animation and all. But for the purpose of testing the levels and trying the game, just snapping to the hook and waiting for the player to press JUMP or leave would do the trick.

The train-idea here is for the step just after that bare proof-of-concept: I already have a "radius" controller that keep a character within a given range of a "pin point". Being hung could use that controller rather than being snapped to a static position. 

To do so, we can shoot a new game object, Bilou's hand(s), that will snap to the hook and use that as a pin point for the swing. That means we'll have to hide bilou's hands on the existing hero game object (like we do when he's carrying something) ... or just don't draw the hand at all, and reuse its OAM slot to draw Bilou's eyes separately from his body, meaning we'd gain one extra freedom degree for the animation, and wouldn't have to draw a dedicated body-and-eye sprite for every angle.

Then I started brainstorming about the croc-platform: I'm not satisfied with its current look. I dug some real egypt crocodile pictures (and real statues pictures). I toyed with the idea of having the crocodile head showing sideways rather than front view -- that would have meant it wouldn't stop sands when flapped anymore ... The blue book said it wouldn't harm that much.

But I couldn't convince myself it would work either. When the crocform#1 flaps down, it completely cease to interact with characters. A sideways crocodile head flapping down by 90° wouldn't "disappear" that way. It would still be in Bilou's way, mostly as a small wall, but it should still be possible to stand on the rear of its neck ...

A few spots in the ongoing level design would work fine with crocform#2 repurposed, but in other spot, it would mean throwing the player into spikes, rather than just let them fall down...

And then I thought about a type of object in New Super Mario Bros that would behave quite like what I need for my collapsing platform, and it meant I wouldn't even need to drop the "shut the sand door" idea:




Monday, October 21, 2024

bug on blador

J'ai tout les morceaux pour qu'on puisse à nouveau utiliser la map "anniversaire" de la school zone dans l'exécutable de "Three Rooms Demo" ... mais quand je veux le faire tourner, on ne peut pas vraiment dire que les choses se passent merveilleusement bien. J'ai cru au départ que c'était des choses que j'avais "cassées" en développant le "soft landing" des furblocks (la motivation n° 1 à faire revenir ce niveau *maintenant*, c'était précisément de vérifier l'absence de régressions). Et des choses qui vont de travers, il y en a quelques unes ^^°.

I wasn't 100% confident with the changes I made to special flags used to implement the furblock... So as I'm entering one week off, it seemed appropriate to ensure I have all the required material to revive a School Zone level where all the "monsters" are featured and ensure there aren't regression. So here's the "anniversary" level again.

Mais pour certains bugs, un petit voyage dans le temps avec Mercurial ne laisse aucun doute: ils étaient déjà là avant. C'est notamment le cas avec dumblador, et Bilou qui tout d'un coup se retrouve bloqué et immobile s'il lui atterrit dessus au moment où il devrait pouvoir servir de plate-forme...

Cette fois encore, c'est dans ddd que la réponse est apparue. Si le n° d'état renseigné par InspectorWidget (bi28) est pour "RIDLE", l'affichage de Bilou en train de tomber n'est pas un glitch: on a jamais su rester sur le taille-crayon parce que le contrôleur "onpath" estime qu'il n'y a plus de plate-forme... la faute à une modification pour crocform qui ne s'est pas re-propagée jusqu'à dumblador: le choix du bit d'état qui indique si on est bien sur une plate-forme ou non ...

And well, we do have some regressions, and some of them are quite older than the furblock modification. Today I repaired the ability to stand on a stunned blador, which should have been updated after I implemented the pyramid "collapsing" platform: it reuses bit-testing that allowed stacking dumbladors, but for obscure internal reasons, it did not use the same bit to declare that the platform is indeed valid. Tricky to find, but easy to fix.

Saturday, June 24, 2023

area %d = anim %x

Bon, franchement, je me demande depuis quand ce problème attend que je m'y attelle... que ce soit mon blog, twitter ou mon calepin, impossible de trouver une date correspondant à "oui, la plate-forme se reclappe, mais quand je me mets plus sur sa gauche, je passe à travers.

J'imagine que ça fait partie des choses qui m'ont motivé, fin du mois dernier, à faire en sorte qu'Inspector Widget marche à nouveau dans la démo "3 rooms". Et la visualisation des zones de collision m'avait porté à croire que j'avais mal défini les zones de collision dans l'éditeur, sur NDS.

At some point, I noticed that InspectorWidget wasn't working anymore in Dreams.nds ... not quit ideal when you're trying to add bits of gameplay to your years-long-under-development demo. Especially not when you barely manage to get more than 1 hour of gamedev at once. And after I managed to get it back, I suddenly remembered that seeing Bilou falling through the flipping platform was nothing new and that it was linked to the platform having bad hitbox.

Parce que oui, ayant la flemme de définir les zones à la main, cette 'crocforme' est (avec la branche-qui-rebondit), un des premiers objets du jeu à importer une zone de collision passive directement avec area 0 = anim ${FLAGS}, plutôt que d'en fixer explicitement les coordonnées comme j'ai fait avec Apple Assault et School Rush.

Sauf que sur DS, les hitbox sont parfaites. Rien à redire. Je re-transfère le fichier (le lendemain), des fois que j'aurais oublié que j'avais déjà corrigé le soucis. Je recompile (le surlendemain), je teste. Pas d'amélioration. On est samedi, je sors l'artillerie lourde: une nouvelle instruction `break` pour le langage de script histoire de pouvoir mettre un breakpoint dans ddd et commencer à inspecter le comportement du parseur de script pile là où ça coince: dans la boucle qui lit les commandes 'Define' de l'animation où on fixe les coordonnées de la zone solide et des hitboxes pour l'animation.

At first, I thought I had just messed the hitbox within AnimEditor for DS. But a few checks and WiFi transfers later, it turned out that no: the data (as far as the editor was concerned) was ok, but the game still would use the bad hitbox. Checking that on the parser would be darker than night -- or so I thought. This is how the parser now supports an additional "break" instruction that is a noop where you can set a gdb breakpoint while parsing things. These are not meant to be committed, of course, but it definitely helped.

A few 'next instruction' later, it turns out that my engine is using tool-absolute coordinates for the hitbox instead of object-relative coordinates. That is, when you edit an animation in AnimEDS, you don't only store how to use it in-game, but also what you need to edit it again in the editor, and that includes where to put each component on-screen in the editor. The character's center and the edition widget center may match, but they don't have to.

Le code qui gère ça n'est pas tout neuf: il a permis d'améliorer les hitboxes pour attraper les objets dans SchoolRush il y a près de 10 ans. Mais j'ai commis l'erreur de copier-coller le code plutôt que de faire une fonction "importArea" qui serait utilisée des deux côtés: pour les zones actives et les zones passives.
ça n'aura donc pas été trop compliqué de faire en sorte que les deux utilisent le même bloc de code (le bon) et d'avoir une plate-forme qui fait *enfin* ce qu'on attend d'elle :-P

J'espère que je passerai un peu plus vite de la découverte du problème à la recherche de sa solution, la fois prochaine ^^"

If I want to fix that, I need to track not only hitbox#n ORIGIN coordinates, but also those of the 'solid' box -- the one used to decide whether the object cando() something. then when one 'ORIGIN' instruction shows up for the area we're interested in, we create relative coordinates. Hopefunny enough, it turns out I already have code that does precisely that, because I have both active and passive hitboxes and I failed to avoid repeating myself when writing the original parsing code ... and later failed to fix both copies when I realised things were not going as they should have.

Thursday, December 29, 2022

crocform #1

You may remember I had plans for a larger variety of platforms in the desert/pyramid zone of Bilou Dreamland. There's a second flavour of the crocodile-inspired platform that I barely shown so far, but which got a significant role to play in the work-in-progress level design. Unless you have some sandfall around, it is merely behaving as a "disappears after some time" platform. With sandfall, it adds "respawn" to the mix.

Last week end, I finally got to the point where I wrote some script to give it existence in the ongoing 3-room demo. There's a thing that went significantly wrong, though: Bilou couldn't notice when the platform is gone.

La pyramide, c'est l'endroit idéal pour des plate-formes un peu particulières. Qui croulent, par exemple. Ou qui changent d'orientation. Mais quand j'ai voulu faire un p'tit essai dans ma démo actuelle, Bilou est resté gentiment à attendre que la plate-forme revienne, flottant dans le vide. En réalité, il me manque un évènement capable de "décrocher" Bilou de la plate-forme: puisqu'elle existe toujours, pour le jeu, on peut toujours marcher dessus.

Il y aurait plusieurs moyen de régler: Bilou peut déjà se faire "propulser" par une collision (hic: seulement s'il n'est pas au sol). Les dumbladors empilés détectent quand l'un d'eux s'en va (hic: seulement grâce à un contrôleur dédié et l'ajouter ici décalerait tous les évènements de Bilou). Au final, c'est le contrôleur testant si on est sur une plateforme que j'étends pour qu'il puisse tester un bit d'état de l'objet auquel on est attaché..

I've had a similar issue with dumbladors when time came to 'stack' them: when one recovered, those stacked on top of it had somehow to detect they'd no longer have a platform behind them. It would be trivial if the gameobject implementing the platform was destroyed, but here it stays around.

  • extend dumblador's extra gobbit(when 7.1) to Bilou
  • trigger an extra "throws up" temporary hitbox when flapping down the platform
  • implement it all with brand new "larger animated blocks" feature, not with a sprite, because that platform doesn't truly "move".

The temporary hitbox seemed to be the least-resistance path, so I gave it a go. But unfortunately, it led nowhere. Mostly because the already-implemented collision I was trying to reuse (that use to make Bilou bounce of erasers, for instance) is only tested in states where Bilou is airborne. Here, I'd need it in states where Bilou is supposed to be on the ground.

Yet, I hesitate going for an additional micro-controller gobbit (despite it already has C++ code) because that would introduce new events to deal with. I'd rather have the onpath controller be able to fire an event when the platform-object it is attached to signals it is no longer a platform, the same way the controller can signal the object no longer exists.

I could try having some automated test into 'onpath' that would ensure the current state of the 'platform' object still has the area active and using the proper flags, but that would require extra care if I don't want Bilou to behave weirdly when the platform turns back or does any state transition that don't actually imply losing its 'platform' behaviour.

reality check: using onpath(when w7.2); (from the worst-possibly-named commit)

Tuesday, January 18, 2022

Le fruit-bouffi

Dans un ancien post, j'avais des piafs-saucisses-plate-formes. Dans un autre, j'ai des piafs-copains-qui-nous-transportent-à plusieurs...

I've got an old post where birds have been stretched and helium-inflated so they could be used as walkable platforms, and another, more recent one where birds have birdish shapes and use ropes to carry the player -- but you need many of them if you don't want to fall down.

What if I could get the new-one turn into the old-one for some specific locations, as result of a key-and-lock interaction ? A possible key would be something you can feed the bird with, but isn't exactly part of their diet. Maybe a raw berrybat ?

Et si on pouvait faire transformer un piaf-copain en piaf-plate-forme ? par exemple en lui faisant avaler quelque-chose qu'il ne digère pas vraiment ...

Une chauve-souris-baie pas mûre, par exemple, qu'on aurait été pêcher dans une caverne de la montagne ...

à creuser.

It would introduce a valid reason for having caves in addition to peaks within those mountains (bats like caves more than peaks).

Wednesday, January 05, 2022

Les Capris et tutti quanti.

Avec les enfants qui veulent aussi jouer, les niveaux plus longs et une fonction "prendre une vidéo en jouant", je suis moins tenté sur Switch de mettre mon jeu en pause et de commencer à parler/redessiner quelque-chose. Quand je le fais quand-même, c'est souvent pendant que les enfants jouent, et donc des petits schémas techniques griffonnés plutôt que des croquis.

Mais l'an dernier, j'avais quand-même pris le temps de passer en revue mes vidéos de Donkey Kong Tropical Freeze pour voir un peu ce qu'il y avait de particulier comme type de plate-formes mobiles (avec évidemment la Peaks Zone en tête).

C'est aussi vers DKTF que je me suis orienté il y a quelques jours pour essayer de trouver des idées de 'niveau aérien' et c'est en voyant la tempête du niveau 3-3 emporter tout et n'importe quoi que j'ai réalisé que "bah, en fait, j'ai pas besoin de me creuser la tête pour trouver des animaux succeptibles de faire plate-forme volante: il suffit que je dise qu'il y a des courants d'airs et que je trouve des choses assez légères pour se faire emporter. C'était le premier "débloqueur".

Puis en bas de la feuille j'ai commencé à dessiner ces arbres tout tordus et leur branche m'ont donné envie de tendre des cordes entre les deux pour que Bilou puisse passer dessus. C'était l'élément de level design qui m'avait manqué jusque là.

It's been 2 years since I decided to have a 'mountains peaks zone' for Bilou's Dreamland, and even before that, I had ideas to use sheep/goat-like monsters to populate it (plus birds). But none of this led to any monster design or level design post. I just couldn't come up with anything to draw. Hopefully, it changed lately. It all started with a funny tree I draw on a sketch while collecting gameplay ideas from Donkey Kong: Tropical Freeze videos (and other possible videos about 'air world', btw). It had hook-like branches, with no leaves on it. It was appealing for a string bridging from one to another. It felt natural that Bilou would use that string to move from one place to another when there's nothing 'floating' inbetween...

I tried to imagine what could prevent him from doing so. Like a tightrope dancer. I tried to recycle my goat-idea and had fun giving it a Ice-Kirby pose. It seemed to work like magic. It's not an evil opponent, just someone who happens to be dangerous for you, in this case because you happen to have missed that you're on a circus-training area. The idea was working well, so it was time to pick up proper pens, proper paper and start drawing that for real.

Une fois la corde tendue et Bilou accroché dessus se posait la question: qu'est-ce qui pourrait le mettre en danger. J'avais depuis longtemps l'intention de mettre des espèces de bouquetins dans la montagne. Une influence du premier Rayman.

Ça s'est mélangé dans ma tête avec une posture de Kirby-patineur avec son pied en l'air. Ah, ce serait tellement plus facile pour Bilou s'il avait une formation de funambule ...

Mais pour un bouquetin, ça devrait être un jeu d'enfant, non ? Une fois cette idée dessinée, je savais que je tenais le bon bout.

Restait à voir si tout ça est assez "Bilouteux". J'entends par là, est-ce qu'on se sentira sur la planète des chauve-souris-baies et des crayons soldats ? Les rochers troués comme du gruyère sont rigolos, les arbres sont bien quand ils sont nus mais un peu plus classiques avec leur look de palmier quand ils ont encore leurs feuilles.

Probablement que Joke trouverait que tout ça manque de champignon. Alors j'ai repris mon dessin et j'ai gribouillé des chapeaux de champignons par-dessus tous mes feuillages d'arbre. ça marche. c'est même ce que j'ai de plus convainquant pour justifier les "feuilles parasols" servant de plate-formes volantes. Alors allons-y: ce seront des hybrides arbres/champignons dont le chapeau se laisse emporter par le vent pour aller disséminer plus loin une fois qu'il est bien mûr.

So I started drawing all the stuff I had barely sketched so far, leafless trees, ropedancing goats, watching goats, large flying structures brought up by upwards winds ... a bit too big for a single leaf given the trees size. You'll notice that this early sketch also features sorts of 'beaks' within the rock. That's something I had noted to lead to interesting look, but which doesn't seem to work well with the 'cheddar-holes'. And I definitely want to keep cheddar holes :P

Later on, on a walk, I realised that a pal known as 'the BilouMaster' would likely suggest that the scenery needs more mushrooms. So why not claim that those trees have mushroom-like tops instead of leaves ? That would give me free 'floating platforms in upwards winds', free umbrella-like thing to hold while a goat is ropedancing and contribute to the overall 'Bilou, not earth' feeling of the area. I overdrawn my sketch a bit .. it seemed to work. I kept it.

A ce stade, j'ai repris ma liste de plate-formes spéciales dans DKTF. La première, c'était une plate-forme qui se met en mouvement en fonction de la position de DK sur la plateforme: à gauche, elle part à gauche; à droite, elle part à droite.

ça marche impeccablement avec un chapeau de champignon. En fonction de la hauteur des colonnes d'air, de leur intermittence ou non, je peux construire un niveau aussi varié que la traversée en montgolfière de DKC2.

DKTF propose un joyeux nombre de variations sur ce thème, avec de l'électricité ou des plate-formes incomplètes, mais une des plus remarquable, c'est peut-être celle qui la combine avec la mécanique "s'accrocher" introduite dans Donkey Kong Returns.

Ça tombe bien: j'ai justement envie de faire de "Dream Land" le jeu où Bilou peut justement s'accrocher à tout et n'importe quoi. aux branches des arbres, aux racines souterraines, au cous des bestioles qui infestent la pyramide ... Et évidemment aux cordes des ponts de cette nouvelle zone.

Alors du coup, ça nous donne une manière bien plus intéressante d'utiliser la combinaison 'une corde transportée par deux oiseaux: Bilou au centre, les charges sont réparties et la corde s'élève emportée par les deux oiseaux. Si on se décale d'un côté, ça augmente la charge pour l'oiseau correspondant et on dévie de ce côté tout en descendant lentement.

It felt like it was the right time to pick up my never-blogged list of original kind of platforms in Donkey Kong: Tropical Freeze, and see whether I could match them with things that would work in the newly defined Peaks Zone.

A platform that starts moving left or right as you move to its left or right, for instance. That could be a floating mushroom top. Another one where you're hanging instead of landed ? Well, since "I don't see why Bilou wouldn't use the ropes" would work well here too. When there are just 2 birds and one rope, they're just strong enough to lift him if Bilou's weight is equally distributed. Otherwise, you'd dift in one direction (and slightly slide down).

Mais revenons à nos bouquetins. Un autre petit schémas de plate-forme que j'avais dans mon cahier montrait une bascule avec un obstacle à pic passant d'un côté à l'autre.

Alors bon, on ne va pas vraiment commencer à rajouter des boules à picots ici (je n'ai pas les fruits géants de DK pour le justifier), mais dans la catégorie 'obstacle à roulette', je peux profiter de l'idée "font leur cirque pour introduire un autre type d'acrobate.

et le voilà. Irrésistible. Adorable mais redoutable.

Can the new goats also be used in some DK-like platform mechanics ? Sure! There was one about a platform that tilts back and forth and makes a spiky hazard roll left and right along with its movement. We can sure find something that rolls in a circus setting, right ? Just add a happy goat/sheep thing on top of it and voilà.

And while I was telling all that to my brother, I've got a flash-vision of happy goats appearing from the bottom of the screen as if there was a hidden trampoline and you could make your way by carefully bouncing from one goat-back to the next. 

Puis en racontant tout ça à mon frangin hier me vient l'idée d'un passage où on voit tout simplement des bouquetins surgir du fond de l'écran, faire leur petite pose et retomber. On doit passer à dos de 'mouton' pendant ce temps-là.

au moment de le dessiner, vu que je n'ai pas de "fond d'écran" pour masquer ce qui se passe, j'ajoute à nouveau une corde. il rebondissent dessus comme sur un trampoline. Un clin d'oeil à Sleepwalker.

Autant dire que ça aussi, il vaudra mieux que ça n'arrive pas pendant que Bilou est suspendu à la corde.

Of course 'a hidden trampoline' isn't something easy to draw, so I replaced it by a string. A string you should better not try to use because you can't hold to a strumming string. There were more platforms styles in DKTF, of course, like that giant flower that starts bending when you lose its center, but there's already a good deal of things to implement here, isn't it ?

Il en reste, évidemment. Je n'ai pas essayé de convertir les fleurs géantes qui basculent, celles qu'on déplie en se suspendant à un truc qui pendouille ni les tours de plate-formes qui s'enfoncent (et donc se déroulent) quand on marche sur l'une d'elles. Mais bon, je crois qu'on peut dire qu'il y a déjà de quoi voir venir, non ?

Sunday, March 07, 2021

Fezzy platforms

 Vous vous souvenez que j'avais joué à FEZ, hein ? Et pendant ce temps-là j'essayais aussi de voir si je trouvais des idées intéressantes pour Bilou, bien-sûr. Comme cette plate-forme qui fonctionne par paires, et qui se transforme en écrabouilleur sous certaines perspectives ou comme plate-forme inerte sous d'autres.

Bien chouette, mais comme Bilou ne peut pas changer la perspective, ça reste moyennement intéressant. (edit: à moins que ...) 

La deuxième (oui, je les fais dans le désordre par rapport à mes notes sur Boox) est déjà nettement plus exploitable.

C'est une sorte de mélange entre une plate-forme dont la taille varie au cours du temps (cf. SMW / Yoshi Island 3), mais avec en plus un effet 'répulsif' si on anticipe pas le moment où elle pivote. Et une phase où le saut de l'une à l'autre sera légèrement plus difficile vu que la hauteur augmente de 1 bloc.

Je trouvais que dans le thème de la pyramide, elle se serait assez bien déguisée en tête de crocodile. ça tombait assez bien: j'ai envie d'utiliser l'excuse de la pyramide pour introduire plus de plate-formes mobiles (sans avoir besoin de leur coller des ailes ou des réacteurs) et je n'ai toujours rien de crocodilien pour ma pyramide.

Mais pour en faire quelque chose de plus 'unique', je combinerais bien ça avec les plate-formes à dos pointu de Shantae. Sauf que comme Bilou ne sait pas souvent 'taper' dans quelque-chose, je pourrais utiliser un mécanisme "coup-d'boule" pour faire pivoter les plate-formes de 90° quand elles sont orientées "gueule en l'air".

ça pourrait être un défaut, mais en fait ça s'est avéré très inspirant. "et si les plate-formes étaient inter-connectées de sorte qu'en en cognant une, on en fait bouger plusieurs". "Et s'il y avait un 'pieu' dans le chemin de la plate-forme qui l'obligerait à faire 90° en plus si elle est dans le bon sens". "Et s'il y avait un switch pour faire apparaître/disparaître les pieux pendant que les plate-formes bougent" ... vous voyez le tableau ;)

edit: une variante qui fait un quart de tour quand on la quitte avec un saut (surtout pour le 'chemin des papas' à la demande de J.L.N qui vient de peiner sur qqch du genre dans Gris) et la possibilité d'attraper les montants verticaux avec le poing-lasso pour by-passer les challenges quand on a un power-up.

edit++: J'avais apparemment déjà fait une mise en image de plate-formes-croco basées sur les plate-formes de FeZ, mais avec une traduction plus litérale (et à mon avis moins convaincante)

Sunday, February 16, 2020

Plate-formes volantes ?

Si je veux faire quelque-chose de plus "aérien" pour la dernière zone, il va me falloir des plate-formes volantes. Mais voilà, je n'ai pas envie de leur coller des petites hélices (qui aurait fabriqué ça) ou d'invoquer du gravitium (pas partout, en tout cas). Pas envie de resservir le cliché du "bloc de pierre collé à un autre bloc de pierre qui vole grâce à des petites ailes de Parakoopa" ...

Pas convaincu non plus par des piafs qui auraient justement une forme de plate-forme. Il y a quelque-chose d'un peu ce genre-là dans DKC:TF, mais il s'agit de plus de bumpers volants -- rôle que les parakoopas avaient employé déjà bien avant. Ici, je veux bien parler de quelque-chose de suffisamment large pour qu'on puisse marcher dessus et de suffisamment coopératif pour qu'on puisse traverser un écran avant qu'il ne s'en aille.

You know, I'm trying to make Bilou's Adventure a somewhat consistent world. I won't say "believable" or anything like that, because we play as a ball with hands/feet floating around him anyway, but I'd like to avoid introducing too many alien elements like gravity-defying blocks or cartoon pockets or even human characters. If something exists in the game's world, at least Bilou and Bouli must find it believable. And that makes designing a mountain level with floating platforms ... a bit more challenging. I'd like to avoid the generic, Zool-like "floating rectangle -- just don't ask", and its Mario-like "floating rectangle with not-so-little wings".

Je m'oriente vers un croisement entre les zeppelins et les piafs. Les saucisses/zeppelins, c'est sympa. J'ai bien aimé l'idée dans Endymion, dans Titan et dans "L'incident Jésus". Dans Kirby, aussi ^_^. Avec un bec et des zyeux, on peut leur donner plus d'expressivité et les écarter d'une trop grande ressemblance avec Kirby, justement.

ils sont suffisamment dépendant des caprices du vent pour ne pas vraiment pouvoir éviter que Bilou ne les emprunte, pas vraiment mis en danger par ses atterrissages non plus.

I've postponed this post for a while as I was considering and then discarding ideas. I finally converged towards zeppelin-birdos. I loved zeppelin-like sentient creatures in Endymion, Titan and Frank Herbert science fiction books. They're close enough from a regular platform shape so that we can land and walk on them, not just bump on them. But in Bilou's world, it would be best if they had eyes and stuff that can suggest they feel something. And giving them little wings will make them more interesting to look at when you're not on them. But they're wings are too small to be able to do anything but follow the winds. And their body is soft enough to avoid taking damage from Bilou's lands.

Sure, I'm not the first one to try using second-class creatures as platforms. One of the most prominent example I can think of are the owls in Tropical Freeze. You'll note that these are more floating bumpers than floating platform, though: you cannot move freely just like on a parakoopa. And it make sense: if you had intruders landing on your head, chances are you wouldn't just wait for them to leave. Even the Parabeetles don't just keep moving unchanged if you land on them. Maybe SML2 owls ?

J'ai écarté juste avant ça des tapis volants (pourtant, des écharpes rouges volantes, ça aurait été un clin d'oeil sympa) et des plate-formes pendues à des poulies. Des cordes et des ponts suspendus, il y en aura sans aucun doute, mais je n'ai aucune raison pour justifier que Bilou ne puisse pas s'accrocher au "câble porteur", et donc c'est très différent d'une plate-forme volante.

A final word about dismissed designed. No flying carpet (flying scarf could have been fun). No walkable cloud. Since I plan to have ropes between peaks here and there, I must admit I've been tempted to go for platforms-on-pulleys. But no matter how I approached it, I couldn't explain why Bilou wouldn't just grab the carrying rope in case of emergency. Knowing my kids, they'd feel it unfair if they went for the rope and just fell through what is just decoration element.

Monday, November 18, 2019

Pyramid zone : un peu de design

 Hey! Je retombe sur quelques croquis de design pour le niveau du désert ... Avec notamment de vieux écrabouilleurs, mais aussi des voleurs-de-trésors qui sont en compétition avec Bilou pour retrouver "certains artefacts". Leur progression correspondait à une forme de timer assez visuel.

Just stumbling upon old scans for pyramid zone level design in the "still draft" folders while I was digging for lost (?) GEDS3 thoughts. Featuring early, non-convincing "smashers" design, and the idea that there would be ninja-bags progressing towards the same artifacts/treasures as we do, acting as a visual time limit to reach something.

Un autre "vieux" design : je cherchais une plate-forme qui se déploie ou se rétracte selon les actions de Bilou, un peu dans le style de ce qu'on trouve dans Shantae. Avec des raté et certains un peu plus chouettes. There was also some attempts to find a visually-pleasing item that would act as triggerred / time-limited platforms as we see in Shantae (and many other games).

And of course, some early appearance of the furry mimmic-block thing that isn't really a destructible block and isn't really a monster either, with some ancient runes that pre-date the electroglyphs.


  Et bien sûr, les blocs-poilus, qui peuvent nous bloquer mais pas indéfiniment. On y voit aussi quelques anciennes runes (juste un alphabet secret) plus anciennes que les électroglyphes.

Wednesday, January 03, 2018

A dos de blador.

Mes taille-crayons, une fois en mouvement, font d'assez mauvaises plates-formes, en vérité. Celà vient de leur animation. D'abord (comme la plupart des animations de marche), elle va retarder certains mouvements pour consommer d'un coup 2 pixels de déplacement après être restée immobile pendant 4 images si la vitesse de consigne est d'1/2 pixel-par-60eme de seconde. Ensuite, parce que contrairement à Bilou, le déplacement de dumblador s'interrompt pour une courte pause avant de reprendre: non seulement ce taille est trop "dumb" pour mettre un pied devant l'autre, mais en plus, il lui faut un moment pour se souvenir de ce qu'il convient de faire pour finir le mouvement qu'il a entammé. Autant dire qu'il vaudrait sans doute mieux pour une "pile de dumbladors" de tomber d'un étage quand un des tailles-crayon se remet en mouvement plutôt que de jouer à rajouter des "selles invisibles" pour offrir quelque-chose de plus souple.

Non. Je préfère tenter maintenant de faire tenir Bilou sur un taille-crayon à l'arrêt. Et là aussi, j'ai du travail: il faudra veiller à

  • forcer une mise à l'arrêt complet au contact, puisque le contrôleur "stopper" sera court-circuité,
  • "détacher" Bilou de son support lorsqu'il saute,
  • compléter le contrôleur "onpath" pour qu'il provoque le détachement lorsque Bilou n'est plus par-dessus le chemin.
This has been a "known issue" since April 2014, and it still wouldn't be easy to fix it today: you can walk on a Dumblador (after stunning it) as if it was a platform, but as it wakes up, weird things occur that make Bilou slightly slip forward and eventually fall of the blador. Initially, it was also affecting stacked dumbladors, so I added a rule to "break" the stack as a blador wakes up.

The core of the problem comes from the fact that a carried GOB will adapt to the "moving platform"'s speed in order to give the illusion of friction, but when it comes to dumbladors, the speed and the effective motion quite disagree. First because - as with any WALKing GOB - the horizontal speed isn't constant, and second because I introduced a small pause between two steps for the blador, to reinforce the feeling of "dumbness". As a reminder, the GPath abstraction is as follow:

  • GameObjects have an 'onpath' pointer, which complements the 'attach' pointer (to a gob).
  • GobArea now implements the (horizontal) GPath API, returning always the same y coordinate, and checking that you're in the desired xrange.
  • 'Ap' in a gobexpression will attach the object to a "path" rather than to an object, the area that triggered the collision will be used to define the new path.
I gave path-capable engine a try back in february 2013, but that was nothing I could test. The idea was to support both NSMB-like angled mushrooms and (softly) swinging ropes. The current code with dynamic GPath comes from June 2013 and has still to be complemented with a controller that uses it.

It's all described and motivated in Walking on Platforms

Sunday, December 28, 2014

Keen ClipToSprite()

This is the code snippet for the ClipToSprite() action that results in pushing monster/keen interaction when the monster stands on the left. The code adapts characters expected motion (which differs from its computed speed and is transient) so that intersections between characters hitboxes remains empty.

The condition highlighted with yellow puzzled me at first. In fact, we'll note that leftinto == xmove (the difference between characters speeds) when they were exactly side by side at the previous tick. Would there be 1 pixel distance between them at the previous tick, we'd end up with leftinto == xmove -1. So what it really implies is that we won't get pushed at high speed if we fall down just on the left of a carrot running to the right with a large leftinto value (e.g. if we fall on carrot's head and move down through it).

Une seule fonction -- ClipToSprite -- permet à Keen de s'aligner sur d'autres objets en définissant un nouveau mouvement qui s'exécute en plus du mouvement prévu par la fonction think(). Le principe de base est de calculer de combien de pixels les deux personnage s'interpénètre et de repousser celui qui n'est pas solide par un déplacement opposé.

Il est important pour comprendre ce code de se souvenir que le moteur de jeu travaille en plusieurs passes et que tous les personnages ont déjà leur nouvelles coordonnées quand les tests de collision ont lieu. Les valeurs originales de xmove et ymove ont donc déjà été appliquées. Par la "condition jaune" (leftinto <= delta_xmove), on s'assure que Keen ne sera repoussé par le bord d'un objet que s'il n'avait pas déjà dépassé ce bord à l'étape précédente (mais sans que la collision n'ait lieu parce qu'il était au-dessus du chariot, par exemple).

The ID keen engine is multi-pass. That means when ClipToSprite() is invoked as result of keen/courier contact, setting keen.ymove=0 doesn't prevent keen from falling, because he already moved down in the previous step. Instead, it prevents him from moving down again as result of the carrot collision. This design avoids issues with moving platforms without requiring a re-ordering of the objects evaluation.
This is also made possible because objects have a separate react() function to align against level structures.


Pour les plate-formes, des tests verticaux font suite aux tests horizontaux également présents dans les "monstres pousseurs" comme la carotte véloce. S'il est surprenant que le déplacement horizontal de Keen soit exactement celui de sa plate-forme (et pas Keen.xspeed + Cart.xmove comme le voudrait la physique), c'est qu'un premier mouvement a déjà eu lieu. Il ne reste plus qu'à appliquer le mouvement de la plate-forme à Keen, le repousser vers le haut et surtout s'assurer qu'au moment de l'appel à KeenAirReact, la logique du jeu pense qu'il y avait un bloc solide sous Keen. C'est le rôle de la variable hitnorth qui conserve le type de tile qui a interrompu le personnage lors de la phase de déplacement.

Characters that push you but you can't ride ends after those horizontal tests. For carts, platforms and Keen4e's bouncing red ball, you'll also process the "bottominto" test. Note that since we already moved Keen according to the direction keys, setting keen.xmove=cart.xmove and invoking ClipToWalls() again -- which includes applying (xmove,ymove) to (x,y) coordinates of Keen -- combines cart's move with Keen's own move as expected. Hacking the hitnorth member will make KeenAirReact() function believe that some solid ground was found during move/clip step.

Thursday, June 12, 2014

InspectorWidget could be more helpful ...

Ok, je suis toujours dans les ajustements supposés permettre à Bilou de soulever un taille-crayon dans un empilement. DDD, cybook, tout le monde y passe ... j'aurais bien aimé avoir un peu plus progressé sur l'Inspector Widget pour me simplifier la tâche, mais il faut faire avec ...

Après avoir envisagé la possibilité d'envoyer un message "à tous les objets qui me sont attachés", j'opte pour une approche plus pragmatique: une variable de la plate-forme que les objets transportés peuvent tester via leur contrôleur (on écrira donc onpath(when w7.1)) pour demander un avertissement si la 7eme variable de la plate-forme voit son bit 0 retomber à 0.

At last, Bilou can pick up any blador even when they're stacked up. One glitch fixed. I hope the same technique will allow me to have Bilou's carrying/non-carrying state more coherent. What technique ? Well, at first I thought collisions would be suitable to notify that one can no longer stand on a platform. E.g. when the platform fades into the background, I'd have a state with a collision area triggering a $STAND->$FALL (Detach) transition. But that's not working properly, because gobs might get collisions from another object that the one they're attached to. Tweaking areas so that the collision is properly received by all the gobs in all their states also turns into a sort of nightmare. 
Instead, I updated 'onpath' controller so that it optionally polls one of the target's variable and raise an event when this variable states "I'm no longer a solid platform, go away." That was the least resistance path. Plus, the polling is virtually free since we had to check that target for presence, position and speed anyway.

What about inspector widget and the picture ? well, it's an additional todo list to remember everything InspectorWidget should have been able to do to ease the (completed) debugging session.

On dirait bien que le problème est maintenant résolu. Glitch suivant: les mains de Bilou qui disparaissent dans certaines conditions (lancer un taille-crayon près d'un taille-crayon isolé, p.ex).

Saturday, May 17, 2014

Walking on Bladors

It's far from being done, but at least now I can give it a try: I can start walking when standing on a blador. Issues remain:
  • [done] once moving on a blador, I cannot stop: I slide. That's because "onpath" so far short-circuits "stopper" who was in charge of both bringing Bilou (with some inertia) to stop and check whether he'll fall. These two will have to be split for "onpath" to work properly.
  • [done] I am not detached when I leave the blador, making me slide even when I walking *past* the blador. 
  • [done] if bladors are stacked onto each other, make the upper one fall when the lower recovers.
  • [done] same if the lower got picked up.
  • [check] I may still end up not on the platform, but still forbidden to fall. Repelled and not attached am I ?
  • [todo] Why is there a slight bounce when I'm done picking a blador ?
  • [todo] horizontal speed killed when landing on a blador. But at least we can nicely move *out* of a blador.
  • [done] Why am I able to "restore" a blador when I pick up the one he's standing on with random chance ?
  • [todo] whatever went wrong with Bilou vs Inkjets ... fix it.

Saturday, March 22, 2014

Stack'm'up!

totally totem !
Commencer par les choses simples. C'est ce qui m'a permis de progresser en fin un peu sur le systèmes des plate-formes dans mon moteur de jeu, malgré des semaines bien remplies. L'objectif: permettre d'empiler des dumbladors l'un sur l'autre pour que plus tard, Bilou puisse lui aussi grimper sur un dumblador puis sur des objets qui bougent.

C'est un bon premier pas, même si dans l'immédiat, le taille-crayon du dessus ne se rend pas compte du "démarrage" de celui d'en-dessous, ce qui m'a permis de l'envoyer à son tour par-dessus le premier.

that was too much for one chunk.
At last, I've got one more step performed on the game engine. Too many times, I picked up my laptop after the kids when to bed to end up watching things on youtube or hunting for a new car. Somehow, getting at once into "Bilou riding some platform" was intimidating and I couldn't get things in place. When picking up my notes again this morning, I wanted to come back to small steps that can be chunked with a single tea cup. How about having Bilou able to stand on a stunned blador and call it a milestone ? As I started converting blador.cmd into the new cpp-assisted format, it turned out that I could get something even simpler to check the bare mechanisms: having stunned blador stacked onto each others. Well, tonight it's done.

Oh, and I'm afraid you'll have to wait somewhat for my "Critical Link" series comparing the gameplay of 2D Zelda games: my scanner has apparently entered the dark world of non-functioning appliances.
PS: it's easy to explain the fact that the "stacked" blador stays in place: I was missing the "attach to path" statement. More annoying: the new GameObject::ride() method was built under the assumption that Gob's movement in (dx,dy) would be consumed, which is not the case with dumblador's stepped movement.

Sunday, March 16, 2014

un bout de code ... d'alignement ?

Je range ... Et au milieu de tous les brols qui reviennent de mon ancien bureau et qui ne trouveront pas de place dans le nouveau, je tombe sur une tentative d'illustration du roll-jump de DKC returns précédé d'un morceau de code:

while (! cando(dx, dy)) {
  if (dx!=0) {
    dx=(dx>0)? (((x+w+dx)|7)-x)
               : (((x+dx) & ~7)-x);
  } else {
     if (dy==0) return FAIL;
  }
  dy=(dy>0)? (( y+h+dy ) | 7) - x)
             : (( y + dy) & ~7) -y);
  }
}
return NONE; 

Some code snippet I found on a flying sheet of paper while cleaning up and shifting some books around. It should help dealing with alignment along walls and floors while being carried by a platform. Time constraint do not allow me to integrate it into the source code so far, and I've been wondering where it could be for about 2 weeks, so I'll just keep it here for now. It should complement the newly introduced GameObject::ride() function.

Il doit s'agir de la logique d'alignement impliquée dans le déplacement "sur une plate-forme", gribouillé une fin de soirée, mais comme je n'ai aucun schéma qui l'accompagne et que j'ai été avare en valeurs symboliques, on verra ça plus tard: c'est l'heure des tartines.

Saturday, June 15, 2013

NSMB Editor !

The fact that I've just beaten the game without using a Mega Mushroom against final Bowser on *deline's request shouldn't let me forget that new Super Mario Bros on Nintendo DS is now 5... omg! 7 years old... Much enough to allow level editors to have been created. And I'm really glad that NSMBe works fine on my linux, since it's a mono-friendly Csharp program ^_^. Much easier than running Lunar on Wine.

Cette fois j'ai battu Bowser sans utiliser de Mega Mushroom (interdiction édictée par *deline). Et je réalise tout à coup que "new" Super Mario Bros a ... 7 ans. Bien assez pour que les éditeurs de niveaux aient fleuri, et j'ai même réussi a faire un peu tourner NSMBe un tout petit peu sous Linux. J'avoue que je n'ai pas l'intention de créer mes propres niveaux à NSMB. C'est un exercice qui ne m'a jamais vraiment attiré. Par contre, je suis curieux de voir ce que je peux apprendre sur la structure du jeu.

As you guess, I'm not that interested into crafting alternate levels for nsmb, although thanks to my ds linkers, I could even play the modified ROM on the Real Thing. But I'm deeply curious to discover how the thing was built. As I had expected, many of the special platforms you can walk on are "sprites" (either made of OAM or using 3D hardware ? I still couldn't tell). Obviously, not all level may use all the sprites, but what is interesting is that they have been organised in swappable "banks". You can't have e.g. giant Bowser and Nessie starred in the same level because they both belong to bank 5. But you're free to chose wheter you complement them with Hammer Bros. or Chomp Chomp, with mushrooms or tornados or moving platforms, etc. Spawn points, door/pipe entrance are also managed as "sprites".

Comme on pouvait s'y attendre, un grand nombre de plate-formes sont en réalité des "sprites" (soit avec des OAM, soit avec la couche 3D. Difficile à dire), même celles qui ne sont pas forcément mobiles, mais dont le comportement est suffisamment différent du sol. Les portes, les début de niveaux, les entrées/sorties par des tuyaux, sont eux aussi gérés avec des sprites.

Les sprites sont organisés en "bancs" que l'on peut utiliser ou non dans le niveau, certains bancs en excluant d'autres (pas de bowser et de nessie ensemble: ils sont tous les deux pour le banc n°5, par exemple). Par contre, on pourra les compléter avec des Hammer Bros ou des chomp chomps, comme on préfère.

Coins and blocks belong to the "ground" layer. Even item-providing blocks. I trust that to be made of good old tiles, as there can be only one layer of 3D objects and that sprites already use it... yet it remains to be proved. One reason that make me hesitate is that you edit it in terms of "objects" and not merely by laying out tiles on a grid. Each object can be individually selected, moved along, dropped, resized, etc. It is very efficient, compared to what LEDS currently offer, so I'm not surprised. It leads to funny things such as many different patterns of 'coins' so that you could have vertical, horizontal or dithered coins arrangement with a single 'object'.

Les pièces d'or et les bloc-question font partie de la couche "sol". Idem pour les blocs-à-power-up. Ils sont sans aucun doute fait à partir de bons vieux "tiles". Chose assez inhabituelle, en revanche: on les édite et tant "qu'objets", pas juste en plaçant des pavés sur une grande grille. Chaque objet peut être sélectionné, déplacé, redimensionné individuellement, ce qui s'avère très efficace pour la conception rapide de niveau comparé à ce que LEDS propose. Du coup, on retrouve des éléments assez curieux comme des "pointillés de pièces d'or" qui permettent d'avoir un "damier de pièces d'or en diagonale" avec un seul objet.

Tout ça n'a pas l'air d'être juste un choix de fonctionnement de l'éditeur: les niveaux eux-même contiennent ce genre d'objets: si on clique sur un "bloc" du dessus d'une plate-forme, on sélectionne directement l'entièreté du sommet de la plate-forme. Je présume que c'est une technique pour réduire l'espace sur la cartouche: le contenu en mémoire du niveau sera reconstitué en appliquant des commandes du type "remplir (10,10)-(20,20) avec du sol" puis "remplir (10,9)-(20,9) avec de l'herbe", etc. J'y crois d'autant plus fort quand je vois des motifs "effaceurs" qui n'auraient aucun sens dans un système utilisant des textures et des polygones.

And that doesn't seem to be a mere side-effect of the editor: the level has those objects, truly. If you click on the top edge of a platform that's already part of the design, you select the whole top. I can only imagine that this helps storing levels using less memory. Given that there's a lot of empty space and repetitions in NSMB maps, storing the level as "paint commands" (fill x1,y1 - x2,y2 with object #12) where object12=[start at tile 42, width=3, height=4] is much more compact than storing the whole map, and allows easier edition cycles. That would also explain the presence of "erasors" patterns that wouldn't make any sense if the level was 3D-rendered (afaik). When the level is loaded, the painting list is streamed from the ROM card (unlike previous Nintendo console, the DS doesn't have direct access to game ROM through its bus, iirc), a large chunk of RAM is allocated, and the commands are applied to know what to map on-screen. This in-RAM map would then be dynamically updated as coins are taken, blocks are used and bricks are destroyed... it all make sense.

Alternatively, you could just 'unpack' part of the level by applying a clip mask on the "paint commands", and have a level-sized bitmap for "interactive tiles".  Both coins, bricks and blocks are binary (original/used) so you'd mix that information with a paint command and still be able to retrieve the start of the level as the player left it although it wasn't permanently available as a tile map in RAM.

Friday, June 07, 2013

walking on platforms

I was somehow 'home alone' Wednesday evening. But my eyes were stabbed by my laptop's backlit. Perfect mood for some thinking on game engine features with some pens & paper. Theme ? How to enable Bilou walking on platforms. I initially hoped that a GOB reference would be sufficient to "walk on a platform", but that would restrict us to "platforms that have just the shape of the object's bounding box, while there is much more I intend to do with a generic "dynamic path" abstraction!

Cette fois, je pense que je tiens enfin le bon bout. J'ai réussi à fusionner la notion de "chemin" modifié dynamiquement (pour les cordes qui se balancent, entre-autres), et de plate-formes.Tout ça en prenant le temps, pour une fois, d'y réfléchir en cherchant quelles sont les questions auxquelles il faut apporter une réponse plutôt que d'essayer de construire une solution en partant d'une page blanche. Un système efficace qu'il faudra que je réutilise plus souvent.

And for once, I didn't started building a solution, but rather by writing down the questions that need to be answered. Once again, it proved being a powerful exercise. The questions were:

  • Is the "path" object permanent ? sometimes
  • Is the "path" object redundant ? only in the basic case
  • Could a GOB walk on more than one path (at once) ? no
  • Who 'own' a path ? usually, a GOB.
  • How many path can be owned by an owner ? I don't want to limit.
  • Can we be both 'on path' and owning a path ?  Yes (see picture above)
  • How could the owner of a path force objects on that path to lose their reference ?
Now, it's time to be more precise. The path is redundant with collision box in the very case of an horizontal platform. Yet, collision boxes (GobAreas) are not easily accessed from a GameObject reference. For once, I recall of Super Mario World's slanted platforms in the Chocolate Zone. It's still linked to a GameObject, but it will require a dedicated y=f(x) function.

La clé, c'est d'arriver à la formule "l'objet GPath est redondant avec la GobArea -- les zones rectangulaires utilisées dans la détection de collisions entre sprites -- dans le cas précis où l'on veut que le chemin aille de (gob.x+area.left,gob.y+area.top) à (gob.x+area.right, gob.y+area.top)". En d'autre termes, GPath est une abstraction générique, et le GobArea contient les données nécessaires pour cette abstraction dans un cas précis, mais on ne souhaite pas que le code utilisateur soit exposé à ces données. L'exemple-type d'une classe implémentant une interface ^_^. Il me faudra bien sûr d'autres implémentations si je veux des plate-formes inclinées, rotatives, basculantes, et tout ce que NSMB a apporté aux jeux de plate-formes ... mais le code de base "marcher sur une surface" restera là.

I also think the "path" we walk on must be potentially dynamic, that is, manipulated by a controller, for swinging ropes (example of a vertical path) or those NSMB dancing giant mushrooms. Writing it down as "only in the basic case (GobArea), but as a function of what I already have" made the bell ringing: GobArea is a specific implementation of the GPath interface. Virtual methods and inheritance are what I need to avoid cluttering controller's code with interpretation of coordinates array.


It also nicely solves the "ownership" (and thus allocation) issues. I know that things like huge mushrooms would have their Path allocated with level-scope, and then manipulated through a controller. The Gob that runs that controller is likely to be permanent as well.

Path for a platform, on the opposite side, are required only as long as a character interacts with the platform. By making GobArea ISA GPath, and stating that all coordinates resolutions are relative to the owner's coordinate, it means that all the platforms in a current state may share the same "path" information (offsets to their local coordinate) and  function implementation. Nice. They stop being "transient/temporary" structures and get level-wide scope as well: the allocation problem disappears ^_^. It do mean, however, that the "gobs" that control movement of multi-segment, dynamic paths will not be able to be themselves on a path, as they'll need their "path" reference to define what path they're altering ... unless I find a better solution, I can live with that.


L'autre bonne nouvelle, c'est que celà règle également les problème de "responsabilité" entre objets. Je trouve cette notion de responsabilité fondamentale en C++: une fois qu'on a pu définir qui est le seul et unique responsable d'un élément, alors on peut gérer beaucoup plus facilement son allocation, surtout lorsque les durées de vie coïncident. "Un chemin pour marcher sur une plate-forme", à priori ça a une durée de vie assez brève: du moment où Bilou entre en collision avec la plate-forme jusqu'au moment où Bilou s'en détache (de son chef ou de celui de la plate-forme, d'ailleurs). Un vrai cauchemar, surtout si on commence à se dire qu'il serait sympa qu'un autre ennemi arrive à la rencontre de Bilou sur cette même plate-forme!

En revanche, dès que GPath n'est qu'une façon de regarder la zone de collision (GobArea), tout s'arrange. Les "GobAreas" ont une durée de vie identique à celle du niveau et sont sous la responsabilité des états des machines d'état (et donc partagées par tous les objets d'un même type). C'est tout à fait satisfaisant si on considère qu'elles définissent des fonctions y=f(x) dans des coordonnées relatives à l'objet auquel Bilou est attaché.


All I still need in addition to the existing Attach, Detach and AttachToPath 'interaction opcodes' in GobExpressions is a 'IsAttached' test that will allow me to craft "force-detach" collision boxes that won't detach objects from other platforms ^^".