Tuesday, September 28, 2021

just another breakpoint in the wall

Since last week, I've been tweaking the state machine of my meka-tester trying to make it better mimmic the behaviour of Bilou when it gets into the walls. I finally get the kind of error I wanted, but it makes little sense.

. . .  Well, I initially wanted to tell you about how it suddenly hops into the wall, 4 pixels further than it was without ever seeing the 'building up' delayed move explain anything of that. but I feel so tired. s/4f.f, S/ffe6.0 ... I'd have to dig up my notebook (page 14) to decode what that means. I just can't. my eyes don't want to look at the screen anymore. See you later.

Pendant près de deux semaines, j'ai fait des essais et des ajustements pour avoir un meka-apple qui reproduise les bugs et-vlan-me-n'là-dans-l'mur que je rencontre systématiquement dès que j'essaie de jouer dans le nouveau niveau de mon fiston. J'ai fini par y parvenir, mais on ne peut pas dire que ça m'aide à comprendre ce qui se passe. Une téléportation de 4 pixels d'un coup, alors que tout semblait aller bien jusque là...

Un peu de repos, un peu d'astuce, et j'ai des pistes pour améliorer la situation. Mais alors que je refais un essai dans "Dreams.nds", je me rends compte que le problème est toujours là. Et il est très facile à reproduire manette en main sur ce niveau, en plus. Est-ce que j'ai tenté de faire du unit-testing trop tôt ?

<later> over the week, I managed to identify some issues and possibly fix some, but it is still possible (and actually easy) to trigger. 

It makes me feel like I tried to unit-test the issue too early. Maybe what I actually need is a way to get a bunch of data out of the emulator, and monitor them when I'm done reproducing the issue.

Let's see what we would need ...

Je change d'approche, du coup : il existe dans l'organisation de mes jeux une classe indépendante du Game Engine, mais qui a accès aux objets du Game Script et qui peut exécuter une méthode à chaque frame, le HUD. Si je fais tourner mon niveau dans un émulateur avec débuggeur, et si je rajoute un break pointau cas où Bilou serait arrivé dans un mur, je devrais pouvoir creuser le problème.

  • [done] access game object position and variables.
  • [done] record them, e.g. in the GameObjectState structure defined in unit-tests
  • [done] check whether game object got into a wall (cando(0,0, PLAYER_THRU)
  • [done] switch to 'investigation' mode when we're in a wall
  • track state changes and controllers reports (through a custom inspector)

edit:A class deriving from iHud met all the criterion above. If I'm okay with using ddd to inspect the content of the last GameObjectState array, I can start investigating ...

Sauf que ça n'a pas été si simple. Même en ré-important le code des tests qui enregistre les mouvements des dernières seconde de jeu, l'information restait trop sommaire pour pouvoir retracer pas à pas ce qui ne "marchait" pas au cœur de la fonction do-slopes.
Mais Murad-dib m'a sauvé la mise  (oui, depuis qu'on est allé voir Dune avec les collègues, je me suis replongé dans le bouquin.) Et si comme lui je balayais de la main toutes les règles et les conventions (du c++, ici, pas du C.H.O.M.)... si je prenais avant chaque appel à bilan.PlaY Une copie de la mémoire contenant l'objet 'Bilou' ... je pourrais en cas de mur réappeler 'play' sur la copie ! le moteur de jeu est ainsi fait qu'il n'y verrait que du feu, et je pourrais faire mon débugging pas à pas en étant sûr que je suis dans un cas où le bug va se manifester

It wasn't quite sufficient, unfortunately. Hopefully, I was reading Dune again, and going through the moment when Muad'Dib decides to break all the rules so he could get victory, I realised that I could go for Muad'dibugging too: create an empty GameObject in addition to the real one for Bilou, and memcpy a snapshot of the current state before every 'play()' call. If we turn out to end up in a wall, I could just call 'play()' on the copied state to reproduce step-by-step what the first one had encountered.

Of course, that goes against all established rules about how to deal with C++ instances, and make the 'NOCOPY(GameObject);' macro look like a fool. But it worked.

And at last, on 2021-10-13, 22:**, I think I nailed that stuck-in-the-wall bug that had been since my kid drew his pyramid level.
 

No comments: