Showing posts with label newmeta. Show all posts
Showing posts with label newmeta. Show all posts

Thursday, September 03, 2026

Inspector Widget Improved

Inspector Widget ... le mode pause du moteur de jeu de GEDS qui permet de voir à travers la Matrice. Repérer les zones de collision, mais aussi visualiser le terrain autour des personnages tel que les contrôleur le perçoivent. Sauf que le code qui faisait l'affichage du terrain date de l'époque Apple Assault  et qu'il est plus ou moins inutile avec le nouveau système de map physique.

During AppleAssault and SchoolRush development, the "playfield" feature of InspectorWidget has proven an extremely valuable feature of the GEDS engine. I could get an overview of what the engine sees of the level without having to manually decode contents of the physics map. But with the evolution towards a new, richer encoding, the information it was showing became mostly useless. But hopefully, during the "Blador-vs-Spike" episode, I located where the responsible code was and could start fixing it. Initially, it was looking like the listing below.

Le code qu'il aurait fallu que je retrouve il y a un moment était caché dans InspectorWidget::clearmain(). 

for (int ty=sy; ty<=ey; ty++)
  for (int tx=sx; tx<=ex; tx++) {
    unsigned f=gob[0]->world->getflags(tx,ty);
    unsigned c=BCHECK; // pattern for the "outer ring" of the zoomed tile
    if (f&F_BLOCKING) c=BON; // plain light ring = solid block
    if (f&F_PLAYERTHRU) c=BOFF; // dark ring = air / water / etc.
    if (f&0x10000) c=BCHECK; // checkered ring = special block
    if (f&F_SLOPE) c=97; // striked through = slopes
    char sq[16];
    memset(sq,c,16);
    if ((f&(F_FLOOR|F_SLOPE))==F_FLOOR) memset(sq,BON,4);

    sq[5]=80+((f>>12)&0xf); // 4-digits code in the inner area
    sq[6]=80+((f>>8)&0xf); // encodes the F_* flags for cando() calls.
    sq[9]=80+((f>>4)&0xf);
    sq[10]=80+(f&0xf);
    u16* v = vram+MAP+(ty-sy)*128+(tx-sx)*4;
    for (int i=0;i<16;i++) {
      *v++=sq[i];
      if ((i&3)==3) v+=28;
    }
  }

Pour ceux qui ne parlent pas le C couramment, le listing ci-dessus raconte que chaque pavé de la map va être représenté par un code à 4 caractères entouré d'une bordure dont le pattern est variable. 

  • bordure solide pour ce qui ne laisse pas passer le personnage
  • bordure en damier pour les blocs spéciaux
  • bordure en hachure pour les pentes.

Le code au centre du carré, ce sont les propriétés utilisée par la fameuse fonction cando(). Et il faut bien admettre que maintenant qu'il y a plusieurs types de pentes différents, plus de blocs spéciaux et des blocs aux propriétés particulières, juste les flags pour cando(), c'est devenu à la limite de l'inutile. Parce que la plupart des blocs spéciaux ont les mêmes propriétés et que celles des pentes sont prédéfinies.

Mais heureusemement, j'ai trouvé l'occasion d'améliorer ça.

  • un code à 2 chiffres, c'est un tile à encodage direct. on voit littéralement le byte de la map physique et chacun de ses bits nous renseigne pour une propriété. 44, c'est de l'air.
  • un code à 2 chiffres sous une petite ligne à damier, c'est un bloc spécial. Ici aussi, la valeur et celles du byte de la map. Les valeurs ff, fe et fd servent pour les fameuses "flèches jaunes" de l'éditeur.
  • les pentes sont toujours identifiées par leur contour hachuré. Le code à 4 chiffres donne les hauteurs des pixels au centre du tile. 3456 ou 6543 pour des pentes à 45°. 2233 et 6677 pour des pentes plus faibles en "montée" de droite à gauche, etc.
  • Enfin, pour les autres blocs, on reste sur un code à 4 chiffres qui contient les flags. à l'ancienne. 

The new code varies the shapes a bit more. Some tiles will only have a 2-digit code (the byte straight out of the map), sometimes with a checkered line on top of them for special blocks. Slope tiles still have a 4-digit code, but it now shows how heights ramp up or down along the tile. And the so-called "indirect" tiles, those which can be assigned physical properties such as friction and flow, keep showing the 16-bit cando() flags as before ... at least so far.   

 

 

Sunday, August 23, 2026

Blador vs. Spike

While I was checking collisions/interactions were still working fine after introducing the G_FIGHT group, I noted something not so right about the dumblador. Something I don't think I've ever blogged although it was available since the anniversary level: throw a dumblador into pencil spikes and it will snap to the spike it lands on, turning itself into an additional safe platform.

But with the current engine, you may end up with the blador "waking up" and start walking within spikes. You may also see it stopping completely misaligned and almost everytime, it would be too low compared to where it used to stop.

I first tried to tune collision areas, but that did not seem to help. I checked some values in the DDD debugger, but it's a bit of a lottery: you can't really tell in advance whether you'll find yourself in an interesting case. Note to future self: there are save states in desmume! (In such a case, I should have saved the emulator state before throwing the blador, save again when the breakpoint triggers, fast-forward to see whether the condition will happen and only then go back in time to either review the step-by-step behaviour or change a little bit the initial conditions and try another throw).

But I had not came back from the future to leave myself a note yet, so instead, I started adding coordinates of colliding entities in the "gobscript expression debugger" so I could have something that is stepping faster than DDD, and present precisely the information I needed (although I could have used it in base 10 :P).

And there I realised that when the blador ended up misaligned, it was colliding with a spike whose position was a mere multiple of 8 rather than a multiple of 16 ...

Back in SchoolRush times, it was mandatory to be a 16x16 pixels block if you wanted to have special behaviour such as hurting the player. But it changed with the tiled engine revision where each individual 8x8 tile can be of any 64 special type (or any of the other 192 "normal" types).

Larger blocks are still possible thanks to "refer too" special tiles that point towards the top-left corner tile of the block. When loading an older map, the conversion is automatic, but when I created the "school teleporter" room for the 3-rooms-demo, I just added 1-tile spikes instead. With a small change to the Level Editor, you can now press A to reveal the redirecting arrows (default behaviour is to mirror the pink tile instead). That should make such errors easier to spot in the future, if I ever make them again.

So the script for the dumblador now looks like

$THROWN :anim3 {
  using gravity(24,1536)
  testpoint off (8,18)
  test 0 (0,0)-(8,12) ${F_BAD|G_FIGHT|F_WEAPON} //# weapon against other monsters.
  test 1 (0,15)-(16,16) ${F_BAD|F_PLATFORM};
  area 0 (0,0)-(16,12) ${F_ISINK} //# deleted-by-ink
  area 1 (0,0)-(16,8) ${G_FIGHT|F_HURT} // # stand-on-spike
}

$THROWN->$STUNSTAND on hit1 (0 :1 0 :0 Lc $vPlatform(2));
$STUNFALL->$STUNSTAND on hit1 (0 :1 0 :0 Lc $vPlatform(2));

and the script for the pencil spike looks like

 block 21 {
   is spike "0101030307070f0f"
   area (7,0)-(8,16) 10010010 # hurts
   on hit [0] (t)
 }

 Together, they allow to get a functional blador-align-on-spike (aligning is performed by the Lc opcode), but there's still one thing to fix if I don't want to see dumblador waking up and start walking on pencils: duplicate the $STUNSTAND state into something like $SPIKED, while removing the "get feet" area. But well, a remaining glitch makes some more fun for ScreenshotSaturday ;-)



 

Sunday, January 25, 2026

Corrigeons l'appleman ...

Bien, j'ai pu un peu montrer l'appleman qui roule à mon frangin lors de l'anniversaire de J.L.N l'autre jour, et il avait plutôt apprécié. Surtout les interactions supplémentaires que j'envisage avec les autres ennemis du jeu.

We have rolling appleman now, and both my son and my brother do like it. But before I start adding all the fun interactions I envision (and they're awaiting) using that new mechanics, I have some clean up to do.

Mais avant de m'attaquer à ce genre de jeu, il me fallait d'abord corriger quelques étranges bugs apparus près de ces plateformes rajoutées dans le niveau de l'arbre creux en construction.

Le premier est un curieux alignement: au moment où la pomme commence à rouler sur une plate-forme à sens unique, elle se retrouve curieusement alignée fort bas. Comme si le bas des tiles était le sol, plutôt que le haut comme prévu. Ou comme si la géométrie de la pomme était beaucoup plus plate que ce qu'il faut.

Two bugs were requiring some attention. The first affected the ground height of the rolling appleman on jump-thru platforms. A quite perplexing thing which I expected to require tracking of coordinates and tile properties as the debugger would let me dig within some of the more complex functions of the engine such as "do_slopes". So I went on posting debugger screenshots as bread crumbles for a non-existent time machine. 

Post by @PypeBros@mastodon.social
View on Mastodon

C'est le genre de situation où je sais que je vais devoir regarder en détail ce qu'il se passe dans les fonctions do_slopes ou cando, parce que c'est là que se prendront les décisions. Et je sais d'expérience qu'il va me falloir une idée précise des coordonnées impliquées, où noter les résultat intermédiaire etc. 

Je suis donc reparti à me faire des petites annotations dans mon carnet et une série de captures d'écran du débuggeur qui me servent de machine à voyager dans le temps. Et on retrouve bien les deux problèmes: la bounding box definissant la taille de l'appleman grandit entre l'état "lancé" et l'état "roule", ce qui veut dire qu'il se retrouve automatiquement avec les pieds dans le sol. Mais en plus de ça, la hauteur du sol n'est effectivement pas correcte. Un résidu du passage au nouveau système de propriétés du décor qui n'avait pas encore été corrigé.

After numerous breakpoints and conditions and instructions stepping, after using a second emulator in parallel to figure out coordinates, check bounding box size and the like, I eventually noted that the height for a "direct" tile like those used for jump-through  is 0. That's intended for "look at what's beyond" when walking on some ground. That's fine for water or air or maybe even vines to be climbed. Not for any sort of ground. Easy to fix.

Now, the second one the appleman didn't pretend to enter the "jump-thru" platforms while being carried. That led to weird situation where it would push on Bilou, preventing him from even approaching the platform. Here the issue was in the properties we told the gravity controller to test for. It doesn't need to be AIR for the appleman to move through. In fact, anything the carrier could move through would be equally fine for the carried object. In the capture below, I only fixed the state when the appleman is facing right, so that gives you a nice fixme/fixed comparison.  

Autre effet bizarre: l'appleman ne voulait pas entrer dans ces régions "jump-thru" pendant qu'il était transporté. Un choix malheureux des propriétés recherchées qui insistait sur le fait que "ça doit être de l'air". En fait, non: partout où le joueur peut passer, ce qu'il transporte doit pouvoir passer aussi.

(la petite capture animée montre un état intermédiaire où j'ai utilisé ddd pour modifier les propriétés recherchées quand on est tourné vers la droite, mais pas encore quand on est tourné vers la gauche, pour vous faire un "avant/après" plus parlant)

Vous noterez peut-être dans ces petites captures un moment où Bilou se retrouve avec 4 mains. C'est le problème que j'avais cherché à (et cru) résoudre en Mai dernier ... manifestement, ce n'est pas encore complètement au point. 

Sunday, November 16, 2025

Signets et attach

J'ai pour la SchoolZone l'intention d'introduire des signets/marque-pages qui pendouillent... on pourrait s'y accrocher (indispensable), grimper, descendre (sympa) et ils réagiraient comme des cordes plutôt que comme des barres.

J'ai appris dernièrement qu'il fallait que je prototype ce genre de choses dans l'environnement des "three rooms" sous peine d'être démoralisé par le côté "nu et inintéressant" d'un niveau à peine commencé. Et coup de bol, il y a un coin de la salle "école" qui conviendrait bien : le haut. On pourrait atteindre les signets en utilisant la gomme et s'en servir pour rejoindre l'éponge, un peu compliquée à utiliser pour l'instant.

Hanging to a rope-like bookmark, using it to swing around and hop to the next ... that's clearly something I'd like to bring into the school zone and I may have just found the right way to introduce it first in the "three rooms" demo. Yes, I could use one of the levels in which they are featured, but recent development on the green zone shown that a rushed large level doesn't motivate me as much as a small polished screen can. They would be there, in the top corner and providing an alternate way to reach the swinging Spongebop.

Avant de permettre de s'y accrocher et de se balancer, je voulais voir comment m'y prendre pour une interaction plus simple: juste laisser Bilou bousculer le signet et qu'il ondule un peu en reprenant sa place. J'ai le comportement "circular" qui pourrait être pas mal pour ça.

Before I'll let Bilou grab them and swing, I'll have to start with something easier, like just having Bilou disturb them and make them swing stronger when passing nearby. It should be a mere matter of attaching segments to one another with the "circular" controller... except that once Bilou pushes the bottom part of the "rope", segments now need to lookup two objects instead of just one. And that's a bit more tricky to handle for my engine that only allow one object pointer per object.  

Sauf que on tombe dans le cas de figure compliqué où les mouvements d'un segment dépendent à la fois de la position du segment au-dessus et en-dessous de lui, ce qui pose trois questions:

  • Est-ce qu'il faut que j'ajoute une zone "solide" à Bilou ?
  • Quels flags (pour les collisions) sont disponibles pour ajuster les comportements (j'ai oublié ^^") ?
  • de quelles infos est-ce que je dispose après une collision entre deux segments ? Est-ce suffisant ? 

J'avais pensé relire le tag "attach" pour me rafraîchir la mémoire, et j'ai eu la désagréable surprise de le trouver confus, avec quelque malheureuses infos pratiques perdues au milieu du "gamedev story". Il est devenu mon "tag de la semaine", mais j'ai dû reconnaître que ça ne suffisait pas. Je me suis retrouvé à essayer de l'extraire avec les outils "blogpress" et lui appliquer une feuille de style avant de l'utiliser pour tester les "pages web codeberg".

So, that was the idea back on 11/11 when I sat down with my notebook and collected the questions that needed answers before I could get to the coding stage. I thought unrolling the "attach" tag of the thread would give me answers, but it turned out the useful information was somehow lost into trivias, screenshots and other progress reports. And the code documentation wasn't much better, so I ended up restoring a setup for blogpress and tutogit at the same time, uploading them all on codeberg and see whether I could apply simple.css etc.

ça m'a donné le déclic pour reprendre le travail sur le repository "tutogit", en plan depuis 7 ans, vu que maintenant le nouveau système de gestion des propriétés du niveau est arrivé à maturité. Je pense que ce serait là le bon emplacement pour des pages thématiques présentant chaque élément du moteur de jeu ... qui puisse au final s'intégrer à la documentation doxygen. Voilà déjà celle pour attach.

Sunday, December 17, 2023

tapis roulant!

Nous y voilà enfin! Après l'eau-qui-pousse, je peux vous présenter le sol-qui-pousse. Le point délicat, vous vous en doutez, ça aura été de mélanger ça avec des sols pentus. Ce à quoi je ne m'attendais pas franchement, par contre, c'est que être poussé pendant qu'on est immobile sur le sol se révèle plus compliqué à gérer qu'être poussé pendant qu'on avance.

The natural step after water-that-push-Bilou was ground-that-push-Bilou. It started quite nicely and it is finally working, but to reach that nice behaviour, there has been significant ups and downs, and especially to get it working on sloped ground. But hey, sloped conveyor ground was my trick to have one-way halls without getting too mechanical.

C'est que pendant qu'on avance, on appelle régulièrement la fonction do_slopes, voyez-vous. Et même si le sol annonce "je te pousse de deux pixels sur la gauche" alors qu'on est sur une pente, on finira bien 2 pixel à gauche et 1 pixel plus bas si nécessaire. Mais rien de ce genre dans l'état "immobile sur le sol". Et notre fonction do_slopes est prévue pour aller directement corriger la vitesse et les déplacement retardés du personnage, or l'idée du "sol qui pousse", c'est justement de manipuler la position dans un premier temps et de laisser le code qui traite la vitesse tranquille. Sans ça, sur un tapis roulant trop rapide, vous verrez Bilou se retourner pour marcher tout seul vers la gauche plutôt que de le voir s'échiner à avancer vers la droite tout en reculant malgré tout vers la gauche. Pas terrible.

Dans Rayman, j'avais pu voir qu'on avait deux types de pentes: des normales et des glissantes. Chaque angle et chaque offset est dédoublé avec un second type pour gérer les deux types de physiques. J'avoue que je souhaite plus de souplesse pour Bilou. Pas tant que j'ambitionne de faire un jeu plus complexe que Michel Ancel, mais surtout parce que je n'ai pas l'occasion de planifier l'ensemble du jeu. Je suis incapable actuellement de garantir qu'il n'y aura jamais plus de 2 types de sol dans un niveau ni 2 types de pentes. Le projet était donc d'utiliser des emplacements séparés pour encoder la pente et les propriétés du sol. Et quand je me suis mis à coder, c'était encore plus simple que prévu: quelque soit la position de Bilou sur une pente, il est toujours à l'intérieur du tile "pentu". Et donc pour trouver le tile avec le type du sol, il suffit toujours de regarder 8 pixels plus bas. Enfin ... presque toujours.

And that was the final test for my "neat idea" to "simplify" the level editor: use separate tiles to indicate the slope (if any) and the ground properties. Ground properties are always on the 'plain' part of the ground and the slope types sit on top of it. A new getGroundType function can probe through that slope layer to find the actual ground and return its numerical type. Then, each controller use that to index to retrieve relevant parameters, such as push vector, friction, or whatever needed. It mostly worked except on one spot: the precise location where Bilou's hotspot has just been shifted out of the lowest 'sloped' tile of a slopes stripe. It is now mid-air, with one 'slope' tile below it and the ground properties one more below. Then Bilou stops because it is no longer pushed but doesn't fall either. And if I try to hack that around, I end up with Bilou moved horizontally instead of following the slope because there's no slope to follow.

Comme toujours avec les pentes, les problèmes commencent quand le sol n'est plus dans le prolongement horizontal de celui utilisé une frame plus tôt. On se retrouve dans ce cas-là soit avec Bilou qui s'arrête au milieu de la pente, soit continuant à se faire pousser, mais à l'horizontale. 

Yet, when you walked on the sloped ground rather than letting yourself pushed by flowing sands, you wouldn't get any issues. The trick is that walking state already has a call to the do_slope function that keeps Bilou in contact with sloped ground despites of motion. The extra shift happened prior that call, so it would still re-align when Bilou's own velocity is applied. But there was no such call in "idle, standing" state so far. And the do_slopes function wasn't meant to affect anything but character's speed, while it should now sometimes affect temporary variables used to immediately apply a coordinates update.

And just in case that seemed too easy, a typo in the first coding sprint made me change accumulated step instead of actual speed, ruining the whole thing with Bilou digging into the ground. Then a bug introduced in the level editor broke some part of the level without me realizing it and I started suspecting wrong properties for the ground here or there.

But there we are. It's working, even though it cost me hopping back in time with Mercurial and re-doing the sprint one dash at a time, checking, committing, re-importing maps and the like. And about one week later, I finally shot a decent .gif of the behaviour so I could post it and write this stuff. It's been planned for so long. It has been through so many preliminary work and so that I'm gonna call it a milestone.

Bref, inspector widget, ddd, j'ai pu sortir toute la panoplie. Presque (pas les unit-tests, cette fois). Mais l'éditeur de niveau m'aura bien cassé le rythme.

(wow. Le soir est tombé, j'ai encore une machine à faire tourner et je n'aurai pas fait plus de homebrew de cet aprèm' libre que de vous raconter tout ça :-P)


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...

Saturday, January 29, 2022

Les bonus s'emmèlent...

J'étais tout content de voir que Bilou savait aller dans l'eau, et je ne me suis pas rendu compte qu'il y avait un soucis avec les bonus: on pouvait carrément marcher dessus. Quelque-chose lié à la nouvelle propriété F_START_FALLING, sans doute ... sauf que non. c'est surtout lié aux bytes 'regarde à côté'.

C'est que l'ancien moteur de jeu utilisait le numéro du 'bloc spécial' pour décider s'il devait être solide ou non, et la fonction qui indique la 'hauteur du sol' essayait toujours de faire comme ça. L'ennui, c'est que j'ai utillisé les codes 0xfc à 0xff pour les fameux 'regarde à côté' qui permettent aux blocs spéciaux d'être des blocs, et pas juste des pavés de 8x8.

Jan.24. Managed to have Bilou switch to 'swim' state when it gets in contact with F_WATER tiles. It's as swimple as $LFALL->$INWATER on fail [H WATER ?] ...

Jan.25. It uses the new H GobExpression 'operator' that puts type of the tile under character's hotspot on stack, where it can later be compared with a constant flag (WATER). That operator will expect an elevation value on the stack first. like [2 H WATER ?] to tell "check 2 pixels above the hotspot"

But this is not the point of this post. The point is, looking at the video I captured (bottom left on the toot panel below), I noticed I was walking on disappeared apple before going into the water.

Jan.29. When you pick up a bonus, a MapAnim is spawn, that will edit graphics to get that sprinkling animation. It should clear "properties" as well, as soon as you get in contact with the collectible.

Yet, the change to newmeta changed what 'cleared' means on the map. Now, the clear value 0 means 'lookup World::properties[0] to know what you can do'. Another trap was that, when checking ground height, you might find yourself on one of the new "lookup one tile left" or "lookup one tile up" that are used to make special *blocks* of adjustable size (not just special mini-squares of 8x8 pixels). If that happens, code was still lacking "locate the actual block defining corner" and then use that special blocks's properties set to decide whether it has ground or not.

Pas le choix, donc: ici aussi, il faut retrouver le 'coin actif' du bloc spécial et aller chercher ses propriétés dans le BlockInfo correspondant.

Deuxième farce (voir l'animation): une fois le bonus effacé, il a laissé derrière lui un bloc à travers lequel il est possible de continuer à tomber, mais aussi de continuer à marcher. La faute cette fois au tableau des propriétés pré-encodées pour les blocs à définition indirecte (prévus pour les physiques particulières, essentiellement).

edit: if you don't have a twitter account, here's what the videos looked like:

Saturday, December 25, 2021

xmas21.zip

I finally posted something more on my sourceforge project: the set of editors (plus runme) as I've got them by this Christmas, invoking oven-hot slopes support.

I wish I could provide you with a meaningful 'change log' for this 'release' of my tools, but let's be

honest: there are over 20000 lines changed between then and now (assuming that you're only interested in what changed since last AnimEDS release in 2020). It won't be exhaustive, but I'll try to give you an idea of what's in anyway.

Sprite Editor

  • allows you to work on any file you've got on your memory card (including automatic backups put in /DATA/SEDS/*)
  • better 'colors zapping' implementation.
  • 'where is that color used?' now cleanly implemented in the PaletteWindow
  • (improved host tools sprdo and sprck are missing from this pack)

Animation Editor

  • allows you to work on any file you've got on your memory card. 

Level Editor

  • uses new map layout with dedicated PHYS layer (accidentally named 'SYHP' in the file >_>)
  • show the 8 color palettes when selecting a block in DRAW mode (A). Color paint mode now available on both foreground and background layers (trigger with L+A on the desired layer)
  • supports new any-sized special blocks with 'lookup arrows', features revised 'meta buttons' widget to select tile properties.
  • reads new 'slopes %d = "%x"' hint in .cmd or .gam files and populates the slope tiles graphics accordingly. Different maps can use different slopes or share them by importing the same .gam file.
  • supports spritesets and tilesets overlay commands

runMe (gameplay preview & WiFi transport)

  • Allows live-skipping of buggy script lines
  • allows auto-repair of the /moving/ directory
  • features new level map engine
  • supports script-driven song swapping with zik.file = "%s"
  • Improved modplayer playback speed stability
  • supports spriteset overlays (spr.more "%s" ...) and tileset overlays (bg0.more "%s" ...)

All these .nds files will work from anywhere in your flash card, but if you install them with their original *dlta.nds filenames at the root, you'll be allowed to hope from one tool to another with the embedded buttons (quit, LEDS, SEDS, MEDS) in the application welcome windows.

Wednesday, December 08, 2021

3 Rooms - Release Early

 

There we are. The first demo featuring the first 3 environments of Bilou's Dreamland cycling to one another, changing music and graphics. It's super work-in-progresss, and there are so many things to be fixed that I won't try list them now. But you know what they say: "release early, release often", and a fellow gamedever asked me earlier this week about being allowed to test and so on. So if you think he's right, enjoy this St-Nicolas gift.

Download: Dreams.nds updated Dreams.nds for new year

Voici donc (enfin ?) quelque-chose de téléchargeable avec les environnements que j'ai l'intention de faire évoluer pour y amener toutes les nouveautés de gameplay de Bilou's Dreamland. Alors, soyez avertis quand-même: c'est vraiment une version 0.0.0.1 là. Pas même une ébauche, tout juste un canevas. Y'a des retouches à faire par-tout. Y'en a tellement que je n'aurais même pas le temps d'en dresser la liste avant d'aller me coucher. Mais qui sait, ça vous amusera peut-être.

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.
 

Monday, August 16, 2021

DJLN.cmd

Faire des niveaux sur papier, ce n'est définitivement pas une activité à proposer à mon fiston. Au mieux, je peux lui proposer de me dicter un niveau que je ferais moi sur papier.

Par contre, prendre la Nintendo DS de papa et ajouter des blocs ici et là, ça ça lui plaît bien. Mais pas de chance, la branche "newmap/newmeta" n'est pas encore stabilisée au point qu'on puisse tenter de jouer au niveau ainsi construit.

Assez surprenemment, mon nouvel écran de patching m'indique que l'erreur se trouve sur la première ligne de pyram.spr, CMAP n'étant pas une commande valide pour les scripts. Enfin, ça c'est sur émulateur après avoir récupéré les fichiers présents sur DS avec le wifi remis en service.

En fait, ce serait la commande spr.more "pyram.spr" qui n'a pas été comprise par l'éditeur de niveau. Du coup, au moment de sauver, il en fait un input "pyram.spr" Si j'en crois les numéros de version, le bug a déjà été patché, c'est juste que la DS n'avait pas pu profiter de la nouvelle version. C'est J.L.N qui va être content...

  • invoking autoexec.cmd with the [run] button does not seem to allow PatchWindow to be invoked.

Twitter Trap Status: story is featured in "All tweets from blogger". No videos around. 

Sunday, November 15, 2020

DS Day Off

 Il me restait quelques jours de congé à prendre. Et la Wallonie avait prolongé les congés de Toussaint de 7 jours ... du coup de mercredi à dimanche, j'ai pu prendre à peu près 2 heures par jour pour faire un peu de développement DS. L'objectif: pouvoir faire une démo des "blocs interactifs de taille variable". La stratégie: remplacer les fichiers de la "démo git père Noël" par les fichiers de Crazy Brix.

J'ai fini par y arriver, mais avec 3 jours de bidouille pour parvenir à utiliser des fichiers pré-existants, on ne peut pas dire que dsgametools soit prêt pour une game jam.

Mon éditeur de sprite ne m'a pas aidé à manipuler ce 'brix.spr', importé par WiFi, si bien que j'ai finalement ajouté un widget pour pouvoir ouvrir n'importe quel fichier (et pas juste les quatre "projets en cours").

Je devrai rajouter une p'tite couche de ce côté-là: une tentative pour sauvegarder les modifications, et vlan, c'est le répertoire tout entier qui s'est retrouvé renommé 'movibak'. Et aussi bien runMe que mon éditeur de niveau se sont retrouvés incapables de poursuivre le travail parce qu'ils n'avaient plus leur répertoire temporaire.

Le code de base du moteur de jeu m'a mis les bâtons dans les roues, lui aussi. Pour pouvoir changer la couleur des briques, j'ai utilisé les changements de palettes. Si, vous savez: ce mécanisme qui permettait à Super Mario Bros 1 de gratter quelques blocs mémoire en recolorant les nuages pour en faire des buissons. Ouais. Bin la DS sait faire ça aussi mais avec 16 variantes de couleurs pour 256 couleurs. Quelque part cet été, j'avais ajouté la possibilité de repeindre les morceaux du niveau (pas juste les éléments de décor, comme dans School Rush, mais aussi les éléments principaux). Mais j'avais oublié que le moteur de jeu, lui, n'était toujours pas prêt pour cette rajoute ^^". Et desmume n'est pas aussi sexy de ce point de vue-là que les émulateurs des devkits SNES ou NES: je ne me suis rendu compte de rien jusqu'à ce que je fasse un dump des registres graphiques dans DDD...

Voilà. Ajoutez un premier jour bien cahotique où le code importé du repository git ne voulait pas compiler, ou ne trouvait plus ses fichiers intégrés, ou "oubliait" de reprendre les couleurs des personnages parce que, dans sa branche, il n'y a même pas encore de support multi-palette pour les sprites (mais si, enfin. Ces p'tits blocs mobiles qui se déplacent librement sur l'écran, en plus des grilles qui servent pour les décors)... Vous comprendrez pourquoi ce genre de chose ne s'était pas mis en place depuis un bon moment.

Twitter Trap Status : two referencing threads, including one video post. transported to https://mastodon.social/@PypeBros/117172866517516760

Sunday, October 11, 2020

Direct Flags

Signing in for a 7-days trial of the Nintendo Online sure affected how I used my hobby time these last days. But nevertheless, I could do some homebrew coding, and it was for the level editor.

You may recall that I'd like to introduce 'direct flags tiles' in the engine. The idea is to enable any combination of some very basic properties like "can be swum through", "can be climbed on" or "can be fallen through" within the level by dedicating 64 tile types where the 'type identifier' part is used as a direct set of flags for those properties.

Une des idées avec la révision du monde de Bilou, c'est de pouvoir permettre à certains tiles de définir directement les propriétés physiques à appliquer. Dans Apple Assault et School Rush, chaque numéro de tile fait appel à un lookup dans une table de correspondance pour connaître les 'flags' à utiliser dans cando(): ça, c'est l'encodage indirect. (ça vous rappelle vos cours d'assembleur ? c'est normal). Un quart des types de tiles seront maintenant dédiés à ce fameux encodage direct, qui permet notamment d'exprimer n'importe quelle combinaison de 6 propriétés fondamentales comme "permet de tomber", "permet de nager", "peut être escaladé", etc.

Yet, that's only efficient if you don't have to come with 64 custom editor art for them. And that was only possible with a few changes to my MetaFlags widget and the surrounding code:

  • paint color for 'environment type' tiles 
  • on/off switches for those tiles in MetaFlags
  • auto-generate combined tiles for combined environment (e.g. CAN_SWIM + CAN_CLIMB)

"auto-generation" works by painting the the 'pure' tile with the highest bit, then painting over the lower-priority bits. So if you swap the order of  all-blue CAN_SWIM and some-green CAN_CLIMB, you won't see that you can do both anymore.

Jusque là, c'est bien beau sur papier, mais dans l'éditeur, comment représente-t-on que le bit 4 est utilisé pour l'eau et le bit 3 pour l'escalade ? Eh bien à travers le fichier .gam, bien-sûr. Celui qui contient déjà des commandes "block {}" pour tous les blocs spéciaux (bonus, clés, portes, etc.). Comme leur nombre a été réduit à 64, je peux utiliser une partie des numéros pour décrire 6 graphismes de base (un par propriété fondamentale). La chaine hexa sert toujours à définir l'image à afficher, le nombre qui est derrière la couleur à utiliser (le noir pouvant servir à 'effacer'). A partir de ces images de bases, l'éditeur générera les combinaisons possibles.

It's far from perfect, especially because I still have to override that for the tile that says "plain air here, sir". But I realised it was merely an optimization over the 'indirect' tiles, and premature optimization is the cause of so much bad things ...

*but* I can manage to get some clean output if I define 'flags' in the .gam file. Especially, knowing that meta-tiles are alpha-rendered, meaning that any black color turns transparent, whatever their palette indices. 

*edit* And the reason why so many levels I edited lately would have buggy 'empty' tiles rendering is that this "rush.gam" file I modified for the snapshots is only used in two levels so far.

Tuesday, September 15, 2020

makechar(BG_GFX, digit[i])

Bon, j'avais des affichages curieux dans LEDS. "où sont passé les pentes et les blocs jump-through" disait mon calepin. Eh bien ils étaient toujours bien là. Simplement pour les voir, il faut qu'il y ait quelque-chose au bon endroit dans la mémoire vidéo de la DS. Et jusque là, le code d'initialisation n'avait pas suivi l'évolution de la branche "newmap". Le niveau était donc bien converti mais les codes 0x81 pour "est une pente, type 1" n'avaient droit à aucun dessin.

Mais je n'ai pas sucé ça de mon pouce. Pour y voir clair, j'ai bricolé une p'tite table de caractères hexa en 3x7 pixels qui sont ensuite combinés pour faire 256 tiles dont le dessin indique le numéro.

I started getting weird effects in LEDS on the 'newmap/newmeta' branch. Special blocks and plain blocks seemed to work fine, but everything in-between (shadows, slopes, jump-through) was missing. Or so it seemed. They were actually still present, but invisible because the pixels to render them was still on the 'old codes' rather than on the new ones. I got it confirmed once I introduced a small loop that primes all the tiles used by the meta-layer with two-digit hex codes stating explicitly who's who.
 Unlike the legacy 0-3 codes, these are not meant to be shown to the level designer. As soon as we load the level, effective tiles will be filled, for instance using the 'symbol' statements.

Contrairement aux anciens codes, il n'est pas prévu ici de les conserver à l'écran: pendant le chargement du niveau, tous les codes utilisés seront remplacés par les symboles définis dans "rules.gam". Seuls restent affichés à coup de codes hexa les types de tiles "inconnus" -- ici les 00 qui servaient à "pousser" les personnages par-devant tous les plans de tiles et la pointe de crayon inversée.

Par contre, du coup, les "méta-boutons" deviennent beaucoup plus vides ^^"

Et comme maintenant je suis en mode multi-palettes pour tous les rendus de graphisme du jeu dans l'éditeur de niveau, j'ai les coudées franches pour redéfinir la palette principale, toujours utilisée par les plans "16x15 couleurs". C'est fondamental vu l'affichage du meta-layer en alpha-blending: utilisez une couleur non-définie (donc noire) et le truc est invisible. Prenez du blanc, et l'alpha blending sature.

Ok, c'est à peu près aussi passionnant que l'avancée des négotiations fédérales belges. Mais si je ne me remets pas ce genre de chose au frais en tête, je n'ai aucune chance d'avancer sur du homebrew. Et si je le fais, il est 23:37 quand j'ai fini ^^". 

C'est pas terrible pour la lisibilité des méta-boutons, par contre. Je vais leur donner une palette rien qu'à eux avec des couleurs bien EGA pour qu'on ne les loupe pas, du coup.  Puis j'irai jeter un oeil à la page du projet "Méta-Boutons" aussi, pour voir ce que j'avais envisagé pour passer les valeurs "inutilisées", parce que là, ça serait assez désagréable à utiliser (1 à 2 tiles utiles par "page" de boutons ... bof)

Thursday, June 25, 2020

Le retour des Meta-Boutons

Bon, la bonne nouvelle, c'est que j'ai repris le travail sur l'éditeur de niveau: il faut bien qu'on puisse profiter des nouvelles possibilités offertes par le moteur "newmap", vu qu'il a passé le premier round de tests automatiques.

J'ai attaqué avec la révision des "méta-boutons", cette palette d'outil qu'on peut faire apparaître sur la droite de l'écran pour définir si le sol est solide, pentu, préciser si les graphismes sont des bonus, etc. Il est encore trop tôt pour balancer un "ça avance plutôt bien", disons juste que je n'ai pas encore été immobilisé.

There's some good news: I resumed working on my level editor. Having a brand new game engine supporting more slopes and more physics won't be very sweet if I can't make level for it, right?

Well, I started with fixing 'meta-buttons', that widgets palette on the right of the map edition that let you define blocks properties. It is still too early to claim "good progress has been made". At this point, the best I can say is that I haven't been stopped yet.

There's some bad news too, unfortunately. If there is progress, it is even slower than Wintergatan's marble music machine. I'm happy if I managed to work 3 or 4 hours a week on the topic. I started my todo list in my notebook so that I can plan the things to happen even though I might not be ready for more screen time by the end of the day.

La mauvaise nouvelle, c'est que ça avance encore plus lentement que la machine musicale à boules de Wintergatan. Si je "travaille" dessus 3 ou 4 heures par semaine, c'est beaucoup. Heureusement, donc j'ai mon calepin pour y cogiter quand j'ai un peu de temps libre, pas d'épisode de Castle en retard, mais que je ne suis plus trop d'attaque pour me coller devant un écran.

Pour situer, j'ai même carrément commencé un thread twitter avec des p'tits bouts d'avancée parce que je sais parfaitement bien que quand je serai finalement devant le bon PC (plantage de desmume pendant que j'essaie de faire tourner l'éditeur sur le PC plus souvent disponible), j'aurai probablement oublié le calepin à côté de mon téléphone dans mon "cubicle" au premier qui me sert de bureau depuis que je suis en mode télétravail.

I had initially thought that once planned, I could crunch the thing in a couple of evenings, but no. This has turned so much into micro-development that I even started a twitter thread to post my screenshots and track "what's to do next". Left foot (one fix). Right foot (another bug discovered). Left foot(another fix). Right foot (yet another bug).

Not that ugly code got written, but the dependencies of what I had foreseen to need changes was of course imperfect. Sometimes more buttons means I start trashing the VRAM with my "back-up memory". Another time, I notice that the 'autorun.nds' used for tests doesn't know how to clear the screen (and turns it all red). Every step takes only an hour or so, but since that's all I can afford per sprint evening, it starts remembering me of how it felt to write code when I was 12 and my parents told me "that's it. 55minutes. Now save your work and wash your hands: the dinner is ready". (except that I'm one of the parents and that I'll have to make the dinner ready ;)

"Tiens c'est quoi, cette barre verte" ... une petite heure d'investigation. un commit qui corrige le mauvais positionnement de l'espace de backup dans la mémoire (oouhhh). Je déclenche accidentellement un "mur rouge" en voulant vérifier que tout va bien mais il est trop tard: ce sera pour un autre jour.

Et cet autre jour, je constate qu'un peu de refactoring serait le bienvenu avant de chercher l'erreur. Paf, une fois le refactoring terminé, il est déjà temps de refermer le laptop. Jour suivant, je fais les recherches avec gdb. Mais une fois le problème identifié, bardaf, il est temps d'arrêter.

Bref, je crois que vous voyez le tableau. ça rappelle un peu les conditions de programmation BASIC de quand j'avais 12 ans, tiens.

Well, let's not get disappointed, shall we ? I finally got translation-on-loading repaired yesterday. I refreshed how-autorun-checks-VRAM in my brain. Maybe I'll be able to fix one more bug tonight? Or I'll watch some more of Castle, S5 with my Fairy.

Wednesday, April 01, 2020

The Dreamland Map

I'm reaching the last pages of my plan-your-things notebook. It helped a lot completing both real-world and hobby projects. I've got more books available to take over, but I also need to make sure I won't miss contents of the 2019 book when I'll be hanging around with the 2020 book. That's why the 'todo maps' are on flying sheets rather than on proper pages.

Maybe there are things I should blog for remembering. Clearly there are things I should doxygen...

There are things I still need to blog in there. Notes I've taken about SNES hardware, for instance, and similar hardware features from the NDS which I haven't used yet.

And then, there are game analysis things, which are totally unrelated to tools & engine development, but which I'd like to bring into the 'design class'. Those, hopefully, will not be missing if I don't have them around in the new book.

You see, having the dsgametools code around in a e-boox is nice, but I need some additional place to "think out loud", and with my eyes not liking using screen more than 10 hours/day, it cannot only be this blog anymore. That's what the notebooks are for ;)


Wednesday, January 08, 2020

L'encodage de la physique du sol

Bon, j'ai pris un peu le temps de cogiter à ce dont j'ai besoin pour les nouveaux types de sols dans mon moteur de jeu. Je sais que je veux plus te types de pentes et plus de types de physiques, mais en relisant mes notes sur les pentes pour comparer ça à celles de Ishisoft, je suis tombé sur un os:

Si je veux des tapis roulants qu'on ne sait pas traverser, il me faut des tiles "physiques" avec la propriété "IS_WALL". Ou plutôt sans F_PLAYER_THRU. Cette propriété va être testée sur l'ensemble de la zone que le joueur (ou un ennemi si on regarde F_MONSTER_THRU) voudrait occuper après son mouvement.

I took some time to make a list of those 'special grounds' I'd like to have in my game engine. More slopes, that was an easy one. But while I was comparing my plan to Ishinsoft's tigsource post, I noticed a potential issue.

If I want to have conveyer belts that act as solid structures, I'll need physics-changing tiles that also have some IS_WALL property. Well, actually, that doesn't have F_PLAYER_THRU, since the 'cando' system allow move to some area only if a set of properties is true for all the tiles covered by this area.


Mais si je veux des plate-formes glissantes en jump-thru, il me faut des tiles "physique du sol modifiée" sans la propriété "IS_WALL" (donc avec F_PLAYER_THRU, cette fois-ci). Jusqu'ici, comme la physique "glace glissante" et "tapis roulants" sont dissociés, je pourrais m'en sortir en définissant aussi les propriétés de collision pour chaque type de physique.

I also want slippery jump-through ground, which requires physics-modifier tiles that act as plain air if you jump through them (so with F_PLAYER_THRU set). Hopefully, slippery ice and conveyer belts are distinct things, so I could just have per-physics-tile properties set and we'd be done.

Les ennuis commencent si je veux un mur solide avec des pentes et une physique particulière: à l'intérieur de la structure, il faut que des tiles avec 'F_PLAYER_THRU' pour qu'il n'y ait pas de murs cachés dans la pente. (Un vieux truc mais toujours indispensable avec 'cando' et ses flags) et sur les bords de la structures, il faut que je repousse les assauts des sprites trop entreprenant pour les obliger à attendre le sommet avant de s'installer.

ça me consommera 2 types de tiles physique. Ce n'est pas forcément un cas fréquent et on aura pas nécessairement besoin de dédoubler tous les types de physique.

Things really get nasty when you consider structures like Aladdin's sandfalls (we should have some in some Sonic games too). There are physics tiles (pushing the player to the left) involved and slope tiles involved. Some physics tiles will have to let the player thru, else they will get stuck into the slopes (that mostly happens in the middle of the structure), and other physics tiles will have to act as walls at the edge of the structure, so that aggressive speedrunners don't get through. I don't see shortcuts to workaround the situation: we'll need two separate tiles type here, despite they'll have the same effect on physics (push player to the left).


Du coup 1) il faudra regarder sous une pente pour avoir ses paramètres de physique et 2) ce sont les contrôleurs qui conserveront les informations dont ils ont besoins. Le coefficient de friction dans le contrôleur 'momentum' qui traduit les impulsions en vitesse et 'stopper', le fait d'être poussé dans un sens ou dans l'autre dans 'walker' et 'needground' etc. (on y reviendra).

Et pour afficher tous ces types (pas loin de 250 en tout), il me faudra plus que mes 16+n petits tiles utilisés actuellement. Je n'ai pas la place pour mettre tout ça dans la "zone libre" de caractères prévues pour les widgets (128 caractères, juste après les codes ASCII): je tombe dans l'espace prévu pour les écrans. Mais j'ai assez de place après les écrans. (oui, ça n'a rien avoir, mais j'avais besoin de le garder sous la main).

Wednesday, January 01, 2020

TileMap

I had a remark in my notebook, wrote a few months ago, where I felt it weird that some parts of the game engine would require a SpriteSet where they actually needed information about the level map, and that the SpriteSet class was actually the only object capturing the map pointer, as well as its dimensions.

I then realised there was several places in the code where you'd load a map from a file, and it was tricky to use only one of them because one is within SpriteSet and the other (in the level editor) has no use of such a SpriteSet. It was time to introduce a new class with informations about a loaded map. Refactoring things went pretty fine and I could even repair a few things thanks to the 'unit-testing' tools (and thanks to the 'watchpoint' feature of ddd).

Well, I realise that doesn't mean a lot. That's all I could craft since I'm on holiday, I'm afraid. Happy new year.

edit: now, with only one class doing .map - to - memory conversions, I can make a new unit-testing tool that operates on level maps. I stuck to the idea of having some 'generic' tool invoked in scripts to define test cases based on reference data, but I pushed it on step further than 'cmdck' I wrote in early 2019: 'mapdo' handles a stack of level maps in the way a RPN arithmetic evaluator handles a stack of numbers. And you can quite easily define new 'operators' that act on that stack. It will help for things like cropping, splitting, patching etc. and can also help for tests such as "load level1.map save test1.map load test1.map eq" to check the level hasn't changed after being saved-and-reloaded (e.g. on-the-fly newmeta conversion produces the same contents as PHYS chunk loading).
  • by just passing "show" as the constructor argument to CommandHandler, this handler will be invoked whenever we see "show" on the command line
  • CommandContext.maps is the stack of level maps,
  • CommandContext.next() provides one token from the command line, for both commands-to-handlers lookup or for command arguments.
  • it could be further simplified into a void run(cc) since we no longer need to communicate the amount of command line tokens we consumed.

I love how both the core loop and the handlers are elegant, although I'd have loved a more in-line syntax like case "show": or show=>sub { ... } as well, but they wouldn't have worked in C++, would they ?