Saturday, December 30, 2017

SchoolRush NY2018

https://sourceforge.net/projects/dsgametools/files/demo%20games/SchoolRush-NY2018.nds/downloadHappy New Year Everyone. I've got a new build of SchoolRush uploaded. Hope you'll enjoy it. For those of you who mastered the game, you'll discover the credits level and the hint towards the secret, vertical level that I've been working on half this year.

Prêts pour la nouvelle année ? Voici une version de Bilou: School Rush avec un niveau secret terminé, des images de chargement qui racontent l'histoire du jeu, la séquence de crédits ... Et pour ceux qui n'arriveraient pas encore jusque là, deux modifications qui rendent le jeu moins impitoyables: on peut "nager" hors de l'encre (encore faut-il pouvoir trouver une plate-forme où atterrir) et on grimpe automatiquement dans les encriers quand on tombe dessus, même si on tenait un taille-crayon entre les mains.

For everyone, you'll enjoy the "swim up for your live" mechanics that will let you go forward even if you missed a jump and fell into the ink. Well, you cannot recover *every* missed jump that way, but it's already much more forgiving than it used to be.

You'll also enjoy how jumping into an Inkjet now automatically let you in, dropping the Dumb Blador you're carrying, if any.


Story and gameplay migrated to latest release post
how to play
Get the .NDS image and play it on your homebrew-ready console or in an emulator, such as DeSmuME. See latest post if you need extra explanation/instructions for running homebrews.

Wednesday, December 27, 2017

[done] fargrounds

Eh bien, ça en aura fait des rebondissements pour débloquer le "super décor du dernier niveau"! Mais on y est. Du coup, les derniers éléments sur la "todo list" de School Rush, je vais les rassembler ici façon "bullet journal"

  • [done] la séquence de fin pour de vrai
  • [cancelled] le niveau bonus
  • le mécanisme pour se rendre dans le niveau bonus
  • une éponge qui monte-et-descend à la surface de l'encre, svp ?
  • [done] un affichage du nombre de vie (intégré aux images de chargement ?) 
At last, I have proper background graphics for my final secret level. The time is right to review the to do items, close some and bring here what will have to be done to get the game completed, bullet-journal style (as I don't have phabricator-for-sourceforge).
None of the things that are still on the todo list for School Rush could really be completed by the end of the year. But none is blocking a release either. I think we can call the vertical level .done. That took almost half the year, but I think it worked. Enjoy your season holidays.



Rien de tout ça ne semble faisable en quelques jours de super-papa-bros, donc on va emballer ce que j'ai pour boucler 2017 et prendre le temps de faire le reste correctement en 2018. Bonnes vacances.

Ce niveau vertical aura occupé une grosse partie de l'année donc, du mois d'Avril à la fin décembre, mais au moins il est testé et validé. Il reste sans doute un peu mystérieux à la lecture de ces lignes ... forcément, c'est quand-même un niveau secret ;-)

    Thursday, December 21, 2017

    Refactored, but freezing

    ok donc, j'ai eu du code qui compilait en un rien de temps, malgré un refactoring plutôt osé. Par contre, plus moyen d'atteindre la fin du premier niveau: le jeu freeze, à peu près tout le temps au même endroit, juste avant de m'afficher les premiers "inkjet" mobiles.

    Good joke! How useful is it to get refactored code compiling if you cannot reach the exit of level 1 anymore? The game now freezes every time roughly at the same spot, just before the first moving inkjets. I will need my mercurial time machine...

    Je prends donc ma machine à remonter le temps (comprenez mercurial) ... le bug semble aussi se produire avant la refactorisation ... j'évite donc de passer pour un clown qui fait des effets d'annonce sur son flux twitter, mais je n'ai quand même pas du code qui marche. J'ai noté que A. avait réussi à rejouer aux premiers niveaux après avoir fini le niveau vertical, donc il existe un point pas trop éloigné dans l'espace-temps où j'ai du code qui n'a pas ce problème.

    "Good" news is that the bug wasn't introduced by the refactory -- at least, my twitter-honor is safe. But honor does not make code run. I know that A/S-team could beat levels 1 and 2 during the last playtesting session, so the bug must have been introduced fairly recently. If I could find the last working commit, that would help understanding what went wrong and how to fix it.

    Reste à le trouver pour comprendre ce qui cloche. Pour ça, j'ai maintenant mon programme automatique de "unit-testing" qui simule un va-et-vient dans les niveaux.
    Et le programme de test en question crashe, lui. Un beau gros "segmentation fault", dû à un débordement de pile. Et la fonction "backtrace" capable de m'indiquer où s'est planté le programme et comment on en est arrivé là prend un plombe à s'exécuter (en fait, j'ai intérêt à l'interrompre):
    • CompoundGob::collide(#288)
    • BlockArea::collision(#1934)
    • InfiniMap::getflags(#350)
    • GameObject::cando(#1786)
    • CompoundGob::loadAnim(#178)
    • CompoundGob::setstate(#52)
    • CompoundGob::collide(#288)
    • BlockArea::collision(#1934)

    Hopefully, I now have an automated test that moves back and forth through the levels. And that test program crashes (big segmentation fault) when running one failing build. The backtrace function of my debugger takes ages to point out where the crash occurs (and how the program reached that state). When I interrupt it, I see no memory reference on the "call" instruction. All registers have valid values, no invalid opcode to be spotted around. The only suspicious thing is the fact that there seems to be a repetitive pattern in the function calls.
    Then I checked the value of the stack pointer and Captain Obvious knocked on my head.


    Oui, vous avez bien vu: on tourne en rond. Et le code fautif serait apparu pendant que j'essayais de corriger le problème des personnages qui jouent à Philadelphia Expérimental avec le plafond.

    Mais comme j'ai une release à assurer demain au boulot, je vais pas la faire trop longue. On sait où chercher. On cherchera pendant les congés entre les paquets de Noël et les cotillons ;-)

    This is a stack Overflow, caused by something in the new code that enforces alignments when resizing bounding boxes. It is obvious because the stack pointer has the lowest allowed value, given the area allocated as stack according to /proc/self/maps. It is too late to start searching what and why, but at least I know what to look for and roughly where.

    edit: trouvé en 20 minutes de "cybook" pendant que *deline travaillait sa danse. Corrigé en à peine davantage. On va pouvoir reprendre le travail sur les plans de scrolling ;-)

    got it located while *deline was having her dancing lessons, fixed in about half an hour. I thought it would take me at least a week-end. Good. I'll be able to go on with the rest (todo: figure out what still has to be done)

    Tuesday, December 19, 2017

    Refactoring de dingue!

    J'hallucine. J'ai pris une de mes plus vieille classes -- InfiniMap, responsable à la fois du scrolling et des collisions sprites/map. J'ai renommé ça en "CommonMap", appliqué les changements partout sauf aux sites de construction. J'ai ensuite déplacé le code utile dans un nouvel InfiniMap, déclaré l'une ou l'autre méthode comme purement virtuelle dans CommonMap ... et recompilé.

    I can hardly believe it. I picked of my oldest classes -- InfiniMap, that controls  scrolling and  -sprite-vs-world collisions -- and renamed it common map, everywhere but on lines of code building some instances. I then moved the "real" code into a new InfiniMap, mentioned a few ."pure virtual" markers in common Map, and rebuilt...

    Et ça marche ! C'est du délire à l'état pur. Ok, j'avais une classe iWorld mais je ne m'attendais pas à ce que le truc ne réclamme aucune autre intervention. Nada.
    Allez, demain, je déplace le maximum de variables membre.

    And it works! I can't beleive it! (dott). I knew I had some interface class already, but I wasn't expecting it to work that easily, not requiring any fix or whatever !

    Tuesday, December 12, 2017

    branches, reviews and cannelloni

    The idea is hanging around. It has been for some times, now. Possibly since I re-started exporting code to e-book readers through Doxygen, or since I tried to use apple assault as a tutorial to libgeds. I'd like to go for some in-depth review of my engine code. I'd like to use powers of code versioning system to slice code into readable, purpose-supported chunks, which would help the reader which components bring what feature and how they interact together.


    Plus les choses avancent, et plus j'ai envie de pouvoir proposer quelque-chose de plus didactique pour encourager d'autres amateurs de développement de jeu à s'essayer à la plate-forme NintendoDS. Pour ça, il me faudrait pas mal de réorganisation du code, et (idéalement) une branche mercurial qui approcherait les techniques nécessaires une par une, mieux documentées et testables. Et là, maintenant, c'est parti.

    But now, I started it. I've got a "bare minimum" DS application with corresponding library code (mine or 3rd-party), and its build system.
    [done] found the source of Noda's EFs tool again.
    [done] have it built as part of the dsgametools host-tools binaries, buildroot-style.

    Sunday, December 03, 2017

    Far ground

    Je tente d'intégrer mes bouquins-totems comme décor de fond du niveau vertical ... après quelques essais/erreurs pour faire le bon montage, qui ne consomme pas trop de mémoire vidéo, quelques corrections pour que le moteur de jeu puisse utiliser effectivement les 256KB dont il dispose plutôt que de s'auto-brider à 128K, je commence à avoir quelque chose... Enfin presque. L'état du code pour la gestion du décor en parallaxe n'est franchement pas terrible

    I'm trying to integrate the tiki-books as the background of the secret vertical level. it took a few trials to get something that fits in the renaining video memory, which is much easier after I grant access to the full 256KB allocated. well, sort of ... Unfortunately, the code for parallax scrolling is carrying lots of legacy, hard-coded settings suited for 512x256 -picture, while this new level needs it the other way round. The wale also picks camera coordinates directly, leading to a. weird offset on screen.

    • le code qui effectue le chargement de l'image ne supportait que la taille de 512x256 pixels alors que je veux maintenant utiliser le système en 256x512.
    • le code de scrolling utilise directement les coordonnées de la "caméra" en les divisant par deux, de sorte qu'il me décale le décor de 64 pixels sur la droite
    • on dirait que seul un des deux "écrans" est utilisé, en boucle, plutôt que d'avoir un décor deux fois plus haut que large ... à l'exception de certains endroits où le décors est sans dessus dessous.
    Il va y avoir un peu de travail pour corriger tout ça.
    plus, l have only half the picture showing up, rather than two sets stacked onto each other. And at some place, the scenery is completely messed up. it will take some work to get all that fixed. Maybe if I hack some forced, auto-scrolling, the defects will become clearer.

    edit: je devrais essayer de mettre un auto-scrolleur sur le plan de décor, tiens... ça simplifierait les tests.
    edit2: en effet, ça simplifie.
    • [done] le coup des décors sans dessus-dessous vient probablement du fait que je ne chargeait que la moitié de ma map (eh oui, il faut 2 bytes par pavé, pas un seul)
    • [done] par contre il y a clairement quelque-chose qui annule l'effet du réglage "32x64" (l'ordre d'appel des fonctions, en fait). 
    • [done] Et pourquoi ai-je un VBL handler appelé deux fois, pour deux maps différentes, et qui modifient les registres des deux plans ? 

    cando grow?

    Not so easy to fix the state machine bug about Bilou entering ceiling And that is mostly because it is not in the state machine itself. It happens because Bilou has two sizes, and the "HIT" state is one where he is big. Since"HIT" is a state that you can reach from almost any other state, we can't really "fix" the problem by conditional transition.

    So I took my code back and started looking around the call to CompoundGob::setbbox() for inspiration.
    1. the "grow'shrink." mechanism can be nicely separated along axes. I shall try it on the vertical axis alone so far.

    2. I should use cando() function to detect potential issues with virtual movements before I actually change the size. That should be much easier to have something where we check whether we could move up by dy (actually grow upwards) and align coordinates if we can't.


    Corriger le problème dans la machine d'état de Bilou pour lui éviter de se manger le plafond se révèle plus compliqué que prévu. Et pour cause: le bug n'est pas dans la machine d'états. Du point de vue du moteur de jeu, Bilou a deux tailles (de bounding box) différentes, et l'état "touché" est un des états où Bilou est grand. Du coup, puisqu'on peut se faire toucher dans à peu près tous les états, il n'est pas vraiment possible d'éviter un changement de taille par une transition conditionnelle.

    Il faut donc que je révise plus en profondeur le système de changement de taille (setbbox). Heureusement 1) je peux traiter les axes horizontal et vertical séparément; 2) je peux me servir du système "cando()" pour sonder le terrain avant de procéder au déplacement. 3) si je sais corriger jusqu'à la prochaine frontière de tile, je peux itérer pour étendre à des redimensionnement plus conséquents (à vérifier plus tard).

    3 . That will work for small resizing, and .can be extended to duck/stand for.human-sized characters  with a simpe - iteration. I haven't tested that, because all shrink/grow changes in Bilou change size by a mere few pixels. And I presume it wouldn't be completely satisfying for something like granting mushrooms for Super Mario. For one thing, the code assume that it is possible to grow. It won't catch the situation where small Mario would get a mushroom in a narrow corridor of bricks.

    Tout ça m'aura demandé pas mal de gribouille pour m'assurer que je comprends bien tous les cas de figure et éviter de devoir mettre un grand nombre de tests excessifs pour traiter plusieurs micro-cas (parce que certaines valeurs sont nulles dans certains cas). Peut-être même que je n'ai plus besoin, désormais, du système qui transmet des consignes d'alignement (avec le centre, le bord supérieur ou inférieur) ... mais ça, ça demande à être prouvé, et on verra plus tard.

    It took quite some sketching to find the right adjustments and avoid ending up with tons of tests to find all corner cases, but instead do the right computations, taking advantage of the fact that some terms are just zero in some cases. I think I might even no longer need hints about which side we should align against, but I prefer keeping them at the moment, until I get the proof that they indeed turned useless.

    fix

    Saturday, December 02, 2017

    spriteram vs . Resource

    Using InspectorWidget to understand buggy situations has become abnormally hard. Just look at the picture we got earlier this season. Compare that to what it used to look like. I've got the "boxes" area all messed up. Of course: in School Rush I now have two things trying to use the sprites of the bottom screen: Inspector Widget and the HUD.

    I needed to change a bit the code for the HUD (which uses a SpriteRam to load hud.spr) so that it tells the GUI engine that it used some resources, which are thus no longer available to the InspectorWidget... and let the Engine give some other tiles to Inspector Widget.

    One thing I had overlooked is that I devoted up to 256KB of VRAM to background tiles on the main screen, leaving only 16KB for HUD sprites. At 256 bytes per 16x16 block, that means I can have at most 64 different blocks at all. I have 20 different sprites used, 44 left.

    Inspector Widget uses 1 such block for "box-borders" (with 4 different flips), and then it has 4 areas-reporting sprites (made of 64x64, 16-color sprites that get scaled up and down to match the effective area shape). That's 32 "tiles" count each for the engine, or 8 of the "blocks" I've used above. So with proper values, I can get it right.