Saturday, July 12, 2025

Mario in Godot

Refaire Super Mario World dans le game-maker "Godot" ... j'ai envie de dire à la fois "tout ça" et "rien que ça". Pourtant, l'idée de Wye n'est ni de proposer un Mario World Studio ni son Mario World 3. L'idée, c'est de comprendre le fonctionnement du jeu d'origine en le reconstruisant dans un nouvel outil tout en apprenant l'outil lui-même. Et ça, ça me parle. C'est le genre de bouquin que je dévorerais mais ici, ce sont des vidéos youtube.

"In Super Mario World, Mario was considered fully underwater if both his head and body interaction points are touching water tiles. [...]

That's the kind of things you can learn by watching Wye's series on re-making Super Mario World in Godot, and learn how to use Godot in the process

I've been following the videos roughly since episode 1 or 2, but as Wye now address the water physics, I cannot just remain a silent watcher. I've spent too much time working on water physics myself, and I need to compare the approaches. Of course, Mario isn't using the "cando"  function. Instead, interaction with the world are guided by "interaction points" which remember the type of tile they're on. So for instance, 

"When Mario body is in the water but not his head, that means he is near the surface."

Du point de vue des collisions avec le niveau, Mario n'est pas une boîte. Il est ... une sorte de constellation de points qui ont chacun leur préférence sur le type de terrain 6 en tout, mais dont certains ne seront évalués que dans certaines conditions. Pour déterminer s'il faut nager ou non, ce sont par exemple ce sont les tests du milieu et de la tête qui entrent en ligne de compte. Et pour déterminer si on peut sauter hors de l'eau ? Bin il faut que le corps de Mario soit dans l'eau mais sa tête hors de l'eau. On évite en fait les complications du type "la surface est à la fois de l'air et de l'eau" dans lesquelles je me suis embarqué.

And only when Mario is near the surface is it possible to jump out of water ... and only if pressing UP in addition to pressing the JUMP button ...

The concept of interaction points comes from the disassembly of SMW itself and was discussed in an earlier video. They replace hitboxes when it comes to interacting with the world and there are 6 of them for Mario. But as usual with 16-bit games, not all points are tested on every frame. What is interesting is that rather than testing e.g. "left side" when moving left, the game tests "left side" only if the left side is "smaller" than the right side, as a way to detect "new" things, assuming that what covers most of Mario's box has been tested in the past. "When Mario is on the right side of a tile, the two points on the left are ignored" is possibly a better way to describe what happens, indeed ^^".

I'd be curious to find out to what extent that keeps working where your level grid isn't exactly one hero wide ...

Tuesday, July 08, 2025

blogpress 0.3

Combinez les scripts de traitement "blogpress" (blogger-vers-epub) et le service d'impression utilisé par Rodrigo Copetti et vous aurez le "side-project" qui me distrait actuellement... Alimenté en plus par une page de recherche sur l'utilisation de XPath pour "travailler plus proprement" ... Sauf que XPath, pour traiter une requête sur le blog, il met 8 secondes. Mes expressions régulières, 1/8ème de seconde.

Ça fait un peu suite à des travaux de septembre dernier pour essayer de voir ce que les "takeout" de photos google ont vraiment dans le ventre, et l'idée serait de "rassembler tout ce qui peut parler de Qui est Bilou, plutôt en Français à destination de la génération suivante.

I have PERL scripts to process the XML data exported from this blog and fetch pictures to get something that could be printed or converted into epub. So far, it had a drawback: if you got an updated version of the xml (i.e. a later backup), all implied filenames for the pictures would change and almost everything would have to be re-downloaded. A shame in a context where some pictures may get lost.

So I opened them again and started replacing "line number" by "uuid generated by blogger", which gives them stable filenames. A curious idea, when you know I was almost stunned by fatigue. I guess I was just too tired to resist the idea of working on a printable book around the idea of "who is Bilou?" that could be printed like the work of Rodrigo Copetti.

Things haven't been all fine, though. One annoyance was those "new" (vs. 2019) 72x72 pixels thumbs that broke some assumptions I made about multiple URLs pointing to the same file in the same post... Then I've tried to use symlinks to refer to contents previously downloaded, but accidentally forgot to tell the "get-pictures" script that it should skip symlinks when they're around, so it tried to overwrite those pictures I already had and I had to plug my backup HDD and enter data recovery mode ... (I mentioned I was tired, right ?)

Plus tôt dans le mois, j'avais passé en revue tous les posts avec le tag "Bilou", donc, pour en retenir à peu près la moitié. 16 Mo de fichier XML, 106 posts retenus (plus les drafts ^^ ) ... des soucis avec les miniatures 72x72 qui essaient de se faire passer pour les images "grand format" ... des soucis avec les fichiers 1600-h qui font semblant d'être des images mais sont en réalité des pages HTML présentant l'image ... des soucis avec les fichiers tirés de screenshots dans firefox qui à force de conversions / -> %2f finissent par produire des noms de fichiers trop long ... les joyeusetés du scripting quoi. Mais au final, j'ai pu avoir un fichier HTML d'à peu près 1Mo référençant la majorité des images voulues convertible en 115 pages de pdf mal fichu (entendez, avec tout de même des images tronquées ou coupées sur deux pages ^^") qui m'a donné envie de voir malgré l'heure avancée "ce que ça donnerait avec la sélection définitive"

Je me prépare donc à télécharger blog-05-07-2025.xml mais à la place ... me voilà débarqué dans le portail "takeout" de google ...  

By late Saturday, I had collected everything again and was ready to apply the scripts on the latest .xml file, the one where I'd have processed all posts with #bilou and assigned some of them to #firstDemo (because they really weren't quite about Bilou himself, but about trees, applemen, scripting ... or something totally unrelated but featuring a small illustration from the 2001 comics). Only to realize that Google has now decided that Blogger export should be managed by the Google Takeout portal. That means waiting for several hours (up to 2 days, but hopefully not in my case), checking boxes and finally receiving a link to a 2GB archive containing .... (drumroll) ... the whole set of pictures uploaded to the blog.

Il me faut donc patienter plusieurs heures pour avoir le nouveau .xml qui est entre-temps devenu un .atom, a laissé tomber certaines informations, regroupé d'autres autrement et est maintenant accompagné ... de l'ensemble (?) des images du blog. Je m'autorise un point d'interrogation, parce que si j'ai finalement pu produire le bilou.html.pdf que je voulais, j'ai quand-même conservé le listing URL->fichiers construit avec blog-28-06-2025.xml et pas avec le nouveau feed.atom ...

Tout ça pour passer le témoin aux p'tits jeunes ? Bah, quand j'ai montré pour la 2eme fois à J.L.N les feuilles qui étaient malgré tout sorties de l'imprimante, il n'y a pour ainsi dire pas regardé et m'a demandé si j'avais fait des progrès avec les cascades, le bug de Bilou-ballerine et tout ça  ^^"

Monday, June 30, 2025

Dangerous, not evil

If you could read the very early design documents of Bilou's Adventure, you'd note a mad scientist (somehow mix of Dr. Eggman and Dr. Gero). All the bosses are experiment he conducted and likely all the baddies are after you because of him. He was actually imported from sketches of "Calimero". He didn't last long.

Au début du design de Bilou, en '93, le joueur était face à un savant fou (importé de Caliméro), une sorte de mélange entre le Dr. Gero de Dragonball et le Dr. Robotnik de Sonic qu'il lui faudrait affronter dans le combat final, et tous les monstres qu'on allait affronter étaient de son fait ou dans son camp. 

Later on, when working on the "ultimate game maker" idea, I tried to introduce an invading species like the Kremlins in DKC or the Koopas in SMB, that would justify the quest, but that didn't last long either (actually, I couldn't come with anything interesting enough to give it a variant for every zone Bilou travels).

Plus tard, en '98, en parallèle aux recherches techniques sur l'Ultimate Game Maker, j'ai essayé d'ajouter une espèce invasive -- l'équivalent des Koopas ou des Kremlins des jeux Nintendo -- mais rien ne marchait vraiment. Entre autre à cause de l'aspect hétéroclyte du monde de Bilou qui n'a pas grand chose en commun avec le Royaume Champignon. Puis alors que la BD de Bilou prenait petit à petit corps, pas mal de personnages qui étaient au début des monstres se sont retrouvés à jouer un rôle nettement moins "noir ou blanc". Le champignon fou se met a avoir un idéal dans la vie (parvenir à voler) et des mouvements d'humeur.

On retrouve quelque-chose du même tonneau avec la gomme qui charge le crayon (qui l'a réveillé en sursaut), mais qui discute tranquillement devant un gogo susceptible de lui construire un pont. Avec les esquisses de la rencontre avec Bangbash, c'est devenu un mécanisme narratif assumé: il y a des personnages dangereux, au même titre qu'un taureau ou un sanglier sont (plus ou moins) dangereux, mais il n'y a pas de méchants (ou très peu: ce seront les pendats de School Rush, par exemple). Et voici une petite gribouille de 2009 qui reprend cette idée pour la première fois à plat.

Then came the comic, and with the comic, many of the baddies stopped being "evil". The bopping mushroom (now known as Funky Funghi) may occasionally become excessively angry, but he also asks Bilou how he manages to fly and whether he could teach him to fly as well. The RectoVerso eraser is aggressive against the crayon who woke him up, but can just stay there and chat when it seems that he could trick Bilou and Bouli. 

And the picture you have above puts it into words for the first time: they are *dangerous* (like a bull), not evil. Very few of them attack you just because you're a non-them, but you should rather not mess with them either because you could quite easily got hurt. With a few exceptions (like the pendats), what you're facing is *not* an army.

Le truc s'invite même rétrospectivement dans School Rush avec un "évidemment que les gommes sont énervées: l'encre monte", soutenu par un graphisme de gomme qui dort une fois qu'on a rebouché la fuite, ou l'idée pour Dreamland que les applemen soient passifs tant qu'on a pas ramassé de mini-pomme. On justifie l'aggressivité des applemen de Apple Assault par le fait que le vaisseau de Bilou et Bouli vient de s'écraser dans la forêt, saccageant leur habitat naturel (désolé, les compotes ^^")

Friday, June 27, 2025

Tomba/ponkadunk pixelstudy

"Tomba!" by Ponkadunk, published in 2019 on pixeljoint and dug by PixelProspector. A pixel art mockup of what could have been the PSX game "Tomba" if developers had not opted for polygonal textured levels instead. It's been teasing me to pixel-study it for years now, so let's give it a try. About everything in this scene is a mastery: the characters, the pick-ups, the ground ... but if you don't mind, this time I'll focus on the background and maybe the rocky ground as these are the parts in my green zone that could use some more work.


I always interpreted the background as "leaves in jungle", but if you actually go beyond the fact that it's all green, you quickly note that these are bunch of leaves here and there over a rocks background. By playing with the palette, I could spot that the greens for the rocks and the greens for the leaves are actually two distinct ramps, only sharing their darkest parts.

The rocks ramp goes from h120s66v30 to h118s79v15, with hue shifts towards h107 on the 2nd lightest shade and h123 on the second darkest. The leaves ramp goes from h93s84v33 to h103s76v20. (oh, I used a "hsv hue" layer in Gimp to tint the "rocks ramp" towards yellow so we can distinguish it better from the "leaves" ramp.

Note in the middle of the snippet that we have blade-like shapes with the rocks ramp, so likely darker leaves more than odd-shaped rocks. A reminder to not let the initial purpose of colours dictate you how you use colours when doing pixel art... not until you really have to ;)

The common darkest shade at h123s71v11 unifies the things together in a single shadow. While some elements are fully detailed over that background, other blend in and only reveal their contour with some of the darkest shades of the ramp.

The tiling of the pattern is huge -- some 164 pixels wide, which does not correspond to any hardware-friendly size, and this is no issue for a mockup.

Compared to Eagle Island or Sonic Mania background, this one has the advantage that it could fit fairly well the colour count and the memory of the "farground" in my engine.
 

Saturday, June 21, 2025

Les portes ... prochain vrai objectif

C'est ce qu'on pouvait lire en mars sur une de mes pages d'agenda et en avril sur mastodon. Et c'est toujours d'actualité, bien que j'envisage de faire d'abord un essai des éléments de base de leur implémentation sur un le bonus qui rend des points de vie ... Si vous avez un peu essayé la dernière démo, vous avez sans doute été surpris par un brusque changement de niveau dès que vous vous approchez un peu trop d'un truc en forme d'ouverture. C'est clairement quelque-chose que je voudrais améliorer.

La bonne nouvelle, c'est qu'en fait, j'ai déjà la moitié du travail: enregistrer la position actuelle dans des variables. Et voici la deuxième partie: se diriger vers les coordonnées enregistrées.

Bilou's Adventure maps have doors... you know, the kind that are located at some point on the map and will near-instant put you somewhere else on the map. So I'd like "Bilou Dreamland" to have doors as well... That will require a bit more effort in the GEDS environment that can't simply do ROOM=12 : xbilou=100 : ybilou=100. So i've got this nice tree stump sketch in my agenda since at least March'25, and I've been twisting my mind around the issue of how to make it work with state machines and collisions and linked game objects.

Now, my Basic games typically struggled to extend beyond one level. At best, I'd chain-load the next level which would happen to look a lot like the previous one (or not) by sharing lot of code thanks to copy-pasta... And entering a door would typically freeze everything as the game had entered a dedicated micro-script that ignored everything but entering the door. 

L'idée générale, c'est donc d'avoir deux "personnages" pour une porte, l'un représentant le point d'entrée et l'autre le point de sortie. Le mécanisme d'attache qui permet à Spongebop de rester pendue à son clou peut aussi servir pour lier les portes. Bilou, lui, se liera à la porte "entrée", et la suit de la même façon que dumblador suit Bilou quand il le transporte.

The overall idea is to have two game objects involved in a door-to-door transit: one being the incoming door, and the other being the target location. There will be a one-way link between them in the level script. As part of the 'entering' trigger, Bilou would attach to the input door, which is itself attached to a target GOB. Using that to transport Bilou to the destination should work quite nicely: it's been years that tracking the attached object works nicely. The question is "how do I send back the door once Bilou has left?"

I cannot just "track an object left at the original position", because so far, the engine only track *one* object at a time. But I could record the position before leaving, and -- with the help of a new controller -- track that position. In fact, I already have such "record position" behaviour as part of the "grid" controller used by bouncy branch and furblock.

Coding directly such a multi-step mechanics didn't sound a wise move to me, but I had an animation for the health power-up that made it circle around ... and a notebook entry suggesting to do that with lines of code rather than lines of pixels. I'll save the introduction of an invisible permanent object to circle around if I inject "reccoords" and "track(recorded)" in that health pick-up ... which has just been completed today. 

Voilà donc un premier pas franchi: ce petit point bleu volant a enregistré sa position d'origine comme l'aurait fait une porte et est en train de se servir du nouveau contrôleur pour s'orienter et graviter autour. 

Bon, et se faire transporter ne sera pas tout: je voudrais aussi qu'on ait l'impression que Bilou *rentre* dans la porte avant le transport. Quelque-chose de plus convaincant que le simple décalage vers le noir de la version BASIC où appuyer sur "haut" un peu trop à gauche ou à droite nous enverrait à travers le chambranle, la main devenue noire de Bilou ressemblant à un trou de trop dans le mur :P  

And I must admit I injected significant time in thinking how Bilou would *enter* the door. I know it isn't required to see him walk into the door like Bubsy did, and likely the spin at the start isn't strictly required either, but I intend to use it as the excuse to align Bilou with the door such that I can later fade him to black without having a Bilou-shaped hole dug into the wall (QBilou.bas did that ^^) nor require pixel-precise location to activate the door (Super Princess Peach did that >_<)

Friday, June 20, 2025

opacity under my middle finger

Pendant longtemps, je suis resté fidèle à la version 16 d'Enlightenment -- le gestionnaire de fenêtres pour Linux. e17 son successeur remplaçait un peu trop de choses à mon goût, et notamment tout mon setup de doctorant basé sur FancyLauncher tombait à l'eau...

Puis les gestionnaires de distribution linux ne m'ont plus vraiment laissé le choix ... et là on en est à Enlightenment 25.3 (bionew) ... et voici que je découvre 

  1. qu'on peut customiser ce qui se passe quand on utilise ALT+roulette
  2. qu'on peut mettre un comportement différent selon qu'on survole le bureau, une fenêtre, ... 
  3. qu'on peut en profiter pour changer l'opacité d'une fenêtre

Alors soyons clairs: les terminaux ou fenêtres transparents, de manière générale, ça m'est inutile: j'ai trop de fenêtre pour que ça serve à quoi que ce soit. Mais les terminaux qui permettent de quand-même voir mon fond d'écran par derrière, ça ça me botte. Par contre, un truc que je faisais souvent sous e16, c'était profiter d'un des mode de déplacements de fenêtre pour superposer deux chaînes cryptographiques, histoire de vérifier rapidement qu'elles étaient identique. Effectivement, au moment de déplacer une fenêtre "en mode transparence", e16 trichait et faisait une capture d'écran de votre bureau qu'il allait garder comme image #1 tandis qu'une capture de la fenêtre à déplacer se baladait comme image #2 avec alpha-blending de démoscèneur.

0.23.1 sur ma "machine à écrire" ... Lui peut toujours être redémarré d'un "kill -11" là où la version de debian va tenter de se blinder mais du coup peut devenir incontrôlable en cas de bug interne, ce qui m'a déjà coûté ma session de dsdev un peu trop souvent.

Il y a aussi ce comportement bizarre avec mon pointeur souris qui fait passe en distortion 3 quand je veux ouvrir un menu dans ddd ... et le fait que la zone d'influence de firefox déborde d'une 15aine de pixels sur la droite de sa fenêtre ... (edit: 0.24.2 me montre dans ce cas un curseur spécial "étendre la fenêtre horizontalement, mais revient à un "simple curseur" pendant encore 8-16 bons pixels avant de me montrer le curseur texte que j'attendais et me laisser taper dans la fenêtre cachée :-/)

Me voici donc au final avec la 0.24.2 (recompilé depuis les sources dans /usr/local/*, ajouté à la main dans un /usr/share/xsessions/e23.desktop -- personne n'est parfait ^^") qui me fait une bannière "guru meditation" quand je lui envoie un SIGSEGV, qui réagit gentillement à enligthenment_remote -restart mais qui a malheureusement remis à zéro tous mes réglages T_T ...

edit: avec un petit réglage de plus, j'ai aussi récupéré le "suspendre si je ferme l'écran": il suffisait juste de passer de "suspend intelligently" à "suspend". (J'imagine que "intelligently" évite la mise en veille si je suis en mode 'présentation', mais ça ne me tente pas pour ce PC)

Friday, June 06, 2025

MainFrames by Assoupi

Il y a longtemps, sur pixelation, un artiste nous a posté une animation d'un écran d'accueil d'un micro 8-bit, sauf que après avoir clignoté quelques fois, le curseur s'ouvrait et laissait sortir un petit personnage qui se baladait parmi les lignes de texte comme si c'étaient des plate-formes...

Alors vous pensez bien que depuis, trouver une manière de mettre en scène un curseur (pointu ou en forme de main) ou une petite diskette, ça s'en va et ça revient dans ma tête au fil des années. Alors quand je tombe sur la vidéo de lancement du jeu MainFrames, j'ouvre des yeux comme des billes façon "The Mask" ... 

Since that day where somebody on pixelation made an animation with a small character getting out of the "READY" blinking square of an 8-bit welcome screen, I've been toying with the idea of making a cursor-like / handcursor-like / floppy-like character. And there comes MainFrame, a game where you play a little floppy within the GUI of a multi-computer system, just as if it was a personnal gift to me.

Un p'tit personnage tout sympa, animé avec un brio plutôt rare, dans un monde qui rappelle l'esthétique des premiers systèmes Unix à Montefiore ... Des clins d'oeil au monde de la programmation, une véritable appropriation de la terminologie un peu bizarre de ces systèmes ... et un guide en forme de gros pingouin qui vient vous rappeler de faire marcher un peu vos neurones quand le jeu détecte que vous "calez" sur une difficulté. Ajoutez-y une bande son 9-bit sans faux pas, et vous avez là un titre à ne pas manquer.

Every artistic aspect of the game is wonderfully implemented. Visuals, animation, soundtrack. Plus you get winky references to programming and system operation every here and there, giving life to the most surprising terminology of computer science, like those "daemons" operating contraptions and wandering around or the huge penguin (officially the interactive manual of the system) that will give you hints when you're stuck in a specific screen.  

Voilà donc: c'est un jeu développé en France, et on ne va pas se mentir: c'est à peu près autant un die-and-retry que Meat Boy, mais dans un univers où le sang n'est pas nécessaire. C'était dur, mais j'ai adoré tous les petites référence et l'histoire de l'équipe en trame de fond, racontée à travers les fond d'écrans et les "emails" échangés.

C'était dur, et pourtant j'ai été surpris par la qualité de la maniabilité. Voyez cet écran: à un moment, il va falloir escalader par wall-jump les parois verticales puis atterrir sur la tranche de ces barres. Oui, sur une surface deux fois plus étroites que votre personnage. Eh bien on y arrive! et sans trop de difficulté, encore bien -- en tout cas comparé aux essais-erreurs qu'Ori and the Blind Forest nous imposait dans ce genre de situation :P

La clé pour rendre ça plus fiable, c'est un système d'auto-contournement d'obstacle assez poussé qui fait que si vous arrivez un peu court sur un saut (la plate-forme dans les dents), votre perso escalade automatiquement cette dernière pour atterrir dessus. 

Gameplay-wise, MainFrames remembered me of Super Meat Boy, without the uncanny blood. I tried numerous times, I failed a little less, I managed to chain improbable timed jumps and flips (not quite a double jump, but still significantly enhance how far you go) to challenges that seemed impossible at first and occasionally skipped 2 final rooms using the accessibility features because, hey, the goal is to have fun, not to get mad.

I've been assisted by the "workaround" mechanics of the JUMP move, that will make you auto-climb on corners when you bump into one, meaning that climbing and standing on those vertical black bars is actually comfortable (unlike in Ori and Whipseey). And I've been rewarded by improbable but memorable places like this coffee machine that would have been a perfect heal spot if the game had hitpoints.  

Il reste une dernière mécanique de jeu que je n'ai pas encore abordé: le déplacement de fenêtres. C'est un thème qu'on a retrouvé pas mal dans des petits jeux flash ou dans des titres de game jam ces dernières années: puisque le jeu se déroule sur un écran d'ordinateur (littéralement), on va pouvoir déplacer, agrandir, rétrécir, etc. certaines plate-formes comme on déplacerait/... des fenêtres à l'écran. ça se fait ici au 2eme stick pendant qu'on contrôle son personnage au premier stick mais surtout, c'est merveilleusement bien intégré. Aucun risque d'en venir à "bah, pourquoi sauter: je vais juste bouger la fenêtre" parce que les autres objets à l'écran vont contraindre les déplacements possibles. Et parce que c'est le niveau actuel, pas vous, qui dicte quelles fenêtres peuvent jouer un rôle et lequel. Et parfois, c'est en marchant vers la droite que la fenêtre s'étire, etc.

One last interesting gimmick that the game brilliantly executed, is that of "moving level parts as if they were things in a GUI". We've seen that in Flash games and jam entries before, but for the first time (afaik) it is integrated into a full-sized quest without breaking the core mechanics (jump) and finding the perfect balance between the move-stuff puzzle times and time-your-jumps skill times. Part of why it works lies in the fact that we've given restricted control, on a room-by-room basis. At one place, you can freely move one window (as long as it doesn't bump into something else), at another place, you can shrink some, sometimes you must use triggers to switch between which one to manipulate as you hop from title bar to title bar and sometimes you use GUI powers to guide another daemon to its escape pod lift. Refreshing.

Un tout grand merci et un bravo à l'équipe de développement d'Assoupi.