Saturday, August 15, 2026

Le fight club, version cflags

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

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

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

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

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

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

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

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

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


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

Tuesday, August 04, 2026

A bit of CI/CD ?

I'm not considering to add some for these projects at this point, despite I now have a few things on codeberg and codeberg sure comes with some CI/CD option, maybe they'll look like the one of gitlab which I've had to deal with today.

Most of gitlab's CI options are tweaked through variables within the .gitlab-ci.yml file of your repository. Most of those variables are free to configure yourself but some directly affect the “Getting source from Git repository” step, especially GIT_SUBMODULE_STRATEGY, GIT_STRATEGY (where you can tell whether you want a full clone or a mere fetch of the branch you're using in your job).

And unfortunately, it's one of those case where git turns out to be complicated, with many trivial things (do you have a "main" branch here?) requiring long commands (git show-ref --quiet main ... you thought that would have been one of the 8+ modes of "git branch" command ? too bad :P) that you may have to post-process. For instance, you can pick only a few commits at the top of some branch, you need not to crawl back to that initial commit.


  mkdir mere_window
  cd mere_window
  git init                   # a new place to toy with commits
  git fetch ~/myFavoriteRepo --depth 10
  git checkout FETCH_HEAD    # so we're somewhere on the history
  whereami 80

See ? 1) not all commits are there, although I asked 'whereami' (alias wh) to show me at least 20 of them, and 2) at the bottom of it, there's one tagged with (grafted). If you had branches merged lately, you might have more. Such grafts still have the same ID as the original commit, but they contain much more things if you show them: the whole content you're missing since repository started is condensed in such grafts. They'll delegate that extra weight to a deeper commit if you decide to fetch again with a higher depth, and turn back to their original size.

But back to gitlab. Its default setting seems to be to fetch with a depth of 20, performing what appears to be dubbed "a shallow fetch". You can spot that with "Fetching changes with git depth set to 20...". Mostly sufficient but if the CI/CD is introduced late in the life of the repository, and if you've been working on long branches for a while, it might not know about the main branch at all. That turned to be a problem for some packaging steps, but hopefully, we have GIT_DEPTH that can tweak things, and setting it to "0" is the way to tell gitlab to drop the --depth argument altogether. There at least, you should have some value of "main", even if it isn't the latest (just the latest known to your branch, I presume).

Gitlab may also play trick on you by keeping the things you already fetched when you start some old test again, just to find that the branch is now listed. You know it does when the job step will mention it "Reinitialized existing Git repository in your_path".

One more trap to avoid: git branch does not list *all* branches. Only those you created locally by checking something out. You'll need an extra -a to also show the remote branches (or -r to see only them).

Sunday, August 02, 2026

Un dernier ver ?

Si vous avez un peu essayé n'importe laquelle de mes démos "green zone" ces 20 dernières années, ça n'a pas pu vous échapper: le petit ver jaune - ce croisement entre un combattant dans Worms Armageddon et un poison slug de Commander Keen - est pénible.


Jusque là, je ne lui avais jamais fait d'animation "éliminé, le petit ver". On l'assomme, il attend, il repart. Il n'avait qu'un rôle minime dans Apple Assault... et le fait qu'on puisse le réassommer à volonté y permettait de reprendre des points. On le supportait.

I've had to apologize about that point to about any beta-tester who tried the Green Zone: the woodworm feel unfair and annoying. You could stomp it, but after a mere second, it would wake up and resume worming. Unlike the Appleman or the the Dumblador, there's no visual clue that the worm is about to wake up, so you're likely to take a hit from something that seemed defeated just a couple of seconds earlier.

Enfin, on le supportait mais de loin, parce que sa manie de repartir à l'attaque sans avertissement, c'est certainement ce qui vous a pompé le plus. Alors le week-end dernier, après avoir déposé les gamins en camp, j'ai allumé la DS et refait 3 petits dessins de ce ver tournoyant dans les airs pour qu'au moins, quand on lui roule dessus avec une pomme, on en soit quitte. ça ajoute de l'interaction et en théorie, ça devrait être rigolo à voir.

The core reason for this are a) the lack of a proper "defeated for real good" animation and b) the fact that worm.cmd was intended to be a tutorial for "the most simple ennemy you could think of". I could justify it for Apple Assault, where the fact it was never really defeated implied you'd always have a way to build up your punch meter. But for Dreamland, it no longer makes sense. Especially when you can throw an apple rolling over them! So I picked up my NDS last week-end and drew a few frames that make it look like it's spinning mad in the air. Yes, exactly as if you had used the bat of Worms Armageddon (or PWorms demo ;).

Il m'a fallu un peu de chipotage pour que le sens de rotation soit cohérent avec celui de la pomme, et j'en ai profité pour lui rajouté un état "détection" qui le remballe directement dans l'état "assommé" s'il sent Bilou à proximité. J'aimerais aussi rajouter une autre fioriture, un état "se fait rouler dessus" qui le maintiendrait au sol jusqu'à ce que la pomme soit passée, et ça, ça va sans doute demander un petit contrôleur supplémentaire...

I'm not quite done with it. Not yet. I feel like the worm starts spinning a bit too early, and I don't really want to fix that with a hard-coded delay but rather by saying "when the apple is done rolling, the worm get caught by the "leftover motion" and *then* starts spinning and falling. Maybe it could be settled with additional hitboxes, and maybe not. If not, I sketched a state machine fix that would help, with a "rolled_over" state, a way to attach the worm to the apple when entering that state and a controller that triggers an event when we're the attached item is far enough... or maybe the regular "track another gob" controller would do the trick if I make the "dead zone" (where it doesn't pull your controlled gob to the left or right) configurable in size (spoiler: it isn'tnow it is). That would give


$STUNNED->$ROLLEDOVER on hit0 [w0 0 >] (128 :0 A);
$STUNNED->$ROLLEDOVER on hit1 [w0 0 <] (128 ~ :0 A);
$ROLLEDOVER->$LKICKED on event0 [v0 0 <] (400 ~:1);
$ROLLEDOVER->$RKICKED on event0 [v0 0 >] (400 ~:1);
$ROLLEDOVER->$RECOVER on done (0 :1)
with
$ROLLEDOVER :anim7 {
    using tracking(@ over 12);
}

And then I'll have something else to fix regarding whether a monster that get hit by a flying-apple-weapon is strong enough to turn back the apple (funky funghi, appleman, caterpillar) or let it fly through (worm, berrybat).  

Un dernier détail qu'il faudra régler: de base, si on touchait le ver avec la pomme avant que la pomme ne se soit mise à rouler, la pomme rebondissait dans la direction opposée. Un reste de quand elle était un taille-crayon, j'imagine. Mais maintenant que j'ai modifié le script de la pomme pour qu'elle passe à travers le ver, elle peut aussi passer à travers les autres pommes ... pas terrible. Il faudrait bien que je me donne une variante de F_WEAPON qui indique "ennemi léger" et une autre "ennemi lourd", ou encoder ça dans encore-une-autre-variable-propre des gobs, ce qui serait sûrement plus facile, mais moins cohérent avec le type de programmation proposée ... un peu comme ajouter un "if" bash dans un Makefile, quoi :P

L'occasion de passer au nouveau système de flags de collisions ?

LEDS ... The forgotten branch

I completely forgot to tell you about that patch from early June that allowed to see clearly the space occupied by larger monsters in LEDS. And I forgot to pull it from "the cube" and to push it on sourceforge, too.

It did not work exactly how I hoped though, so there was still some manual tweaking to get those bouncy branches properly aligned with the tiled tree when I assembled the tree, and I even figured out why. But well, June was fairly crowded IRL.

I even missed to mention that when testing the new tree at my fairy's birthday, my brother almost immediately soft-locked Bilou by just trying to walk from a tiled branch to the sprite branch. It took me some time and a good deal of DDD to realise what was happening: the bouncy-block hidden within the branch would only progress in its state machine if something was falling on it but in this very case, Bilou isn't falling. So Bilou did the transition to the "soft-landing" state while the thing he's landing on ignored him altogether.

So I'm taking a moment this morning to try a patch I think was still required: seeing some random collision box will not help you craft your level. What you need to see is the bounding box of the object, the one that materialize its presence in the world.

...

edit: Ah. Yeah, of course. I'll have to push that new patch, else I'll start hunting for it again when I'll want it running on NDS for more map patching ^^"

Wednesday, July 22, 2026

Apple Assault Advance ?

 Ah, yeah. Early this month, while the heatwave had not burnt our energy and house wasn't yet a post-camp-departure-mess, I had that Silly Idea (tm) that I could enter the

I would have read https://gbadev.net/resources.html#articles, installed the GBA devkit in addition to the NDS devkitpro (reality: done, but where) and I'd have quickly (ahem) converted the Green Zone graphics into 16-colors-per-tile so that they could fit in the smaller video memory of the GBA. Some sprites (funky funghi, Bilou) would have been turned into 16-colors too while some others (appleman, mostly) would have stuck to 256 colors because they're taking more than 16 :P

Only then, I'd have tried to rebuild the Dreams engine for GBA and imported the Dreams animation over the Apple Assault levels, and that would have been the basis for Apple Assault Advance. Luckily enough, the sound engine promoted by devkitpro would have been happy about my brother's good old 6-track variant of String Tracking.

Likely, I'd have needed to find a way to compile the GobScript state machines into plain old data that could stay in ROM so that the smaller-sized (256K?) GBA RAM could have been saved for really-read/write features. Same for the maps, most likely ... They're not that big, so they could have been fit to RAM. Maybe they would have to so that collectible tiles would have worked. (not that there are many such things in Apple Assault).

But that was before blogpress started pressing me to develop it again. I think I'll focus on making first steps with bosses in NDS Dreams engine, instead :P 

Saturday, July 18, 2026

The July Demo

Ooops Ooops oops. It's about time I tell you about the releasable nds I uploaded last week ... I wanted something featuring the latest Funky Funghi and applemen improvements that I could share over the not-too-new itch.io page and tried the development log feature to write a blurp about it. But of course, July is always super-crowded to the point I feel like an impostor when just taking time for me. And carbon-induced heatwave didn't help.

I also managed to put it on sourceforge download before my own laptop's battery told me to stop and go to bed...

Swimming got improved, too, and we finally see all the branches of that important tree, although it could use more leaves at the top ... that shall happen later on.
  

Wednesday, July 15, 2026

It's blogpress time again

French journalists have a word for that seasonal topic that comes up again in newspapers when every high-end interviewers are on holiday and things are up to interns: "Le marronnier de l'été" ... and it may feel that doing some blog-to-printable/epub conversions pops up every summer here, but hopefully not for the same reason.

The motion started with the late-night idea that "tiled" engine discussions could be a chapter 1 if the blog ever had to be converted into a book, but also that editions could use their own tag, like "ch1" for that chapter 1. On the next day, I was dusting off repositories and working directories for the next "blogpress" round, motivated by the fact that I'll have up to early August before the next automated snapshot/takeout.

I wrote a small introduction to that chapter (french only, atm) and then grew surprised by how little preparation there was on that "tiled" tag. Reader would just be thrown stuff at their eyes, and they'd better understand things. Sure, I introduced it rather late, not as I was writing those posts... I discovered a bit sadly that most of the tutorial I had used by the time are now offline (and even their archive.org copy are firewalled T_T by "my" most powerful computer).

I edited some of the early posts in "tiled" following the idea that "Many posts contain parts that would be useful for a chapter (say, one about tiled game engines) but also parts that don't quite fit. So how about having <span> or <div> tags assigning those items a "no-ch1" (or no-ch5 when I'll be at chapter 5) and let the simple.css make them display: none ?"

Finally, 4 days ago, I managed to get all the issues fixed in my scripts and re-generate a good-looking page that I can use in calibre to export an epub file. And because each issue involved a good deal of html snippets and that I'd rather have a clipboard to compare them when that happens, I decided to use codeberg's issue tracking system for that. 



script output, as uploaded on codeberg

what it looks like on the blog

what it looks like copy-pasted in office

what I had from older (2025) script output
We're not fully done, but it's getting in good shape. I couldn't get it printable, though, as the browser seems to ignore the CSS instructions that make it neat and stylish on screen. 
Next points would be
  • recognized purple-colored-text as English
  • if a picture is large enough to cover most of the column width, don't try to make it floating.

A sad discovery while working at all this was that the 72x72 thumbs are no longer automatically provided by the takeout. They might have annoyed me when doing the last conversion back in 2025, but no more than I month later I had figured out that they could be a "magical portal" to posts and uploaded them to neocities.

And now I have another project for those thumbs. I had included the "milestone" tag together with "tiled" to get a bit of reminder of what had already happened and what not between two "tiled" posts, but many of the milestones are too large and distracting compared to what I want. The first paragraph (?), the date, title and the thumbnail would likely be sufficient. Hopefully, I can recontruct some thumbs URIs from regular picture URIs, but I'll need to resort on my drive-archived blogthumbs.zip for the missing ones...  

There's one line of all that that I'd like to bring here. It's the incarnation of "make the possible easy" part of Perl:

$post=~s/src=\"([^"]+)"/src="$larger{$pix{$1}}$escaped{$1}" alt="$1 ; $pix{$1}"/sg; 

In that single line, we iterate through (thanks, g modifier) all the image URLs of a single post and patch them using the hash tables that we constructed by parsing "temporary" files that other scripts produced. No need for split-patch-join sort of loop. 

edit: Some commands used to generate the latest version:

THUMBS=../thumbs/thumbz.html perl ../git/list-atoms.pl ../bilou/feed.atom <(cat ../pictures3.lst ../morepix.lst ../pictures2.lst) tiled '(milestone)' > tm3t.html
where "thumbz.html" is the page featuring a link & thumbnail for every post, which list-atom will look for contents. It needs so many .lst files because I worked on list-
grep '<!-- all images' -A9999 tm3t.html | grep ^i | fe - "cp % /d/local/pages/geds/attach_files/ -v"
I added a flat list of filenames with the pictures at the tail of the HTML file so you can "more easily" cherry-pick the files you need (save-as-html in web browser is doing too weird things)
BLOG=https://sylvainhb.blogspot.com perl ../git/thumbify.pl <(perl ../git/summarize-atoms.pl ../bilou/feed.atom) > thumbz.html
Above: how the thumbs page is generated, below, how I got some -0- thumbs from files that had more normal identifiers. (applied in the folder where I unziped blogthumbs.zip I got from that-time-where-thumbs-appeared-in-exported-data.
ls i* | sed -e 's/\(i[0-9][0-9]*\)-\([^0]\)-\(.*\)/mv \1-\2-\3 \1-0-\3/' | grep -v '^i' > renamethumbs.sh

edit+: fine-tuning keeps going on mastodon