While reviewing the "tiled" chapter produced by my blogpress tools, I remembered that landing on a slope still produces odd effects from time to time. And then came an idea to reproduce these conditions in the unit-test environment.
Just as I was observing that the "dkp54" branch has been around from a long time and so has been the "cflags" branch and that "right, I promised myself I wouldn't merge things unless I've first checked they still pass automated tests."
And unfortunately, right then, the tests were not passing, they were crashing. First with an exception and then with a segmentation fault. The "offending" commit was something from 2025, a few lines that will report (rather than ignore) syntax errors within the GobState parsing.
It took some times to identify where the error was introduced, much less to fix it (hopefully) and so the 'dkp' branch (toolkit update) is now finally merged and the cflags can be just that: a branch propagating the new collision mechanism (and not a adventurous combination of features).
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 ScreenshotSaturday 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.
edit: there was one last thing I had spotted that wouldn't work as expected: sticking dumbladors on pencil spikes. Especially, the dumblador might still wake up. So I dug the good old SchoolRush and checked what happened. Verdict: the dumblador *might* wake up there too, but it looks like it's much more unlikely to happen due to terrain geometry.
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 historywhereami 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).
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
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 ^^"
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
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.
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 alltheissues 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:
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:
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)
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
Bon, oui, le GB studio, c'est rigolo comme concept. Et ça fait pas mal de titres tout à fait sympa comme ce dinosaure de luxe. Mais y convertir du Bilou, je vois mal le truc ... même Badman aurait du mal. .. mais, petit délire de Mars ... j'ai déjà un jeu qui avait été pensé pour le monochrome dès le début: Caliméro!
On ne va pas se mentir, par contre, ça n'avait pas vraiment été pensé pour les 160 pixels de large du DMG. Le personnage ne ferait pas loin de la moitié de l'écran!
I've spent a good amount of hours on GameBoy, back in the 90's, playing Super Mario Lands, Kirby and of course, Link's Awakening. So when I hear fellow developers enjoying to work with environment like GameBoy Studio and reaching a significant audience, I can't help thinking "shouldn't I try gameboy dev as well ?"
But what game would I make there that wouldn't be over-ambitious for the platform ? That can't be Bilou and while there has been a pseudo-gameboy level in Badman III, it's unclear it would be working with the rest of the game. But ... how about "my" monochrome hero in his monochrome adventures because it was originally designed on a monochrome 8086 back in 1990 ?
Une fois remis à une une échelle un peu plus raisonnable, avec un perso en 24x24, ou quelque-chose comme ça, on commencerait à pouvoir jouer. Pas que le jeu deviendrait automatiquement un hit, hein, mais voilà.
So I looked up for a GB screen template, dug my old Calimero screenshots and started to tweak colors to see how it would look like... and spoiler alert: it looked huge. Calimero was designed for 720x348 screen resolution and then ported to VGA 640x480 keeping its original sprite data, of 54x50 pixels or so. that's nearly 1/3rd of the GB screen in each direction. I know Calimero "gameplay" has always been about die-and-retry and you-should-have-known, but it would be pushing the thing too far. Scaling the sprite to some 24x24 would allow something much more playable.
Oh, bin puisqu'on en parle, je pourrais aussi vous mettre le lien vers une série de scans de l'été dernier. La Pipe Zone, bien sûr, inspirée de SMB3 et qui sera un thème récurrent dans les niveaux de mon frère, la pyramide dont le design ne m'a jamais convaincu et la "water zone" qui a un petit côté Alex Kidd.
Même quelques boss ;)
And what better post could I find to put a link towards the set of scanned level designs I did last summer ? Scans, I mean. Level designs are from 1989-1991 and from my brother. Let me tease you with this "pipe world" (obviously influence by the pipe world of SMB3). I'll let you explore the link and find the pyramid levels as well as Alex-Kidd-inspired bosses.
Been reading this far ? well, that deserves a link to that other mastodon thread where I tried to convert some of Bilou screenshots into 4-shades-of-grey mockups, after somebody posted a music disk of Mickey Magical Quest for Game Boy in January '25...
Et on pourrait essayer de finir en beauté avec une petite image de Bilou en 4 niveaux de gris, avant et après retouche par votre serviteur de janvier 2025... qui ne tient absolument pas compte des contraintes du genre "3 couleurs + transparence par pavé de 8x8", ni du nombre max de sprites par lignes, ni du nombre max de tiles de la GB ni rien. Un pur délire de Gimp, quoi.
Toujours en mode "post-desktop". Toujours avec mes carnets qui me servent entre-autres à suivre la progression (lente mais présente) du projet "dreamland". Tout le jeu, avec ce genre de carnet, c'est d'arriver à conserver facilement accessible les choses qui sont encore pertinentes. Souvent, ça passe par un coin de feuille sur lequel je vais me faire une espèce de petit index illustré des pages sur lesquelles j'ai encore des cases de "todo" à cocher ... régulièrement quand la dernière page de ce genre a perdu son statut de "priorité absolue".
Working without a desktop ... without a central unit where your project has its home and grows ... it has slowed me down for years until I opted for making the new home for my project to be made of paper instead. But that means I need to dig older contents into newer pages on a regular basis. And part of the solution for me was that this notebook hosts everything I need to keep track of.
A trick I've started using lately was to make visual/graphical table-of-contents towards past pages, in this case, all the pages where I have "TODO" items still pending, like a small mushroom getting hit by an apple to remind of the todo-state-machine that guided me throughlatest screenshot saturdays
C'est évidemment la page 61 qui a ramassé le plus de cochettes ces temps-ci, avec les interactions autour de Funghi et les Applemen, au point qu'il a même eu droit à sa petite barre de progression.
D'autres points avaient été relevés lors du feuilletage et vont se retrouver grisés: ils ne sont pas utiles pour proposer une "première démo" de Dreamland. C'est le cas pour les ajouts juteux autour du poing-écrabouilleur de la pyramide. Oui, ce serait plus sympa qu'il fasse de la poussière, qu'il fasse trembler l'écran etc. mais on peut très bien tester le jeu sans rien de tout ça.
There are a good number of the other todo items that are linked to water interactions and swimming but that's no big surprise: water and swimming have been added over the previous year to an engine that was unable to handle that before, so there are plenty of little things left to tune or fix.
Once I was done with that first sweep, I tried to rationalize: I'd like to be able to let people play the game as early as I manage, and many of the todo items, while valid, aren't needed before people play. Sure, big smashing punch looks better if it triggers clouds of dust and shakes the screen as it smashes into the ground, but none of this is a blocking point if it's missing ... that's why the punch "icon" is greyed out.
Si la page d'index visuel correspond à un moment-détente, comme certain(e)s feraient des mandalas, il y a aussi des petites notes beaucoup plus gribouillée sur des choses à corriger saisies au vol pendant que l'un ou l'autre essaye le jeu. Mon frère est particulièrement redoutable à ce numéro-là. Mettez lui un de mes programmes entre les mains et il va vous le soft-locker ou pire en moins de 2. Il aura fallu pas loin de 3 reboots pour qu'il puisse lancer une pomme sur Funghi le week-end dernier ^^".
Et comme vous pouvez le voir, c'est beaucoup autour de l'eau que j'ai pris du retard.
And yeah, many of the items in those sub-page are less eye-candy than the index. Many of them are on-the-fly sketches of something my brother or my son or someone encountered while testing the latest version on my NintendoDS. Sometimes they are summaries of other TODO items grouped according to the tools/energy I'll need to tackle them. I can't really setup WiFi transfers through my NUC-cube while the dinner is cooking. I won't have my blog at hand to remember me what I wanted to draw on the NDS once I'll be in a no-WiFi zone with my DS around. I'd better focus on editing code once I'll be in the good setup to edit some code, etc.
Il m'arrive aussi de temps en temps de faire une version structurée différemment de ces todo-index, où je re-trie les check-box en fonction de ce qu'il va me falloir comme matériel pour avancer: la DS elle-même, le laptop, le "cube", un moment WiFi ...
L'idée est d'essayer de mieux grappiller les moments disponibles et ne pas retomber sur "ah oui, il faudrait faire ça ... ah mais non, il faudrait d'abord que je mette à jour Bilou.cmd et je n'ai que la DS" quand j'ai une petite demie-heure qui se dégage.
Et forcément, c'est dans ces moments-là qu'arrive une idée du genre "mais oui! faire des ricochets sur l'eau avec les pommes!" ou "les chauve-souris cessent de vous pourchasser si elles rencontrent de l'eau (façon essaim d'abeilles Disney ;-)
And of course, I have to accommodate for the fact that ideas pop up when they feel it, not when I'm in front of a nice blank page on which a big title has just been polished :P
edit: for the next week-end, analysis and preparation happened thanks to the cube serving the repository over WiFi to the boox sketchpad and then coding happened early in the morning, outdoor in the Virtual Machine of That Other Laptop (better battery, awful keyboard) through sshfs as the files and compiler were hosted on the cube too but the emulator ran within the laptop. At least, the 1st half-hour session was outdoor then the rest was coded on the "dining" table next to the coolness dispenser. That allowed me to have 3 items done (that's completing the page 61) and 2 screenshot saturday released :P
Funky Funghi, un des plus anciens personnages de la Green Zone sur DS, vient de se ramasser une pomme. Jusqu'il y a peu, la pomme serait juste passée à travers, mais alors que ce blog va sur ses 20 ans d'existence, j'ai rajouté les quelques lignes de code script qui manquaient pour que l'interaction proposée début 2022 devienne une réalité: on va pouvoir dégager les champignons du chemin à coup de jets de pommes.
Throwing apples around is a bit more fun since they've started rolling when hitting the ground, but one thing has felt odd so far: seeing the appleman crossing the path of a bouncing Funghi without triggering any effect. Since early 2022, I had the idea that we could have Bilou *bouncing* when hitting the hat of Funghi rather than being hurt, and that implied of course that a thrown apple should bounce as well. It was now time to implement that.
Ah, and yeah, I've played a good deal of the original Rayman, including throwing fist at bouncy plums and yin-yan balls to make them reach the place I wanted them to be. With all this new bounciness, Funghi is no longer just a hazard and you might actually want him to be *somewhere* rather than just wanting him away. Some of the initial ideas -- such as having the hat deflecting apples and only the foot being the target to hit if you want him moving -- quickly proved unpractical, and uselessly tricky to do, especially for a World-1 interaction.
Bon, j'avoue que comparé aux "prunes rebondissantes" de Rayman, on est sur quelque-chose de nettement plus détendu: Funghi ne risque pas d'aller rebondir contre un mur et de revenir vous écrabouiller. Il ne reçoit que la moitié de la vitesse de la pomme et ralentit de moitié à chaque rebond. Juste ce qu'il faut pour passer d'une souche à "entre les deux souches" en une pomme. Mais ça devrait être marrant quand-même vu qu'il y a moyen de ramasser à nouveau la pomme et de la lancer une fois de plus. D'autant plus que maintenant, il va aussi être possible de rebondir sur le chapeau de Funky Funghi! (c'est peut-être encore un peu fort, d'ailleurs).
La solution à laquelle je suis arrivé à coup de débuggeur d'expression est un rien intimidante ... entre autres parce qu'elle dérive de la collision destinée à faire rebondir Bilou, et que pour Bilou, je voulais que l'angle change selon qu'on arrivait plutôt sur le bord ou sur le centre de Funghi, comme s'il était vraiment un bumper de flipper. Pour ça, on va préparer deux valeurs et les combiner avec | dans le byte haut et le byte bas d'un entier 16-bit avant d'écrire le tout dans la 10e variable de Funghi avec :a. C'était rigolo avec l'appleman, mais ça devenait compliqué d'y ajouter le transfer d'énergie ... donc au final, pour l'appleman, Funghi agira toujours comme un mur qui absorbe 50% de sa vitesse horizontale et n'a aucun n'effet à la verticale. Et sur l'énergie absorbée, la vitesse acquise par Funghi est moitié moins importante que celle qu'avait l'appleman ce qui nous permet de calculer qu'un Funghi pèse à peu près 2 Applemen ;P
I ended up with something simple for Funghi/Apple interaction: half of the speed of the appleman (w0) is transferred to Funghi, and the other half is bounced back. But since Funghi is bigger, the half it takes only result in 1/4th of the speed. Not pushing him very far, I'm afraid. And well, that's only the part w0 4 / v0 + :0. All the things that happen before are reusing the "protocol" defined for throwing things where the thrower decides of the direction of the thrown object I already used for dumblador. The X speed and the Y speed will be set in the 10th register of funghi with :a and later used by the appleman with
$RTHROWN->$LTHROWN on hit0 [C_THROW wa 0 < &] (wa $ff00 & :0 wa 256 * :1)
Mais dans le code de l'appleman, j'ai quand-même gardé un code générique qui se contente d'appliquer le vecteur-vitesse qu'il trouve dans la 10eme variable de ce qu'il a heurté. ça pourra me permettre par la suite de faire en sorte que les branches rebondissantes puissent elles aussi renvoyer les applemen ^_^. Petite subtilité: la transition hit de l'appleman est testée avant la transition found de Funghi mais c'est found qui fournit le vecteur vitesse que hit va utiliser. c'est pour ça qu'il y a un test qui s'assure que wa < 0, pour que lors de la première frame de collision, l'appleman conserve sa trajectoire pendant que Funghi calcule l'impact. A la 2eme frame, wa est défini et la trajectoire de l'appleman pourra changer.
Et pour la collision Bilou/Funghi, c'est la distance entre le centre des hitbox (we) qui va déterminer l'angle de l'impulsion que Funghi va nous imposer, entre (-3,0), (-2,-1), (-1, -2), (0, -3)
The idea inintially was to use the same behaviour as the one I coded for Bilou, where the angle you're bounced depends on the position you hit Funghi on. That's decided in Funghi's script with
state0->state0 on found$bilou [C_THROW we 0 >= &] (we 4/ 256* we 4/ 3 - $ff & | :a)
where we is one of the collision-specific parameter (rather than an internal variable of the collided object) containing the center-to-center distance between Bilou and Funghi, ranging from -24 to +24. At the very edge of Funghi, you'll get bounce horizontally by (+-3, 0), and at the center of his hat, you'll be bounced by (0, -3). In between, you could get (+-2, -1) near the edge and (+-1, -2) near the hat. And yup, it's got the overall expr_1 256* expr_2 $ff & | shape again to put both together in a single variable.
I still had to do something for how static Funghi looks when hit by something. My first attempt failed because transanims with characters that are made of a single sprite, and so far, Funghi was still like that. But behold, Funky Funghi 2.0, remade in AnimEDS after I separated hats and feet, so that I can animate it more freely, at in-between frames of some sort, etc.
It doubles the amount of memory it takes, but I think it's worth it.
Il me restait un truc à régler: Funghi donne l'impression d'être en béton et que rien ne peut lui arriver même quand on rebondit dessus ou qu'on lui lance une pomme. J'aurais bien essayé de réutiliser l'animation "rebondit au sol" dans un sens ou dans l'autre, mais Funghi est toujours un "SimpleGob" premère génération, et je ne leur ai manifestement jamais ajouté le support des transanims.
Je profite donc de la p'tite canicule du week-end pour redécouper un peu Funghi dans le Sprite Editor, refaire ses animations dans AnimEDS et rajouter un "fait rebondir un truc qui arrive du haut" ainsi qu'un "fait rebondir un truc qui arrive sur le côté". Ce n'est pas spectaculaire, mais ça donne plutôt bien quand-même.
C'est Régis Monterrin qui avait attiré mon attention dessus avant que je ne note des bizarreries dans les tiles, un peu comme si l'artiste avait fait un chouette truc puis que l'outil pour exporter son travail avait buggé et que personne ne s'en était rendu compte.
Parce que bon, on a tellement de carrés répétés indépendamment de la texture, de transition brutale entre palettes de couleurs aux frontière de la grille-de-tiles que ça en devient presqu'un contre-exemple de pixel-art, où les spécialiste vous donneraient des astuces pour éviter qu'on ne remarque que tout n'est que carrelage aligné sur une grille.
En fait, au fil de l'évolution de ma "green zone", je suis passé par un état un peu de ce genre et j'ai noté que ça me faisait inévitablement penser à ce jeu C64: Forbidden Forest. (et sa suite, sur le screenshot)
Forbidden Forest, c'est le jeu qu'il vaut mieux ne pas regarder de trop près. Alors ok, pour un jeu de l'époque 8 bits, avec un maximum de 256 caractères à l'écran alors qu'il y a place pour plus de 1000 d'entre eux, c'est le truc le plus organique et le plus varié que vous puissiez faire. Là où l'état de l'art, ce sont les écrans interchangeables de "Pitfall" ou la répétitivité de Wonder Boy, ici, on est sur un scrolling continu d'arbres tous différents les uns des autres ... mais aussi sur une omni-présence de l'angle droit.
Tout ça disparaissait sur un bon vieil écran CRT évidemment. Juger du
graphisme de cette époque sur un LCD n'a pas de sens, puisqu'ils étaient
créés sur et pour le CRT
J'avoue que j'avais un peu de mal à y croire. Que le côté "patterns bizarre" du tramage ne pose pas de soucis, oui. Mais ces gros pavés ? ces lignes horizontales et verticales quasi-continues se feraient adoucir rien que par le balayage ?
J'ai cherché un peu sur youtube, des fois que quelqu'un aurait effectivement joué à ce jeu sur tube cathodique ... c'est un des niveaux qu'on avait fait avec J.L.N lors d'un "ludifestival", mais à l'époque, manette en main, on faisait bien sûr beaucoup plus attention aux feuilles-plateformes-géantes qu'au décor. Pas de chance, la seule vidéo que j'aie trouvé, c'est celle ou le joueur a coupé cette séquence au montage.
Mais pendant ce temps-là, Aurélien, lui, avait ressorti son bon vieux Phillips et sa méga-drive et re-joué à Castle of Illusion jusqu'à ce niveau-là pour refaire un screenshot (non?) réaffiché l'image de Régis pour la prendre en photo.
Et là, il faut bien reconnaître qu'à part la ligne horrizontale à hauteur du pied de Mickey, sur la gauche, ça donne plutôt propre. Ni les joueurs ni les testeurs de l'époque n'ont dû y trouver à redire.
Bon, fondamentalement, ça ne change pas grand-chose en ce qui me concerne: puisque mes pixels à moi vont être sur la NintendoDS, je n'aurai pas de flou gaussien pour venir à ma rescousse :P
I have a git folder that is accessed both by a windows host and a linux guest from a VM (as a shared folder). Everything was fine until some git package upgrade started warning about "in the working copy of 'project.txt', LF will be replaced by CRLF the next time Git touches it" (or the equivalent from the Linux guest).
I'd like to avoid cloning the repository twice and I already have something that makes these file LF-only on the master repository. I set autocrlf = false in .git/config, but that does not seem to help.
The manpages of git are heavy, freaky and intimidating to say the least. But I guess if I had rtfm'd them, I'd have eventually encountered the git config --show-origin --get-all core.autocrlf command, which conveniently reports all the files where the given configuration item. I'd have figured out that while I had my local configuration file requiring "do not do auto-CRLF conversions", the system-global configuration actually had the precedence. ... ridiculus, but that's the way it is now.
git check-attr -a project.txt and git ls-file --eol project.txt could be useful to check the current state as well.
With autocrlf=false in Git/etc/gitconfig, I don't have the warnings anymore, but I still have the file that is switching between CRLF and LF depending on whether Windows host or Linux guest is checking it out. It looks like the only way to get the desired behaviour is to edit * text=auto eof=lf in .gitattributes, at the root of the repository. I want that to remain a local decision, and hopefully, my colleagues haven't committed that file yet, so that'll work.
J'avais jusque là la 3.0.6 sur la machine windows du bureau ... qui m'a déplu sur plusieurs aspects. Petit tour d'horizon avant de passer à 3.2.4
sauf que tout à coup, c'est la 3.2.2 qui s'ouvre !?
les niveaux de zoom sont devenus beaucoup plus étalés, notamment quand on zoome avec CTRL+roulette ... au point que avoir un 200% ou un 300% "propre" pour une capture d'écran de pixelstudy devenait impossible sans aller entrer la valeur à la main. 3.2.2 corrige ça en permettant de monter à 33, 50, 66.6, 100, 150, 200 avec les raccourci clavier "+" et "-"
changer de couche avec PG up et PG down ne permettait que de sélectionner la couche, pas de l'activer pour les opérations de dessin et de copier/coller. c'est corrigé avec 3.2.2
Est-ce que je deviens chèvre ? Non. C'est le nouvel outil de sécurité du boulot qui fait les mises à jour dans notre dos. Sans avertissement, sans résumé d'opérations. Rien.
Restait le panneau d'impression qui indique maintenant "pas de prévisualisation possible". Un comble pour un programme de dessin ! Un petit tour dans la base des registres pour ajouter PreferLegacyPrintDialog=(DWORD)1 sous Computer\HKEY_CURRENT_USER\Software\Microsoft\Print\UnifiedPrintDialog et on revient à quelque-chose de moche, mais utilisable.
Quelques semaines avant de partir me reposer un peu, j'ai voulu faire un test de "3 rooms" sur ma DS. Pas de chance, il manquait une ligne - une seule - au fichier script sur la DS, de sorte que le fichier en question ne se lançait pas. Du coup, quand je me suis retrouvé assis tranquilou à une terrasse, je suis revenu sur cette idée d'éditeur de texte pour la DS.
I really could use a text editor running on the DS, to patch those script files without having to 1) turn the cube on; 2) stick the WiFi in; 3) setup upstream/downstream channels; 4) beam file out; 5) patch it in vim; 6) beam it in again; 7) try and most likely repeat from 4. And I did have a couple of hours by the swimming pool, sitting at a table to think how to approach it.
Et après quelques notes sur comment l'éditeur pourrait fonctionner, je retombe sur cette idée de "mode scribouille" qui me hante depuis 8 ans ... pour finir par me rendre compte que le meilleur programme pour tester le système, c'est celui qui permettrait d'encoder les patterns de chaque lettre.
Et donc, après quelques petites opérations de maintenance, je lance une nouvelle branchepour prototyper ça , un peu patraque dans mon fauteuil et pas franchement d'attaque pour grand chose d'autre.
Of course, it wouldn't take long before I tried to inject the "handwriting for DS" technique into it, and I realised something interesting: the "minimal viable product" to see whether I can truly write stuff with that technique is 80% of what we need to populate the recognition data. So after more ndsdev in a row that I've been doing over the last few months, I made a first version of "teds", working enough to decide that, yeah, it's kinda-working.
Je pourrais baptiser ça "un marathon ndsdev", avec son lot d'essai-erreur, de petites étapes prudentes et de passage par DDD pour me rendre compte que j'ai utilisé la mauvaise variable dans l'itération d'une boucle ^^".
J'ai maintenant une sorte de "minimal viable product" qui permet de tracer des lettres et d'effacer l'une ou l'autre lettre d'un L+LEFT. Assez pour constater que
des cellules de 4x4 pixels, ce n'est pas convaincant, vu les imprécisions du tandem stylet/DS
une "zone morte" en bordure de cellule permet effectivement de faire des "diagonales" de façon plus fiable
il reste souvent nécessaire de faire des "retouches" pixel par pixel
tracer les lettres d'un traît ou tracer les lettres "tranches de pixel par tranche de pixel" donne grosso-modo la même vitesse d'écriture: 30-32 secondes pour "there is no spoon" (16 caractères avec les espaces)
Next step will be storage and loading of the "recognition database" and selection of a "bank" of 8 characters to "train" from the ASCII set shown on the left of the screenshot.
Something is annoying me with the underground section of the green zone levels: it's too repetitive. It shows in everyscreenshotI try to make. I have variation tiles that could make it less uniform, but they don't really work if we repeat them. I have plans for a background, parallax layer underground, but it only really works in open environments, not in tunnels, and underground areas are mostly made of tunnels. in the Green Zone.
But those funny pillars might work as foreground layer as well! Maybe even better because they're bigger than the pebbles repeating tile of ground I have. They would focus the gameplay in a smaller part of the level just like a circle-of-light would, but with something pleasant to look at. The question is, how can I make it indeed focusrather than obscure. I don't want to make Infogramish game where you don't see where you're heading to because of the foreground.
Let's ask Bouli to make a bit of math, here: if my foreground layer advances by e.g 3 pixels everytime my regular layer advances by e.g. 2 pixels, then I just have to make a map that is 3:2 bigger than the playfield if I want to follow things properly.
I mean, my "foreground" map would be drawn over a 150% zoom up of the main map, and that should be it. At least, that's the intuition. How to confirm it quickly ? Well, how about cutting some paper to make a live overlay and make it move around. Of course, you have to consider that only a part of the result will be shown to the player, too.
Does that mean I need a special mode or a variant of the Level Editor ? ... maybe not. At least, not more than "use the "physical" layer of gac.map (move by 2:3) and let me edit gacfg.map on top of that.
The fun trivia here, is that the initial motivation was to find a way to have VRAM for textures now that I know it does not require palette slots. But while comparing the options, I came to the conclusion that I had no real use of 3D in the green zone anyway, except maybe to render more trees in the background... but checking Case Portman's Lost in Fuzz video, I realised that proper amiga-style parallax would work better than any 3D and would be easier to make here. And yes, I'm only using 2 tilesets out of the 256K allocated to the background tiles in Dreamland, so I could fit a 3rd one and another "infinimap" in the unused space ...
Does it means textured 3D becomes out of reach ? No, but that Bilou's Dreamland will sometimes use 3D, sometimes not (plain 3D does not require more VRAM, but it consumes one layer).
Does it means Yoshi-Island-Style dual screen action should be forgotten ? No, but it would only work in levels where we have no 3D objects and no fancy lush background/foreground maps.
Does it mean having Bouli or another character "telling the story" on one screen while Bilou is "living the action" on the other impossible ? No, but Bouli may have to survive within 16K of sprite VRAM, using DKC-like live-update techniques for his animations.
edit: sidequest finding: shifting extended palettes from 64K to 16K VRAM isn't that trivial to do. (but not required unless we want to texture 3D stuff)
Since the introduction of the appleman ROLL mechanics, there was something I couldn't completely fix: if you managed to throw the appleman straight into a "jump thru" platform, it would stop as if it was a wall, while you'd expect it to roll over the platform or fall through it instead.
I envisioned a number of solution to this problem until I realised there was one quite obvious one: just bounce the appleman upwards a little bit when that happens. It will then be able to advance sufficiently into the platform so that it is then in the normal "thrownroll" transition. If instead it was thrown into a solid wall, the bounce will be visible, but have no lasting effect
Au début, ça ressemblait à un petit détail: au moment de se mettre à rouler, un appleman pouvait se retrouver bloqué bêtement par un sol qui trainerait en l'air. Mais si, vous savez: ces plates-formes qu'on ne peut franchir que de bas en haut, mais qui vous retiennent quand vous allez de haut en bas.
Eh bien pour vous retenir, il faut qu'elle soient solides au moins pendant que vous tombez. Et à ce moment-là, elles ne font pas dans la dentelle: pas question de venir avec un "oui, mais non, mais regarde: en vrai je ne peut pas atterir, là: c'est juste le côté de mon haut qui passe de quelques pixels dans le bord de ton bas ... j'fais qu'passer, quoi!". Nada. Je me retrouve avec une pomme qui était lancée à vive allure et qui s'arrête nette sur un plan d'herbe à travers lequel elle passait sans problème quand vous la portiez sur la tê♪te, la pomme ♫ i' faut pas'l'nier.
And let's be honest: it would have been a nightmare to debug without the recently introduced GobExpression debugger. You can quite easily end up in a situation where you expect some speeds to have been non-null in some condition and realise that, well, no they're null here.
The alternatives I had envisioned were globally more complicated, like holding the speed for some time and then restoring it. More complicated in the sense that they required introducing new states in the behaviour or even new controllers. Here, it's just one extra transition that says "stay in THROWN state if {conditions}, but update velocities as follows"
C'était devenu un sujet de cogitation dans mon carnet, et un assez bon exemple de ce qu'on pourrait vouloir faire avec un contrôleur "around" pour contourner les obstacles. Au final, ça se passe de ce genre de complication: il suffit de redonner une petite impulsion verticale, juste assez pour que la pomme monte d'un demi-bloc et puisse atterir sur la plate-forme plutôt que de passer à travers.
Tout ça grâce au nouveau débuggueur d'expressions que vous voyez dans le bas de l'animation, qui représente chaque opcode par un caractère qu'on fait avancer petit-à-petit avec la touche L et qui complémente agréablement ce bon vieil Inspector Widget :P
somewhere, on planet Earth, there's a weird guy named Sylvain (aka. PypeBros) who loves to write programs and draw comics with a blue ball named "bilou". That's me.
If you have a blog that talks about similar stuff, just leave me a comment.