Showing posts with label iGobController. Show all posts
Showing posts with label iGobController. Show all posts

Friday, July 18, 2025

using around

I know it sounds like a detail, but trust me: if your game is lacking a "navigate around the corner of a block", it will significantly impede the gameplay. In some kind of games, it may even *ruin* the gameplay

I did not have it in Bilou RPG, and that meant you would be stopped as soon as your character slightly enters a solid tile. Sure, you can reduce the annoyance by making the box of your character smaller than its appearance on-screen.

You can also keep moving along one axis if the other is impossible. That's what's happening in the 'tutogit' demo, but you can spot times where the character suddenly stops and must be pushed again in another direction. It doesn't feel like how a professional game would behave.  

Super Mario World repousse Mario d'1 pixel par frame si le joueur est un peu trop proche d'un bloc lors d'un saut, autorisant jusqu'à 4 pixels de "débordement" avant de faire rebondir Mario plutôt que de le rediriger. ça n'a l'air de rien, mais c'est le genre de petit détail de gameplay qui fait qu'on peut se permettre des niveau un peu plus chauds sans réserver pour autant le jeu à une élite de speedrunners surentrainés. C'est ce qui faisait en '90 la différence entre Super Mario Bros et Great Giana Sisters.

C'est le genre de subtilité que je n'ai pas pu me permettre avec mes jeux BASIC et qui faisait pester les testeurs potentiels parce que le saut s'interrompait net alors qu'il passait presque. Le genre de subtilité avec lesquelles RSD Game-Maker ne s'embêtait pas et qui explique que Badman puisse filer le long d'un plafond défiant la balistique.

Le problème existe toujours avec GEDS, que ce soit en stoppand net le père Noël de la démo git ou en vous freinant pour rien pendant une ascension périllieuse dans le niveau secret de School Rush. Et donc, depuis aussi loin que j'ai un cahier-agenda, j'ai une page avec une petite note sur ce qui pourrait permettre de se coder ça pour le prochain jeu Bilou. Une page généralement couverte d'interrogations et assez pauvre en idées...

So as you can guess, I'm trying to find a solution to make that work with Bilou in my next game, but to be honest, there haven't been many ideas on the many pages dedicated to the topic in my notebooks. Then two things happened more or less on the same month. I've watched Wye's video showing the interaction points for Super Mario World and I got the idea of having a dedicated state for navigating around a block in my game engine. Which came first, I couldn't really tell any more. Unfortunately.

See, the idea so far was to have an around controller that would be part of the chain of micro-behaviours when Bilou's jumping. But what if we keep that chain unchanged, let the FAIL condition happen, and then check the testpoint and decide whether we could try moving around the blocking ceiling or not.

Mais ça va peut-être enfin changer si je prends le problème par un autre bout: plutôt que de faire un contrôleur qui anticipe la collision et déplace le joueur pour éviter que le contrôleur gravity ne signale un échec, je pourrais utiliser un contrôleur capable de nous diriger pour nous remettre dans l'axe après que la collision ait été détectée.

Une fois qu'il est à nouveau possible de monter, le contrôleur around nous en informerait par un évènement et on en profiterait pour restaurer la vitesse de Bilou au moment où il avait cogné le bloc.

We wouldn't try moving around if a testpoint located above Bilou is in a wall. That's the equivalent of Mario's head interaction point.

  • The new controller would tell us whether to align left or right by acting instead of the dpad controller.
  • It could report a failure if we're too far away for alignment or if we still cannot keep jumping after alignment happens -- that never happens to Mario because he's a bit narrower than one (16-pixels) block, but tiles in Bilou's world are 8x8.
  • It wouldn't have to compensate for vertical speed or gravity because you'd use it in a state where gravity does not apply.
  • It would fire an event once alignment conditions are met 

Granted, the behaviour will not be frame-perfect that of Super Mario, but it could be satisfying nevertheless, so it's worth giving it a try, imho.

Chose amusante: le point de "repousse" se trouve au niveau du nez de Mario. Notez que même une fois réaligné, le sprite déborde toujours par-devant le bloc. Et le point qui teste si sa tête a rencontré un bloc est pile entre ses deux yeux.

Bien sûr, avec l'approche que je propose, on aura pas le même comportement à la frame près: Bilou marquera un temps d'arrêt le temps qu'on le repousse. Il faudra tester ce que ça donne pour voir si c'est gênant ou non. Au pire, on ajustera un peu avec l'animation ...

So why reinventing the wheel, you wonder ? why insisting on using cando() while interaction points make things simpler ? well ... because the wheel of Super Mario World is far from being flawless. The gameplay it leads to may be an ideal to reach, but the quality of implementation belongs to the past.

Saturday, June 21, 2025

Les portes ... prochain vrai objectif

C'est ce qu'on pouvait lire en mars sur une de mes pages d'agenda et en avril sur mastodon. Et c'est toujours d'actualité, bien que j'envisage de faire d'abord un essai des éléments de base de leur implémentation sur un le bonus qui rend des points de vie ... Si vous avez un peu essayé la dernière démo, vous avez sans doute été surpris par un brusque changement de niveau dès que vous vous approchez un peu trop d'un truc en forme d'ouverture. C'est clairement quelque-chose que je voudrais améliorer.

La bonne nouvelle, c'est qu'en fait, j'ai déjà la moitié du travail: enregistrer la position actuelle dans des variables. Et voici la deuxième partie: se diriger vers les coordonnées enregistrées.

Bilou's Adventure maps have doors... you know, the kind that are located at some point on the map and will near-instant put you somewhere else on the map. So I'd like "Bilou Dreamland" to have doors as well... That will require a bit more effort in the GEDS environment that can't simply do ROOM=12 : xbilou=100 : ybilou=100. So i've got this nice tree stump sketch in my agenda since at least March'25, and I've been twisting my mind around the issue of how to make it work with state machines and collisions and linked game objects.

Now, my Basic games typically struggled to extend beyond one level. At best, I'd chain-load the next level which would happen to look a lot like the previous one (or not) by sharing lot of code thanks to copy-pasta... And entering a door would typically freeze everything as the game had entered a dedicated micro-script that ignored everything but entering the door. 

L'idée générale, c'est donc d'avoir deux "personnages" pour une porte, l'un représentant le point d'entrée et l'autre le point de sortie. Le mécanisme d'attache qui permet à Spongebop de rester pendue à son clou peut aussi servir pour lier les portes. Bilou, lui, se liera à la porte "entrée", et la suit de la même façon que dumblador suit Bilou quand il le transporte.

The overall idea is to have two game objects involved in a door-to-door transit: one being the incoming door, and the other being the target location. There will be a one-way link between them in the level script. As part of the 'entering' trigger, Bilou would attach to the input door, which is itself attached to a target GOB. Using that to transport Bilou to the destination should work quite nicely: it's been years that tracking the attached object works nicely. The question is "how do I send back the door once Bilou has left?"

I cannot just "track an object left at the original position", because so far, the engine only track *one* object at a time. But I could record the position before leaving, and -- with the help of a new controller -- track that position. In fact, I already have such "record position" behaviour as part of the "grid" controller used by bouncy branch and furblock.

Coding directly such a multi-step mechanics didn't sound a wise move to me, but I had an animation for the health power-up that made it circle around ... and a notebook entry suggesting to do that with lines of code rather than lines of pixels. I'll save the introduction of an invisible permanent object to circle around if I inject "reccoords" and "track(recorded)" in that health pick-up ... which has just been completed today. 

Voilà donc un premier pas franchi: ce petit point bleu volant a enregistré sa position d'origine comme l'aurait fait une porte et est en train de se servir du nouveau contrôleur pour s'orienter et graviter autour. 

Bon, et se faire transporter ne sera pas tout: je voudrais aussi qu'on ait l'impression que Bilou *rentre* dans la porte avant le transport. Quelque-chose de plus convaincant que le simple décalage vers le noir de la version BASIC où appuyer sur "haut" un peu trop à gauche ou à droite nous enverrait à travers le chambranle, la main devenue noire de Bilou ressemblant à un trou de trop dans le mur :P  

And I must admit I injected significant time in thinking how Bilou would *enter* the door. I know it isn't required to see him walk into the door like Bubsy did, and likely the spin at the start isn't strictly required either, but I intend to use it as the excuse to align Bilou with the door such that I can later fade him to black without having a Bilou-shaped hole dug into the wall (QBilou.bas did that ^^) nor require pixel-precise location to activate the door (Super Princess Peach did that >_<)

edit: If I give the engine one extra opcode to "attach to the object that object is attached to", then all those extra steps about the "door" acting as a flying carpet that takes you to a given destination and then goes back to its anchor location becomes useless...

Saturday, March 01, 2025

Pas si circulaire ...

Bon, j'essaie de mettre au point le fait de s'accrocher aux racines, et ça malgré le fait que j'ai noté quelque part "oui, ça ne marche pas parfaitement, mais c'est amplement suffisant pour faire le tour des niveaux sans ce prendre la tête".

C'est sans doute ce que je ferai dès demain, mais il faudra que j'y revienne et que je corrige un peu tout ça. Un composant "reste dans le cercle" avec un comportement cahotique, c'est marrant pour SpongeBop à cause de son élastique ... mais pour les lianes qui pendent ? les signets ? les ponts ? les boss ?

Technically, it would be nice to have Bilou reusing the "stay within radius" behaviour of SpongeBop when he's hanging at a root. Just have a smaller radius, show his hands grasping the root and voilà (oh, and remove the white polygons, please). That would work if that RadiusController wasn't randomly jerking up. Jerky monster with funny tik-tokking eyes is fun. But a jerky bookmark ? A jerky vine ? that looks suspiciously close to a bug to me

I had already fixed a more serious bug last week, and somewhere on some note book, I wrote down that "jerkiness shouldn't hinder levels traversal. Keep it as is and keep going". And yet there I am. Maybe this number shouldn't be that high ? Maybe that thing is wrong ... What does it look like in DDD?

Je vous ajoute deux petites capture-gif pour que vous vous rendiez compte si vous n'êtes pas allés vous promener sur mastodon ces derniers temps ... une où ça va pas trop mal (ci-dessous) et une ou ça part dans tous les sens (ci-contre)

Dans les deux cas, je ne donne aucunes consignes avec la manette. c'est juste "l'énergie de départ" qui est hors contrôle ... ou un problème d'arrondis qui s'accumulent ... ou quelque-chose de plus fondamental.

J'ai fini par rajouter un printf("%vx,vy + %corr_vx,corr_vy @%extra_radius") dans le code et faire cracher des tonnes de chiffres pendant que ça partait dans tous les sens (le debugging step-by-step, sur un problème comme ça ne donnait rien). Contrairement à ce à quoi je me serais attendu, on a très peu de "brusque augmentation du vecteur-vitesse" ... par contre, on a régulièrement un vecteur plutôt important (correction d'1 ou 2 pixels) parfois pendant 2 frames d'affilée. Dans un setup où la gravité met 8 frames à augmenter d'1px/frame, ça veut dire que Bilou va facilement nous faire un petit bond de la taille d'un caillou quand ça se produit.

The 2 screenshots above show the state as of ScreenshotSaturday, 5PM. I guess I don't have to convince you that it would look broken, if the game was doing that while you're not even pressing any button of your DS. I added print statement, revealing adjustments performed to stay within the radius (step-by-step debugging doesn't really work for such use cases), and even shooting a video of those lines so that I could time-travel and see what were the causes of sudden bumps... Except that there were no "sudden huge speed". Instead, there were multiple frames with 1 or 2 pixel-per-frame corrections, but that was already fairly strong for 1/8th-of-a-pixel-per-frame gravity. At 8PM, I had given up: it would require a complete rewrite to get stable behaviour, for sure.

Alors voilà ... j'ai copié le code de RadiusController::think dans un carnet pour pouvoir le comprendre et l'annoter ... j'ai voyagé dans le temps avec les captures .gif et analysé les chiffres que mon print avait produit et ça me donne le sentiment un peu désagréable qu'il n'y a rien de corrigeable dans ce code, parce que l'impact sur la vitesse persiste plus longtemps. Peut-être faudrait-il corriger directement la position, mais alors on perdrait la transformation de la chute en un mouvement de balancier...

edit: vous l'avez lu, j'étais sur le point de jeter l'éponge ... puis le lendemain matin, j'ai voulu tenter quelque-chose quand-même: et si les valeurs dx et dy que j'utilise pour vérifier si dx²+dy²<radius² n'étaient pas exprimées en pixels mais en subpixels ... pas en 256èmes comme la vitesse parce qu'il faudra quand-même les multiplier et que ça ne déborde pas ... mais des 16èmes de pixels ? Eh bien, avec ça, ça donne quelque-chose de beaucoup plus convaincant... je vous remet une mini-animation sur le côté. Il y a un peu de vibration résiduelle mais rien de vraiment choquant. Et ça malgré que Bilou partait avec un mouvement du genre à faire des bonds dans tous les sens au commit précédent.

But as I started my Sunday, I wanted to try something before rolling back to where I was on Friday: adjust the algorithm so that it would work with sub-pixel precision. 16th of pixels, to be precise, just the intermediate between pixel coordinates and current 256th of pixels used for speeds and entity positions by the engine. And ... well ... it turns out I now have something that converges towards a stable state. It's a bit sad for Spongebop... I'll have to try and find a way to turn of stabilization for them ^^".

Il me reste à trouver un moyen de rendre ça paramétrable, des signets qui ne soient pas élastiques et des spongebop qui le soient (la pauvre, obliger de circuler le long d'un parfait arc de cercle, c'est vraiment la dictature de SquareRoot ... je ne le lui souhaite pas).

edit²: le changement d'échelle (subpixel 12.4) suffit à lui seul pour avoir une éponge qui suit une trajectoire toute circulaire ... mais pour Bilou qui peut débarquer avec un vecteur-vitesse quelconque, il faut bien tous les petits ajustements. ça sent le code split, parce qu'il n'y aura rien à paramétrer ...

Sunday, January 21, 2024

De l'eau par ci, de l'eau par là ...

Tentons donc de nager. La première chose serait de pouvoir stabiliser Bilou à la surface sans l'immobiliser pour autant. Ce n'est pas impossible parce que j'ai une bande de 2 tiles à la surface qui est à la fois de l'air et de l'eau. Une ruse pour que Bilou-qui-coule puisse succéder à Bilou-qui-tombait et que la dernière position valide pour l'un soit aussi une position valide pour l'autre. Bilou-qui-flotte à la surface devrait donc éviter d'entrer dans une zone qui n'est que de l'eau ou dans une zone qui n'est que de l'air ? Il lui faudrait pour ça un contrôleur dédié ?

props: 0fc8
props: 8fc4
props: 8fcc
props: 8fcc
using swim
using gravity
using gravity
using float (?)

So, switching between "fall down" and "pushed up by the water" is not quite satisfying to emulate "floating at the surface". Partly because that means every transition between the two resets the animation. Mostly because how leaving water is notified and how that prevents DPAD events to be notified, making things like 'jump out' or 'switch to swim-left' impossible. So I spent time now and then during the week to figure out what I should do to get the desired effect. I do have a row of tiles that are both air and water... could it be enough to try and confine Bilou there when he's floating ? That wouldn't be impossible, but Bilou is 13 pixels high and the row only 16. Not much headroom ...

Mais en fait, ça s'est avéré encore plus simple que ça. J'avais entre-temps réalisé qu'il serait peut-être suffisant de faire tomber bilou-qui-flotte s'il est tout entier dans la bande de surface et de le faire monter s'il est bas dans cette bande ou s'il a commencé à s'enfoncer dans l'eau. Mais en testant, il s'avère que juste "tirer vers le bas dans la bande-surface, pousser vers le haut si on est ne serait-ce que d'un pixel dans la partie que-de-l'eau" donne le résultat qui me convient. Les mouvements de Bilou sont souples et amples, son animation n'est pas interrompue inutilement et sa position est pertinente par rapport aux graphismes.

Hopefully, it turns out that I only need that area for the 'pull down' part of the move. Pushing up can happen anywhere in water because this is the default behaviour in water. I had plan for an extra "surface position" parameter in swim controller instead of a new float controller, but it turned out that was useless as well because the default position (where Bilou is completely in the 'both' row) is just what I need given current graphics.


 

That seemed proper time to try the new 'swim right' and 'swim left' animations inspired by Fury of the Furries. But there I got annoyed again by how other controllers "steal" the focus of an earlier event. This time, the DPAD event notifying that I've pressed LEFT got replaced by an event mentioning that speed changed direction. It did not happen when pressing RIGHT because positive speed to the right and null speed at rest appear to have the same sign.

I cannot possibly express how satisfying it is for me to see that little animation coming to life and respond to my left/right/left/right keypresses. I guess I'm glad I kept up with gamedev so far ^_^

Saturday, November 18, 2023

tile 4 { swim.flow = (256,0) }


Enfin! Je m'attaque enfin à la dernière face de mon 'newmeta/newmap': les tiles spéciaux. Il y avait déjà les blocs spéciaux, auxquels on peut attacher des zones de collision et des actions. Il y a les pentes qui se passent de commentaires et les tiles aux propriétés "directes" qui permettent de combiner jusqu'à 6 propriété distincte (eau, sol, air, lianes, ...) librement. 

Dans le cas des "nouveaux" tiles, le script définissant le jeu va pouvoir encoder librement les propriétés voulues pour chaque type de tile. J'aime y penser comme à un accès indirect, mais c'est probablement parce que j'ai fait trop d'assembleur :-P. Et ça ne s'arrête pas là: je veux les utiliser pour les tapis roulants, le sol qui glisse, et ce genre de choses. Chaque type permet donc aussi d'aller paramétrer des valeurs le concernant auprès des différents contrôleurs.

En pratique, on va définir dans un fichier script.gam

tile 8 {
    is flowdn "0055220000552200"
    props fc8 # WATER
    swim.flow = (0,512)
}

La première commande dans le block, is est utilisée dans l'éditeur de niveau, pour fixer le graphisme représentant le type de tile. La commande props donne les fameuses propriétés indirectes. Ces deux-là existent aussi pour les blocs interactifs. La dernière sera passée à une nouvelle fonction SwimControllerFactory::setTileVariable() qui s'occupera de tout ce qu'il y a derrière le signe = et enregistrera le "mouvement forcé" à appliquer dans GobSwimController::think() quand on se trouve sur ce genre de tile.

Hello. I've been writing notes about how to have conveyers and flow-in-water since at least 2020 2019. Now is the time to get it done. At last. The syntax of the new "tile" description will look as much as possible to that of the "block" description, used for collectibles and more. Like them, it can describe the value of cando() flags to be used by controllers with a props statement.

What only they can do is set values for 'controllers variable'. Say that we want water to be able to push Bilou in some direction while he's swimming, we need a table of swim::flowx and swim::flowy that indicate how much Bilou should be moved at each frame if he stays on the given tile.

After some refactoring of the iWorld class and some more code in the script parser, this is finally possible. And with some bugfixes on the level editor, I've got a test case coded for the "three rooms" demo where Bilou is moved away from the waterfall because tiles say so.

Quelque jours plus tard, j'ai enfin ajouté le code qu'il faut au contrôleur utilisé pour la nage, téléchargé une nouvelle map avec des tiles "pousseurs" sous la cascade, et voilà: une première mise en application du concept où Bilou, tel un Fury, se fait embarquer vers le fond, puis un poil sur le côté avant d'être recraché vers le haut par les remous...

Friday, March 17, 2023

Conveyed ...

It's not a surprise (or it shouldn't) if there are waterfalls and sandfalls in the Three-rooms demo. And especially, if there is ground between two of them. I want my game engine to be able to 'push' you when you're on some ground, like it would if the ground was actually a conveyer belt. And it's been a few years now that using sand/water falls for that integrates better than mere mechanical belts in most levels. 

I have notes in my notebook for quite some times, too, about how the game script should indicate what those blocks do. They're not quite "special blocks" (that interact with collision code), but rather "physical types" that could be polled by frame-per-frame controllers.

I'm not completely satisfied with the proposed syntax, though. I'd rather use type %d {...} and is %s "%x" for level editor identification (like for block %d {} describing interactive special blocks), and I'd use props %x, like we already have for special blocks.

The truly innovative part is %s.%s = ... pattern to setup variables into controller factories. That one will be a bit more complex to get running, because the map of factories is actually managed directly by the GobState class, and I'd rather not re-inforce the Using... anti-pattern here.


Wednesday, July 27, 2022

Oh!? A post! A shell !? Progress ?

I know it's been a long time. Would you like an explanation ? It's a nice one, with Persian princes and oversea travels and unicorns. Maybe even a dragon!

Anyway, I finally got some code refactory completed so that more 'controllers' can record impact speed into script-friendly variables. That at last allow me to code whether a scorpeye shell should bounce or not when it can no longer keep moving the way it was.

Salut! Vous êtes toujours là ? Bien! Merci ^_^ Allons-y, alors. J'ai enfin repris mon projet NDS, finalisé cette classe GobImpactController dont dérive maintenant GobGravityController, mais aussi GobFreemoveController, ce qui devrait (enfin) permettre à cette satanée carapace de scorpion de faire demi-tour quand elle se prend un mur.

Enfin, ça aurait suffi sur un sol lisse et infini. Mais j'avais justement un trou dans mon miniveau de test, j'ai donc pu chipoter un peu plus avec les testpoints, pester sur le fait que le contrôleur de chutes signale un event quand on se prend un mur (plutôt que d'annoncer l'échec du mouvement, vu qu'on peut toujours continuer à tomber ... dans un sens, c'est logique).

Je vous aurais bien mis une vidéo de tout ça, mais à 1Mo la vidéo de 10 secondes ... les plus irréductibles sont invités à la regarder sur twitter.

Oh, granted, there's been pitfalls. The fact that moving along the ground fails when you hit a wall while falling down and hitting a wall just creates an event, wasn't exactly welcome-back-to-coding-friendly.

But well, there it is. There it bounces. Unless you throw it straight into a floor+wall corner or on some odd location on the sand. I'll need more runME+InspectorWidget to find out what is going on there. Or maybe some more muad'dibugging ?

Wednesday, May 11, 2022

freemove ou pas

Bon, le week-end était bien chargé et la semaine qui commence risque d'être du même accabit, mais j'avais quand même trouvé le temps de modifier la configuration de runMe pour corriger l'affichage des sprites 32x16 et du même coup pouvoir utiliser InspectorWidget convenablement. Il est temps que je trouve pourquoi les carapaces de Scorpeye ne font pas demi-tour quand elles rencontrent un mur.

Et on dirait bien qu'une des raisons, c'est que j'ai utilisé pour cet état-là le contrôleur "freemove". (oui. encore;) Et freemove n'a pas le code C++ qu'il faut pour 'rapporter' la vitesse à laquelle on se déplaçait au moment où une collision avec le terrain a empéché un déplacement d'avoir lieu. Or c'est cette valeur qu'il faut utiliser pour faire le demi-tour.

Despite a week-end with a good deal of events, I managed to fix runME so that it could too display 32x16 pixels sprites properly. That unlocked the use of InspectorWidget to find out why scorpeye shells won't bounce when they hit a wall.

Apparently, the core reason for that is that the GobFreemoveController I use for sliding shells is unable to tell at what speed it was moving when there had been an impact with the wall. As a consequence, the script handling state transitions cannot properly program the new speed. And yes, that is very similar to an issue I've had with 'swimming' state for Bilou not so long ago. That sounds like I should refactor something so more state controllers can report impact speed...

Bref, soit un contrôleur comme 'walker' ferait l'affaire, soit il faut que je prévoie quelque-chose d'autre. peut-être que 'sauver la vitesse actuelle si le déplacement en cours n'est plus possible' devrait en soi être un contrôleur autonome dans la chaîne ?

Ou je met une vitesse 'hard-codée' pour l'instant ?
 

Wednesday, January 12, 2022

Slopes Landed.

I think I got it working. There was one major flaw in my earlier design: stating that you can F_FALLTRHU a slope implied that you could no longer walk on it, as the walking controller tests for solid ground by checking whether it would be possible to fall down from the current location. Oh, not much. Just one pixel is enough to claim that you cannot walk anymore.

But the technique used for terrain collision detection -- cando() -- assumes that we only do a move if we can do it over all the tiles covered during the move. That means the slope tiles should both allow us to fall through them (until ground height, at least), and not allow to start falling through them. To get that solved, I had to split the flag, having one bit telling whether we can start falling (F_START_FALLING) and one telling whether we can keep falling. Walker controller tests one of these bits, gravity controller tests the other one.

Then I had another issue, not properly computing the ground distance to see whether the move we cando actually remained over the ground. Let Bouli explain that...

We were at old position (ox, oy) and will move our 'hot spot' (the one that is kept in contact with the ground on uneven grounds) to (hx,hy). In order to know whether we're find with slope-landing, we compare hy - oy with the 'ground distance', which is construct with an appropriate sum of tile.groundheight() calls.

But groundheight() gives us a value relative to the bottom of the corresponding tile. -8 means the whole tile is solid. -2 means the first 2 pixels of the tile are solid, the rest is air. 0 means the whole tile is air. That was quite quickly remembered and accounted for. The other part to take into account is that the start of the darkblue 'vertical motion vector' may be anywhere within the first tile. If we're in the 4th pixel of the tile and the last pixel of the tile is solid, then only hy - oy < 3 are uninterrupted moves.


Tuesday, January 28, 2020

Meka-Bilou au rapport ...

J.L.N s'est beaucoup intéressé à ce que je faisais, ce.tte.s dernière.s semaine.s sur mon ordinateur. Il y avait régulièrement une espèce de mini-niveau (en ASCII art) dans un coin de mon écran qui accompagne les rapports d'erreur du système de test des terrains pentus. Je suppose que ça attirait son attention.

Difficile d'expliquer le principe du unit-testing à un louloup de 7 ans, mais il y avait aussi mon carnet avec le même "niveau" et un bilou-mécanique prêt à le traverser. "Oh oui, c'est le tic-tac-Bilou de parrain! Tu mettras aussi celui avec un réacteur?"

Il ne croyait pas si bien dire. Après avoir reporté des paquets de coordonnées sur un schéma du 'niveau' et analysé dans ddd à quel étapes de la fonction "doslopes()" elles correspondaient, j'ai déjà pu mettre en évidence (et corriger) quelques couacs. Le fait par exemple que doslopes n'indiquaient "on est sur une pente" que si le dernier tile visité est pentu. Malheureusement, ça signifiait un glitch vertical au moment de passer sur le 'sol plat' à la fin d'une pente à plus grande vitesse parce que le code du GobController qui fait appel à doslopes pensait devoir "éviter un sursaut brusque"...

"Will you also put the rocket-meka-Bilou in your test ?" asked my 7-y-o seeing my debug notes for the on-going slopes unit test. He was closer to the reality than what the clockwork-Bilou sketch suggested. The virtual-meka-tester is now zooming at 8 pixels/frame and no longer detects it should start going down. But then the GobController in charge of 'walk-on-the-ground' detects there's no ground anymore and triggers a FAIL event. It should trigger a state change according to the state machine, but MekaBilou has none.

Now here's the catch: the GobController has not cancelled its move, and over every next frame, it will start flying off (so much for the little wheels I'd drawn) and only the 'killer' tiles I put in the sky can stop it. I'll need some more code to interupt tests when unexpected state transitions occur, apparently.

Mais le plus curieux m'attendait encore. Lancé à presque 8 pixels / frame voilà Meka-Bilou arrivé en haut de la pente, et par un malencontreux concours de circonstance (plus un p'tit bug), il ne détecte pas qu'il devrait redescendre. Le code du GobController, lui, constate bien qu'il n'y a plus moyen de se déplacer normalement sur le sol et génère un FAIL (qui doit normalement provoquer un changement d'état dans le comportement du personnage). Sauf que, désolé, les amis: meka-Bilou n'a pas de machine d'état, et le contrôleur n'a pas annulé le mouvement (il était possible: on ne rentrait pas dans un mur). Du coup, rien n'empêche le même mouvement d'avoir lieu au(x) cycle(s) suivant(s). Faisant fi de ses "roulettes", Meka-Bilou s'est mis à traverser le ciel à toute allure jusqu'à ce qu'il soit stoppé net par un 't'as rien à faire là' qui met fin au test.

Un peu de code en plus, et je peux à présent capturer les transitions 'on fail' dans mes cas de tests et tout arrêter quand ça se produit. Et ça me fait penser que, quand j'aurai réussi à importer le comportement des applemen et autre dumbladors dans mon environnement de tests, ça pourrait être intéressant de marquer certaines portions de tests plus sophistiqués comme "interdiction de tomber ici", "interdiction d'atterrir là" ...

Friday, June 29, 2018

Grand nettoyage de printemps ?

Bon, j'ai presque fini avec la révision des "évènements" provenant des contrôleurs de comportement (juste encore un peu de cleanup). Les histoires de signe sont réglées, Bilou fait à nouveau ses pirouettes comme il faut... et oui, j'ai encore fait du débugging avec des p'tits dessins.

Le dernier sur la liste des "grands nettoyages de printemps" devrait être l'élimination de GobExpression::xcontext, et je devrais avoir quelques notes là-dedans sur mon boox.

Après ça, il sera temps de tourner la page (parce que ça devient limite trop long, comme "printemps") vers de nouvelles aventures. J'ai bien progressé dans les recherches sur l'évolution du langage de scripting. Suis-je prêt pour attaquer le "behaviour editor on DS" ?

I'm almost done with revision of the events-from-controllers effort. Bilou at last does his sommersaults when expected ... and yes, I've been drawing while debugging again (that's one of my favourite part of gamedev ^_^). Finally, I'll be able to get rid of the infamous "GobExpression::xcontext" static array. That should conclude the "spring code cleanup", so I'll be free to move on.

What next ? Script language revision research made nice progress lately ... am I ready to start "Behaviour Editor on DS" ?

Friday, June 08, 2018

GameObject::useEvent() should go away.

https://sourceforge.net/p/dsgametools/hg/ci/refactory-engine/tree/libgeds/include/GameObject.h#l175
That shouldn't happen. The way controllers fire an event is not satisfying. A static pointer set by class X so that it is used by class Y with no restriction on who does what and that merely works because we know X calling ::useEvent() and Y checking *::doevents happens to take place with the right timing ? No.

I mean, look at the documentation: "assumes no re-entrance until gobRunController". That has turned false the minute I introduced 'attach-to-other-game-object' feature where you might have to run the object you're attached to before you can run yourself.

I'd like to convert {NONE, FAIL, EVENT}  enum into something else that allow "EVENT" to carry the list of transitions to check by itself.

Wednesday, April 04, 2018

Tutoriel libgeds - jour 5



Redonner du mouvement au personnage dans geds, ça correspond à spécifier une série de contrôleurs pour l'état choisi. Chaque contrôleur a une mission bien précise, p.ex. ici

Code:
state0 :anim1 {
   using dpad
   using momentum(x to 512)
   using momentum(y to 512)
}
dpad va lire les registres de la console et sauver les directions
momentum va utiliser les directions sauvées pour augmenter ou diminuer la vitesse horizontale ou verticale (selon qu'on a utilisé "x" ou "y")

On peut aussi passer des paramètres aux contrôleurs: c'est le cas ici du "512" qu'il faut interpréter comme un nombre de 256emes de pixels par frame (1/60eme de seconde) et qui représente la vitesse maximale autorisée sur un axe.

Le ScriptParser cherchera les classes C++ correspondantes et fait le nécessaire pour que le code qu'elles contiennent soient appelées à chaque image générée par le jeu.

Trois lignes de plus dans le script donc (et quelques modifications dans les Makefiles). C'est tout.

Thursday, September 21, 2017

NExt (last?) steps on School Rush

No real "todo item" identified from last week-end' playtesting session, except one funny idea of using a special feature of the NDS' sprite hardware so that we can see Bilou while he's swimming up the ink.

I've got a few other things to do, though. Some editing on the map, some debugging on the inkjets, but mostly, a way to animate what the pipes when Bilou disable them.


Je me suis retrouvé un peu "tout bête" à ne pas avoir de véritable chose à corriger après la petite scéance de playtesting de du week-end dernier. Qu'à celà ne tienne: il y a quelques détails qui restent encore à améliorer sur le dernier niveau, et en particulier faire en sorte de pouvoir animer l'arrêt du flux d'encre quand on rebouche un bouchon. Je pense bien utiliser les polygones: ça fait parfaitement l'affaire. tout ce qu'il me manqu(ait), c'est un bout de code qui dessine un rectangle noir entre deux objets du jeu, et un peu de script pour lier le tout.

So let's go for a new "GobController" that renders some polygons between two objects and don't do anything else. Ideally, the "circular" controller used to swing spongebops could be cleaned of OpenGL instructions and once I'll have a 3D object editor, I'd be able to name which 3D object should be used as the link between any two attached objects. But we're not there yet.

Ce n'est pas franchement le genre de programmation qui fait plaisir: assez bien de copier-coller, pas franchement le bon rôle (c'est un contrôleur, et on fait de l'affichage >_<), etc. Je reviendrai là-dessus quand j'aurai bouclé le jeu et que j'aurai un peu avancé sur mon projet d'éditeur d'objets 3D sur la DS.

Ah oui. Il y a un autre élément qui serait sympa: faire en sorte qu'on puisse voir Bilou nager hors de l'encre. Point de vue technique, j'ai ma petite idée, mais ce n'est franchement pas prioritaire.

edit: good news, if you want an invisible sprite for some reason, you don't have to devote another blank tile for that. Just 'naming' an empty slot of any SpritePage will do. For some reason ... which I'll have to understand ^^"

Saturday, June 21, 2014

Et zou.

Cette fois, je pense que j'y suis. Il m'aura finalement fallu sortir l'ensemble de mes techniques pour que cette histoire de lancer de taille-crayons empilés fonctionne correctement. Pas de demie-mesure:

  • un nouveau contrôleur, "gobbit" capable de produire un évènement pour signaler le changement de valeur d'une variable -- désolidarisé donc du copycoords dans le plus pur esprit "micro-contrôleurs enchainés"
  • un modificateur, F_ATTached, pour que seuls les GOBs attachés au déclencheur de la collision puisse la recevoir. 
  • Les collisions sont toujours utilisées pour provoquer le jet de dumblador: c'est la seule façon de permettre de "passer" des arguments d'un GOB à l'autre. Les évènements "gobbit" ne sont là que pour forcer les deux -- lanceur et lancé -- à rester synchronisés quoi qu'il arrive. Bilou ne peut plus se retrouver "mains en l'air" alors que son taille-crayon s'est fait la malle, et ses "impulsions de jet" ou de ramassage ne risquent plus d'être mal interprétées comme des pieds baladeurs.
It's been a hard day's night. And I've been coding like a dog ... At last, I can safely pick up and throw bladors even though they're stacked up. I initially thought a few alterations to the copycoords controller would do it and I end up with a combination of an all-new test-a-bit-in-your-attach-target controller and a filter that makes areas only collide when Gobs are attached to each other. But at least, that allows me to keep both states synchronized and got me rid of those "not quite thrown, sorry, but you'll have to get hurt before you can use your hands again" glitches.

PS: J'imagine que ça va encore sembler "beaucoup de complications pour quelque-chose de simple", mais la richesse du gameplay que j'envisage repose beaucoup sur le nombre d'interactions possibles entre les éléments du jeu. De même que le fait de passer de dangereux (en marche) à inoffensif (dans sa carapace) puis à utile (lancée), puis de nouveau à dangereux (demi-tour) rend le Koopa-Troopa génial, c'est la richesse des états que peut prendre "dumblador" sur laquelle je parie pour faire de la school zone un niveau intéressant dans Bilou's adventure.

If that feels like much work for a small modification of the behaviour, I invite you to read the "interplay" posts of R. Terrel on the critical gaming blog. I expect higher interplay with monsters in the school zone to highly increase the interest of my game under progress.

Monday, January 13, 2014

Jump-bounce win.

Participation modérée, mais préférence marquante pour le Bilou-rebondisseur. J'ai moi-même refait le test de désactiver les rebonds et me refaire les différents niveaux. Le "niveau en longueur" devient plus nerveux mais dans le niveau à explorer, j'ai l'impression que Bilou se fait systématiquement "aimanter" par le sol au moment du contact. Rien à faire: j'ai intégré ce petit rebond au personnage lui-même -- introduit dans les toutes premières démos.

The poll is over, massively speaking in favour of "bounce", and a slight preference for the extra "jump". That's quite a relief: I couldn't get convinced by Bilou stick-landing after a fall ... I've seen him bouncing for too long ^^"

RCramiro said:
The current bouncing implementation (i.e. [BIG]) works well as it is. The only issue I have, though, is that it's hard to tell when a given jump will cause Bilou to bounce. I suggest you provide some sort of visual indication beforehand, à la "Kirby's Dreamland" (if Kirby is shown falling head-first, that means he will bounce when he hits the ground).
That sounded like a good idea, and the good thing was that increase/decrease controllers can be used to generate an event "you're starting to fall too fast", which was just perfect for an extra anim and alternate camera settings. However, that's of little use for the player to know he's about to bounce if there's nothing he can do to prevent it: unlike Kirby, Bilou has no floating ability.

Ajouter une autre anim ... c'était vite fait, mais pas très efficace: contrairement à Kirby, Bilou n'est pas capable de se mettre à voler pour éviter une chute. 

I like how dropping from high up has an auto bounce when you land. I found out that if you jump off a spring like an erasure that after the land-bounce you can jump in mid air for a mini-double-jump.
Kirby Kid, qui teste uniqement le bounce-jump accroche, sans explications aucune.

Piek, lui, est plus terre-à-terre:
Oui... Le test... Comment dire ? Je surkiffe Mais je suis un fervent défenseur de la cause du No Bounce... Je trouve le gameplay déjà tellement riche que ce petit rebond, (admirable d'un point de vue technique d'ailleurs), provoque des situations infogramesques et nous fait perdre en pur contrôle...
Le contrôle ... tout est là. Il faut que le joueur puisse éviter un rebond-qui-tue, soit avec un rebond supplémentaire. C'était déjà l'idée du "bounce-jump", il me reste à la compléter. Première chose, faire rebondir Bilou quand il transporte un dumblador, ça donne moyennement. Je peux donc me permettre de passer en mode "no bounce" quand le joueur a trouvé quelque-chose à transporter. Il faudra donc choisir: garder le contrôle ou se débarasser du crayon d'en face.

Piek raised a significant point, though: the bounce is a loss of control. In tight situations in videogames, removing the control can lead to very annoying situations where the #1 rule of game design (whenever you fail, you know it's your fault) is left broken on the ground, and player has to try again with a scream of Infogramish frustration.

I can think of two ways to avoid that to become detrimental to the gameplay. First is to switch to no-bounce when Bilou carries something. Bouncing when you're carrying something as large as yourself ... even for a blue ball, that's excessive. Next, I added a small spin animation upon (L) button trigger coupled with the ability to "brake in the air".


Dernière touche, un p'tit bouton (L) pour faire une pirouette qui ralentit la chute ... on peut du coup aussi éviter un rebond malvenu ... ou l'accueillir avec sourire, presser à nouveau sur (A) pour rebondir mieux ou plus haut. Bien sûr, on est là au niveau du raffinement de gameplay. La bonne nouvelle, c'est que mes p'tits n'veux n'ont pas besoin de pousser jusque là pour s'amuser ni pour terminer les deux niveaux. J'ai gardé un oeil sur la partie, et je n'ai pas noté un seul faux pas lié à un rebond incontrôlé. Bien sûr, ils ont déjà pris le personnage en main depuis Toussaint.

Mais l'approche de Piek, combinée à sa proposition de faire plus de niveaux similaire au niveau d'intro, en distillant progressivement les nouveaux arrivants pourrait offrir un terrain idéal pour une entrée pour la NeoCompo 2014 (s'il y en a une).

Tuesday, May 07, 2013

One must FAIL.

I've been investigating that "stuck in walls" bug for some times now, with little luck to fix it. I'm finally reaching the conclusion that this is not an usual bug, but the bitter outcome of some short-coming in the current implementation of the game engine.

The behaviour of Bilou and NPCs in the game is ruled by some iGobController classes, such as DPAD processing, momentum, gravity and the like. At each frame, each of them think() to evaluate the current game state and adapt the character's state accordingly (e.g. make it fall faster in the case of gravity controller).

The outcome of this "think()" function in turn defines whether some transitions on the state machine should be evaluated. It may either be NONE (no transition involve, we happily stay in the current state), EVENT (something special happened, like the direction reverting or some key being pressed, for which an change in the animation might be desirable), and FAIL (impossible to hold the current state for longer, e.g. we've landed on the ground, there's no further falling possible).

J'ai cherché la cause de ce bug 'planté-dans-le-mur' si longtemps que j'en arrive à me dire que ce n'est pas un 'bug' au sens propre, mais le résultat malencontreux d'un moteur de jeu encore incomplet. Vous vous souvenez du code de gestion découpé en 'contrôleurs' que l'on enchaîne ?Parmi les signaux qu'un contrôleur peut émettre, il y a 'FAIL', indiquant que vu le déplacement demandé, le contrôleur actuel ne peut plus assurer le contrôle. C'est le cas notamment si on atteint le sol alors qu'on était sous la gestion de GravityController.

C'était un bon départ, mais pour construire des choses plus intéressante (des rebonds, notamment), il m'a fallu prendre en charge la vitesse d'impact, et aligner sur un mur/sol plutôt que d'annuler purement et simplement le mouvement en cas de FAIL. Mais à l'heure actuelle, mon code va parfois supprimer toute vitesse quand il aurait fallu en garder, et garder de la vitesse quand il aurait fallu la supprimer. Je vais donc devoir redéfinir la sémantique de FAIL: plus moyen de continuer avec ce contôleur, mais sans que ça ne signifie nécessairement qu'il n'y a aucun mouvement à cette frame-ci.

Initially, when Bilou FAILed to fall, it usually meant that the next move would take him into a wall, and so the move itself was cancelled. Yet it proved to be impractical alone. I had need for the impact speed so that e.g. I could decide to make Bilou bounce if the speed was high enough. Then I had need for aligning the move to the closest wall, and not simply cancel it.

All in all, the remaining code is killing speed where it should better not, and obviously not killing it where it would have to. That smells like some legacy code that need to be re-thought from cleaner base.
[done] FAIL => can't do more than this frame in this state. (but move isn't necessarily cancelled)
[done] no longer sticks on walls
[todo]  hspeed is reset to 0 when Bilou leaves a platform. That should only be the case if forced so by a GobExpression
[think] smoother slope-to-fall transition required.

Friday, July 13, 2012

transition animations

Jusqu'ici, chaque "état" du comportement de Bilou pouvait avoir sa propre animation. Tomber, marcher, sauter, finir le niveau, etc. Tout ça fonctionne très bien dans Apple Assault, mais avec mon nouvel éditeur d'animation, j'ai envie de profiter de la liberté accrue pour donner encore un peu plus vie à Bilou: pirouette au sommet du saut, demi-tour moins brusques, etc.

Mais là, les choses ne vont plus comme prévu. Il y a de curieux soubresauts dans l'animation du saut de Bilou, qui tient plus du numéro de claquettes aériennes à la Snoopy que d'une performance d'athlète, je trouve. Le problème ? eh bien, j'ai créé une animation "chute" qui fait la transition entre la dernière image du saut et la position traditionnelle de Bilou qui tombe, les 2 pieds en avant et les mains en l'air. Le hic, c'est que dès qu'on entre dans un nouvel état, l'animation de cet état est lancée dès le départ. Donc, dès que je fais faire demi-tour à Bilou pendant son saut, il recommence l'animation sauter/tomber. Idem si je relâche ou ré-enfonce le bouton de saut.

Not so long ago, I was still convinced that having one animation per state would be just enough. Maybe some tricks would be needed to pause the animation until a certain speed would be reach or so, so that you could have funny transitions like turning back or fall-and-crash vs. fall-and-land. After the first attempt of re-doing Bilou animations with AnimEDS, I have to face the truth: that wouldn't work properly, and adding "cosmetic states" just for the purpose of having the desired animations would be a real nightmare: the state machine describing Bilou's behaviour is already quite complex.

Bref, il me faut un nouveau type d'animation, des animations de transition, qui sont déclenchées quand on passe d'un état à un autre, pour ensuite céder le pas à l'animation prévue pour l'état de destination. En théorie, il serait possible d'émuler ça avec des états supplémentaires et des "quitter l'état X quand l'animation est finie", mais pour cette fois, ce serait introduire une complexité tout à fait inutile et un fameux méli-mélo quand il s'agira de trouver les bugs dans un comportement aussi complexe. Bref, c'est ma prochaine intervention sur le moteur de jeu: faire en sorte que "stateJL->stateJR on event [DPAD RIGHT &] () :anim9" soit compris et retoucher les animations en fonction.

What I really need, is the ability to assign a specific animation to a transition. Not only you've got anim X when Bilou is idle and anim Y when Bilou walks, but you have also anim Z that will play when you switch from idle to walk and anim Z' that plays when you switch from walk to idle. As soon as Z or Z' is done, it automatically resumes with Y or X (resp.), and you're already in the "walk" state when Z starts playing. If you switch from fall to idle, however, neither Z nor Z' is played. Maybe you'll use Z" for that.

I've proceeded to some sketch and UML reasoning, and I think I figured out how to start coding that. I can't wait for the house to be clean so that I can start experimenting with some libgeds improvement ^_^

Saturday, January 14, 2012

branch/companim

Rien de tel qu'un peu d'UML pour commencer la nouvelle branche du SVN "animation composée" (imho). Ah, mais peut-être voulez-vous un mot d'explication sur les "branches"? C'est l'équivalent pour un programmeur de "Dis, on va commencer par dupliquer la maison dans un univers parallèle avant d'attaquer les travaux pour la véranda. Comme ça, si on doit chercher les clés à un moment donné, on a qu'à le faire dans la copie de base. Et puis on peut laisser les enfants dormir dans celle-là, aussi: inutile de les envoyer dans la copie où on a abattu le mur du salon et où l'eau ne va plus jusqu'aux WC, hein ?"

Convaincus ?

I was quite confuse on where to start working on the compound anim support, so I just started by depicting the current situation into an UML blueprint, trying to precise which are the different phases of SimpleGob::play, which member variables where involved when, and where in the class hierarchy they stand. Part of my indecision came from the fact that the abstract class GameObject is designed to capture what controllers use, so I wasn't quite tempted to push up the state management there.

And to my suprise, that alone suffice to show me the right path to take: introduce a CommonGob class that capture what's not-in-GameObject but should be in all the technical variation of the animated objects.


Bon, première tâche dans cette branche, donc, c'est de refaire un peu l'état des lieux. Une animation composée, ça change essentiellement l'animation des GOBs, mais l'état, les contrôleurs, les collisions, tout ça reste identique. Ouais, sauf que jusqu'ici, tout ça est uniquement dans SimpleGob.

Une fois tout à plat sur ce joli "bluescreen" (excusez ma nostalgie d'ex-codeur en QuickBasic), la solution devient évidente: introduire une classe "CommonGob" qui regroupe tout ce dont SimpleGob et CompoundGob auront besoin dans leur fonctions "play" sans toucher au GameObject héréditaire endogène ... ce qui fera sans doute plaisir à BlockArea, accessoirement.

If you don't get a word of UML then ... well ... I guess the sketched-up version of a former, similar reflexion might help you to figure out what is this CompoundGob stuff all about.

Saturday, July 16, 2011

Implémenter les plate-formes.

Aah. De vraies vacances, ça fait du bien, même si ce n'est que quelques jours... qui se terminaient par un peu de baby-sitting à un mariage cet après-midi. L'occasion de refaire un peu le point sur les problème des plate-formes mobiles. Le point essentiel, c'est que -- tout comme le transport d'objets par Bilou -- ces plate-formes dépendent de la possibilité de lier un gob à un autre temporairement. Un micro-contrôleur "follow", donc, qui déplace p.ex. l'appleman à l'identique de Bilou.

At last some day off ... really off. Not even some Bilou thinking until this afternoon "_". And I had no documentation or current code state with me when doing so, which somehow explained why I focused on a fairly remote problem such as moving platforms. The last thoughts came to the conclusion that being carried would involve a dedicated "follow" micro-controller where a Gob is attached to another.

Be coherent
Comment s'assurer que la plate-forme aura déjà fait son déplacement au moment de déplacer ce qui s'est posé dessus ? Sans ça, on risque d'avoir des effets de "décalage" chaque fois que la plate-forme modifie sa vitesse, comme ceux qu'on peut observer dans Zool.

To make that work, however, it is mandatory that the carrying object has moved before the carried object's movement is evaluated. Otherwise, the player will experience zool-like glitches everytime the absolute speed of the carrier is altered. The FollowController must thus be able to detect whether there is an not-yet-processed carrier situation and execute anticipatively the "animation" of that carrier. That will require some more book-keeping at the core of Engine::animate(), but I think it'd be more flexible than pre-encoded priority levels.

Pour y parvenir, le mieux sera de faire en sorte que FollowController::think() puisse détecter si son objet-cible a déjà été exécuté ou non. On joue là au plus profond du moteur de jeu, qui appelle Animator::play() sur chaque objet qui s'est enregistré via reganim(). J'ai déjà une liste "pending" séparée de "todo", il me reste à noter au niveau de Animator lui-même où on en est. Après ça, il suffira de se faire un petit if (target.state==QUEUED) target.play(). L'objet-transporté voit alors son exécution interrompue le temps que l'objet-transporteur soit mis à jour.

Thou shall not follow the NULL pointer
Avec ce mécanisme, je vais introduire pour la toute première fois une référénce directe entre deux personnages du jeu. Jusque là, je passais systématiquement par le tableau GameScript::gob[] ou je me limitais à une interaction éphémère lors d'une collision. Si je ne fais rien de spécial, une plate-forme détruite pourrait amener les objets transportés dans un état incohérent, voire provoquer de sérieux problèmes au gestionnaire de mémoire ou planter sauvagement le jeu.

The second challenge I addressed is to ensure that we can handle the disappearing of the carrier transparently for the carried object(s). We can do that in different ways, some including list of cross-references, etc. but it looks like the best way around could be to delay actual Animator::DELETE requests by one frame so that the former carrier can be caught in DISCARDED state by FollowController::think() method that would drop then the reference.

Je pourrais exiger du "programmeur gobscript" qu'il règle ça lui-même en prévoyant des états-tampons ou des collisions de désolidarisation, mais ça signifierait qu'une erreur de script dans la machine d'état d'un objet pourrait se traduire en un dysfonctionnement du moteur lui-même... à proscrire à tout prix. Ca risque donc de me coûter un Engine::animate() un peu plus sophistiqué, mais l'idée est de garantir que tout objet "qui s'en va" sera présent au moins pendant une frame dans l'état "DISCARDED".