Thursday, April 18, 2024

32-bit

Bion, jusqu'ici mon laptop tient bon, mais il a un truc un peu spécial qu'il vaut mieux que je documente pour mon moi-du-futur: il continue de faire tourner certains programmes en 32-bit alors que c'est un ubuntu 64-bit. Lors de mes premiers pas dans l'espace d'adressage gigantesque d'AMéDée64, le double support 32/64, c'était la règle, mais ça fait quelques années déjà qu'on y est plus.

Or, mon environnement de tests automatiques pour libgeds s'efforce de faire croire au code qu'il est sur une DS en ajoutant de la mémoire valide ici où là pour que les écritures dans les registres n'échouent pas. Ruse qui ne marche qu'avec un système 32-bit pour une raison qu'il faudra que je demande à mon moi-du-passé de me documenter.

En plus de ça, l'outil que j'utilise pour éditer les musiques du jeu (SchismTracker) a laissé tomber le support des fichiers .XM pour ne plus produire que des .IT ... alors que je m'en sers essentiellement pour convertir les .IT du frangin en .XMs :P ... Je promène donc avec moi un répertoire de binaires 32-bits lui permettant de continuer de tourner mais il faut pour celà que l'OS lui-même ait quand-même quelques outils et configurations sous la main pour exécuter du 32 bits. Faute de quoi, le shell persistera à nous dire

-bash: /home/grizzly/bin32/schismTracker: no such file or directory

alors qu'il est bel et bien là (ouais, pas terrible, les codes d'erreur pour le coup).

Comme linaro vient de me faire le coup, je profite que je suis pas à pas un petit howto sur stackoverflow pour me laisser un topo de voyageur temporel...


sudo dpkg --add-architecture i386 # there is more than x86_64, you know
sudo apt-get update
# accidentally did an apt-get upgrade...
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
# that was enough for me.
# sudo apt-get install multiarch-support # might be needed otherwise...
sudo apt-get install libz1g:i386 # was needed later on for linaro building newlib


Wednesday, April 03, 2024

Chalk 2.0

In the first release of Bilou's Adventure solo anniversary level, I had to use a caption on the blog post so that players would know they need to break one "barrier" to keep going.

Later revision replaced it with a chalk, that can break if you fall from high enough. But that wasn't properly explained to player either.

  • I have sketches of training rooms to teach players chalk can be broken
  • Original level design had key-and-lock there, and one of the design decision for Bilou's Dreamland is "it is okay to rely on keys and locks"
  • What if a simple jump was pushing the chalk down by 1 pixel ? (in addition to everything else you can already do with it)

Bon, ça ne devrait pas être une surprise: Bilou's Dreamland reprendra le niveau-anniversaire pour la school zone. Il a l'avantage supplémentaire que pas mal de mécaniques de jeu qu'on y trouve ont déjà passé l'épreuve du playtesting, même si ce n'était clairement pas parfait. Un des éléments qui a le plus causé de soucis aux joueurs, c'est cette craie-qui-casse que Piek jugeait zelda-esque. C'était pourtant une amélioration notable par rapport à ce qu'il y avait dans la première version nds du niveau, où il fallait lire le blog pour savoir que ce crayon-là peut casser, contrairement aux autres...

It might not be bad that you could push down the chalk-gate without ever making a bigger jump, mostly because those eraser monsters will put you under pressure while you're trying to do that. It wouldn't be a big deal either if you could lower it by e.g. 8 pixels with regular jumps, but that it then lift up by 1 pixel every time you jump from it, making the next jumps useless. But at least you've seen it is interactive.

The 'tutorial' option is to introduce the chalk gate first in a setup where the player is guided into thinking that it is a 'jump-through' platform, but reveal that it actually breaks when Bilou knocks it from below.

Alors ces derniers mois, j'ai rajouté quelques croquis dans mon cahier-design que je vous renumérise ici (panne de scanner) qui étaient sous-titrés "où on apprend que la craie, ça casse". Histoire que le joueur ait déjà des informations à propos de ce type de bloc quand il va devoir réfléchir à son sujet. Je sais: j'avais donné comme ligne de conduite pour Dreamland "on s'autorise des portes-qui-téléportent, des clés, des serrures et des interrupteurs", et dans le design d'origine, c'est un simple interrupteur qu'on utilise. Mais on est tellement proche d'un mécanisme intégré dans le monde du jeu que ce serait dommage de ne pas vérifier que c'est jouable...

And once you know they are breakable, it is much easier to create a setup where you learn that they can also be broken if you fall on them with sufficient speed. Especially if I add some screen shaking when you hit plain ground with that speed... and ask my brother to give me a dedicated sound effect for that.

Sinon, une dernière option serait que chaque saut sur la craie la fasse descendre d'un pixel si la vitesse de collision est insuffisante. De quoi confirmer au joueur que oui, c'est pas interactif et que oui, c'est en tombant que ça va marcher, mais là, ce n'est pas encore assez. Elle n'exclut pas les écrans préliminaires, cela dit... Avec un peu d'écran-qui-tremble quand Bilou arrive sur le sol avec une vitesse suffisante pour casser des choses, ça pourrait faire un combo gagnant.

Being so close to actual organic gate mechanics, I feel like it would be a pity to come back with a plain old key opening a plain old lock.

Tuesday, April 02, 2024

Show and Birthday

It's been 10 years I've swapped jobs. It's been 10 years and yet most of my colleagues had never seen my little DS games. Working as a software developer makes it a bit harder to show hobby software to colleagues. Few of them know this blog, and those who do do mostly because of their intervention on the cxx or rongtudju categories. Most know I'm drawing things because I had some of my drawings displayed on the wall before we move to the new building.

And then a new batch of colleague joined, including one who's been doing a Flappy Bird clone on FPGA for a school assignment. They are the same generation as my S-team beta-testers, so I decided to pick my DS along at one social event, showed it to the young team... not much more than AnimEditor, but they were quite smiley about it. I did not have any ready-to-run playable demo on the device, though, and the cheese pot came in ...

That was a few months ago. Two weeks ago, I was visiting Ged's place. I clearly couldn't get there without my latest demo in my pocket. Well, not quite that version. The 'ongoing work' one, with a different tune for every world, but still needing fixes every here and there. He did enjoy it, though, and his 8-year-old son did enjoy some not-too-old version of SchoolRush. I've been told that it is a shame we can no longer catch the highest apples on the green zone, though.

Then there was my birthday, alone until 13:00 where Cyril came and play some Donkey Kong Tropical Freeze ... and check the latest progress on Bilou. And I knew I'd bring some "cookies" at the office the day after. I typically prefer to make it so people can come and meet me at the coffee machine rather than just drop the stuff and disappear... So I decided it was about time to show them Bilou as well. 

Most of my team were pleased to give a look at the game, a few of them played either 3-Rooms (.nds) or School Rush, and among those who did, none found it obvious that GRAB is GRAB instead of PUNCH. I might want to do something about that before I make a release of DreamLand... A few colleague actually tried to beat level 1 of School Rush and one even managed to reach level 2.

In other teams, there were of course some colleagues to find it odd that I do that with a Nintendo DS rather than going for Androïd or Nintendo Switch. The recent court face-off between Big N and the team behind 3DS and Switch emulators doesn't really speak in favour of retro-homebrew approach ...

Final round was yesterday with my even-younger-nephews who wanted to try 3-Rooms after I shown it to my brother for music selection approval. Last but not least, that triggered a question from the 15-y-o Tango nephew who was curious to know where he could download the tools I used to build the demo and asked whether programming was required to create new characters.

Sunday, March 10, 2024

Gob3D

There are some items in the school zone that would better be done with 3D objects. This is not quite new, but if I intend to have them in Dreamlands, likely it is time to consider them more seriously. At least, to identify the questions to be addressed.

  • How do we define hitboxes for a rotating 3D object ?
  • How do we define events that trigger when a given angle is reached ? (e.g. for state machine transition)

Je me suis laissé quelques petites notes pour quand il sera temps d'essayer de faire des objets 3D un peu plus ambitieux que les élastiques de SpongeBop pour Dreamland. Notamment des livres qui tombent et des lattes qui tournent ... Chacun d'eux ouvrant la porte à au moins tout un niveau dans mon carnet bleu.

Il faudra que je trouve le bon moyen de lier des zones de collisions aux objets 3D, pour commencer. Puis il faudra que je vérifie que j'ai bien compris comment marchaient les "display lists" pour la NDS ... Et accessoirement, faire une petite estimation du nombre "d'écrans" que compterait la school zone de DreamLands avec et sans les objets 3D, vu que pour la green zone, je suis déjà bon avec 2 niveaux ancestraux :-P

For the objects being considered here, it might be enough if rotations always happen around the origin of the model. A smashing book always rotates around its bottom line (X position irrelevant). A bridge book, around the middle of its bottom line (Z position irrelevant). A ruler bridge around its center of mass (Y position of the origin irrelevant). Sure, this does not capture all the possible things you might want to do with a 3D object in a 2D game, but it seems to be a sufficient start to me.

Now, last time I toyed with the idea of doing more than ropes in 3D, I ended up with the issue that anything that isn't hard-coded would have to use "glCallList", but I couldn't figure out how that would work. At last, I studied the registers used to control the 3D geometry engine (which turn out to match the gl* function almost 1:1) and noted that there are "command identifiers" associated with every 3D register. A call list is essentially a set of values to be written to GFX_FIFO. Writing to GFX_BEGIN (in order to implement glBegin) would be replaced by writing the command identifier for "begin vertex list", etc.

I could use a tool to craft these and adjust their parameters so that things look properly shaped.

edit: avec le "niveau de Rémi" et le niveau-anniversaire, je suis déjà à 36 écrans (contre 30 pour le 2eme monde de Kirby's Dreamland). Il y a au mieux 6 écrans à prendre dans le niveau avec tous les livres qui tombent et 2 à 3 fois autant à aller chercher dans les niveaux sans ces livres (mais avec quand-même quelque chose comme des lattes qui tournent et des bookmarks qui pendent). Je dirais que le plus raisonnable, c'est de garder les livres-3D pour un autre jeu.

Wednesday, March 06, 2024

Reprendre les vieilles maps ?

Surprise quand j'avais fait le tour de mon cahier "level design", je n'ai en fait que 2 niveaux et demi candidats pour la Green Zone. Alors que le jeu en BASIC donne l'impression qu'il en comptait 5. Mais certains niveaux (dont celui baptisé "les grands arbres") ont vraiment mal vieilli.

Alors pourquoi ne pas inviter à la fête les maps de la démo 9/9/9 ? Elles auraient besoin d'un peu de vernis, mais elles pourraient faire l'office d'écran pour apprivoiser les mécaniques du jeu avant d'être lancé dans l'historique niveau 1 de la forêt ... 

The goal for the Green Zone of Bilou's Dreamland should be around 26 screens (that's Kirby's Dreamland world 1 size). I have only 2 levels of Bilou's Adventure that seem mature enough to be included ... A bit light if you ask me. But I do have 2 small levels drawn for the earliest GEDS demo back in 2009 that might be welcome, either in the 'dreamland' game, or in the 3-rooms demo.

They might feature a bit too much of Funky Funghi, but some of them are in interesting settings, like in that 2nd level with chunks of dirt here and there that are only waiting for bridges to be tested... So I went for a poll, and 3/4 responders picked "go for inclusion" while the last person would prefer those maps to be exclusive to the 3-rooms demo.

Et le 2eme niveau de la démo, avec ses petites plate-formes et ses funghi partout serait le terrain rêvé pour introduire les ponts et jouer un peu avec. Et si la question n'a pas suscité de débat remarquable sur twitter/mastodon, il y a au moins unanimité sur le fait que les faire intervenir au moins comme terrain d'exploration supplémentaire depuis la démo "three rooms" est une bonne idée.

  • [done] import cube:/home/grizzly/pype/codinDS/dsgametools/schem.map 
  • [done] import cube:/home/pype/hobby/R4-bakcup/GREENY.MAP
  • [done] import cube:/home/pype/hobby/R4-bakcup/GREEN2.MAP
  • [done] see what they look like
  • [todo] bring them back on NDS so they could be fixed with up-to-date tileset.

Saturday, March 02, 2024

Let's have more musics!

If you have tried the last demo, you most certainly noted that there are only 2 soundtracks for 3 rooms. And moreover, that there is a different set of sound effects depending on the room you're in. This is a drawback of the current sound engine, where everything is in one data file: main in-game tune, side tunes for menu and such, single-pattern for level clear, mini-patterns for 1-UPs and notable pick-ups, samples to play them all and samples to be used as standalone sound effects.

Bon, un des gros morceaux de programmation qu'il me reste à faire sur le moteur de jeu, c'est de faire en sorte qu'on puisse plus librement passer d'une musique à l'autre. Pas charger une autre musique en changeant de monde, ça c'est déjà fait. Non. Je veux dire décider que "string tracking" n'est pas la musique idéale pour la green zone et que "4U2" donnera mieux. Ou "little flower on the grass". Pour l'instant, ça pose un soucis parce que les fichiers musique contiennent aussi la palette sonore pour les différents personnages. Je voudrais donc pouvoir faire avec les samples et autres patterns ce que j'ai fait avec les images : charger un deuxième jeu de sons par-dessus la musique destinée au monde. ça fait un moment que ça me trotte en tête.

Et cette semaine, j'ai pu passer un premier cap: importer les samples. ça a l'air de marcher, mais ne nous leurrons pas: vu le type de programmation auquel on a affaire, il faudra rajouter quelques tests automatiques sous scruteur de mémoire pour garantir qu'on n'a pas ajouté une bombe à retardement dans le jeu. Et il y aura une repasse pour mettre ça au net avec des classes une fois que j'aurai validé le concept, parce que pour l'instant, ça part dans tous les sens, aucune des classes du moteur de jeu n'ayant été prévues pour ça.

So among the objectives I sketched in my 2024 notebook, there was some ideas to overlay .xm files the way I overlay .spr files... Or rather the other way'round. Here the generic "bilou.xm" containing mostly sound effects would see its samples and patterns imported over the world-specific song.

#ndsdev status last night: I could allow 2 instances of NTXM::Song to exist together.
#ndsdev status tonight: I can import instruments from one NTXM::Song so that different environment can share some sound effects.
little step for #gamedev, giant leap for game #MadeWithMyEngine.

I admit it might sound weird to add the common part over the world-custom part. After all video does the opposite. The reason here is that odds of adding common sounds over the course of the development feels higher than odds of adding new samples to an existing song. It shouldn't be too hard to tell my brother that patterns 50-60 should be kept free for sound effects, same for samples 50+, no matter what song we're using than to remap all samples of the per-world-songs to other slots because we've got one extra ooch-that-is-electric sample added in the shared bilou.xm

But yeah, I still make sure that bilou.xm is only loaded once, when the game initializes, and we don't pay extra wait time for overlaying it from the SD card. Instead, samples and patterns from the shared song got "borrowed" from the shared song and marked as such so that they aren't freed when we swap songs. Did I mention I read a bit about RUST programming language earlier this week ;) ?

edit: now also imports mini-pattern ^_^

edit: tried new songs ... some things worked, but some things look broken

edit: ow. turns out when you encounter pattern break on a mini-pattern, only the channel with the break command is discarded ^^". Seems like it was only a matter of luck that SchoolRush did work fine, and possibly explain why playing / leaving it idle long enough started producing super-fast trash sounds. Now, you'd have hard time dumping the ROM with that ... not as "easy" as with a runaway audio channel on a GBA.

edit: fixed

Wednesday, February 21, 2024

Demo: Scorpeye, Apple, Water and Sand

A new demo appeared. At last, my checklist is complete (and sure, there are still many more things to write for a next list). The demo is still based on the "three rooms". Don't expect much more land to explore. I still have a few concepts to prove before I can do that.

Enfin direz vous, et je ne vous contredirai pas. Voici la nouvelle démo de mes travaux en cours sur Bilou's Dreamland. Toujours limitée à 3 salles à peine de 2x2 écrans qui servent pour expérimenter les nouvelles mécaniques sans passer trop de temps à courir jusqu'à la nouvelle fonction à tester. Mais pour la première fois, vous allez pouvoir nager, affronter les sables mouvants, lancer des carapaces. Et puis il y a toujours le rodéo d'éponge et le saut en encrier. Allez, quoi. Sortez votre linker et faites-vous plaisir :)

Compared to the previous demo, you can try

  • the new appleman animations
  • the collapsing platform (pyramid)
  • the scorpeye shell (jump on the scorpeye, then grab it like you'd do with a blador)
  • flowing sand, pushing you down the slopes
  • improved swim mechanics, waterflow
tested on NDS Lite, desmume 0.9.11 and desmume 0.9.6

Feel like playing a real game ? Try my previous titles ;)

Tuesday, February 20, 2024

Tools update


It'd be fun to try your editors! I'd probably do any serious development on a computer, but it's still cool to have an opportunity to try something I would've loved to have as a kid.

(Nova Storm, 7 February 2024)

I told you about Nova's work on NES and SNES already. Earlier this year, she shown interest into NDS homebrew and linkers, so I proposed her to try the dsgametools, and she replied with the heartwarming sentence above. My last tools release dates back from 2021, and while there are not that many things that have changed since, some annoying bugs were fixed nonetheless. So I went for a new package with some README, example files and PERL tools in addition to the .nds files proper. 

Salut les neveux. Si vous voulez tenter de faire des jeux sur Nintendo DS avec mes outils, vous êtes arrivés sur la bonne page. Téléchargez le .zip en utilisant l'image-lien ci-dessus et copiez les fichiers *dlta.nds à la racine de la carte-mémoire de votre DS. Tant que vous y êtes, vous pouvez aussi créer un répertoire nommé "moving" à la racine de la carte mémoire et déposer les fichiers présents dans Demo/efsroot/ du zip. On fait bien attention à ne rien effacer, on éjecte en toute sécurité, on remet tout en place dans la DS et voilà.

Level Editor

  • fixing bugs with meta buttons;
  • add support for special tiles used in conveyer belts and flowing water
  • cosmetics: buttons with shadow and show when they are pushed

AnimEditor

  • fixing 'apply to all previous frames' and 'apply to all future frames' buttons.
  • only store thumbnails when the animation is used. 

runME:

SEDSdlta est votre éditeur de graphismes. Il permet de définir des palettes de couleurs et des pages de blocs 16x16 ou 32x32 qui seront sauvées dans des fichiers .spr. Ces fichiers peuvent ensuite être ouverts dans l'éditeur d'animations MEDSdlta ou dans l'éditeur de niveau LEDSdlta. Les niveaux créés par LEDSdlta seront sauvés dans des fichiers .map

Deux points communs dans tous ces éditeurs: maintenir L enfoncé pendant qu'on touche un bouton/une grille/une image à l'écran permet de faire une opération différente. Et appuyer sur L+R donne un peu d'aide.

These tools seem like they're very compact and full of features, maybe to the point of feeling a little bit cramped or unintuitive, though it's tricky to do something about that with this sort of screen resolution. I do appreciate the manual that you can access whenever to find out how to do stuff, and I'd rather have all the features than have a simplified tool. I liked the "scan" button in the sprite editor; that's not something I've really seen in pixel art programs.

I can certainly agree with that. It isn't rare that I have to dig my own blog -- or worse, the source code -- of AnimEDS when I want to do something a bit less frequent like copy a frame to a given position, create a new skeletton or adjust hit boxes. I'll have to complete the "L+R to get hint on how to use things" but it's good news that someone noticed it and appreciated it. Maybe it could be completed by a "please explain that control" mode where you can touch something on screen and learn about it rather than use it ...

I feel like it would help a lot to have buttons that bring up menus (especially on the animation editor, which needs more explanation than sprite editors do), where you'd have more room to make it clear what each option does or avoid needing button combos so you can fit more options on-screen, but that has to be weighed against how much it would slow down a user who knows what they're doing. You *could* have quick shortcuts with small icons alongside a button that brings up a menu that's less compact, though.

I have started something along these lines for 'monsters edition' in LEDS... That will be motivating to push it further

As you may have guessed, that lovely avatar for Nova comes straight from her website ;)

Monday, February 19, 2024

Dans le .zip

 

Pour faire ses propres personnages sur la Nintendo DS avec mes outils, il va falloir commencer par les images. Voilà l'écran d'accueil de l'éditeur d'image de dsgametools: SEDS. Dès ce moment, il est prêt à dessiner sur la grille de 32x32 pixels présentée au milieu de l'écran. Il y a pas mal de choses qui peuvent se gérer avec l'écran tactile, et pas mal d'autres qui marchent mieux avec les boutons de la DS. On en rediscute tout à l'heure.

C'est parfois plus facile de se faire la main en modifiant une image existante qu'en démarrant de rien, donc suivons ce qui est recommandé sur l'écran du haut: appuyons sur START pour passer sur l'écran de chargement et regardons un peu ce qu'il y a dans les fichiers du répertoire Démo du .zip

Nous voilà dans l'écran de chargement touche le mot "browse" au stylet pour explorer le contenu de la carte mémoire plus librement.
L'exploreur montre \moving\*.spr par défaut. pas de défilement ici, mais si nécessaire, on peut filtrer les fichiers et répertoires affichés avec l'alphabet dans le coin. Appuyer sur "I" par exemple montrera tous les fichiers commençant par I. Pour les lettres paires, il faut maintenir le bouton L enfoncé pendant qu'on touche la case.
bg.spr contient quelques blocs libres de droit pour faire des petits décors de niveau de jeu de plate-forme
hero.spr contient un petit père Noël, également libre de droit. Notez qu'en le chargeant après bg.spr, on a encore en mémoire un "fantôme" du fichier précédent. Pas terrible ici parce que les deux fichiers utilisent des palettes différentes, mais ça peut s'avérer utile dans certains cas.
Bien. Maintenant qu'on a choisi le fichier et la page qui nous intéresse, on peut appuyer sur START pour retourner dans l'écran d'édition (ou pointer le mot "Draw" en haut de l'écran tactile, en fait).

Les blocs dans ces fichiers sont en 16x16, la grille est un peu différente qu'à l'écran d'accueil, mais le principe reste le même:

  • Toucher une case la remplit. 
  • Toucher une case de la grille en maintenant L choisit cette couleur sans changer la case.
  • Toucher une couleur dans la palette la sélectionne.
  • Toucher un bloc dans la "table" à droite le copie dans la grille
  • Toucher un bloc de la table en maintenant L y copie le contenu de la grille
  • Presser la croix vers la gauche ou la droite nous promène dans la palette de couleur ("bien pratique pour les dégradés")

Une fois les modifications terminées et ramenées sur la table, on peut appuyer sur START pour retourner à l'écran de chargement. Là, presser sur les boutons R puis A va enregistrer les modifications dans le fichier de travail "spriteA.spr", R puis B dans "spriteB.spr", idem avec X et Y. Appuyer deux fois sur R réécrase le fichier qui avait été sélectionné au départ.

 

Friday, February 16, 2024

Sand "waves" completed.

Bien. Ce coup-ci, je pense qu'on y est enfin. Le sable tombe, il fait un petit tas, le tas croule le long de la pente, puis se "dissout" au moment d'arriver à la chute suivante. ça reste "mode démo", celà dit: le code pour la pente à contresens n'a pas été testé et la longueur de la pente est hard-codée dans la "l'animation" de la vague qui descend. Mais ça fera l'affaire.

At last. Sands falls down, piles up, flows down slope and then falls again. The illusion is complete. The code is partly production-grade, partly demoshow-grade. Just what I need for a new release of the 3-rooms demo ... if only there wasn't that just-popping-up bug in the School room >_<

Tuesday, February 13, 2024

Ciao, Lime ?

Depuis plus de 10 ans, c'est surtout ma DS colorée "Lime" que vous voyez. C'est elle qui sert à dessiner des nouveaux pixels avec Sprite Editor, c'est elle qui a l'éditeur de niveau à jour pour 3-rooms. C'est encore elle qui va m'aider à faire des animations pour les nouveaux personnages.

Mais là, pour les derniers ajouts pour avoir du sable fluide, Lime me lâche. Son trigger gauche ne répond plus qu'occasionnellement, or il est absolument critique pour tous mes outils. C'est lui qui fait la différence entre "CTRL+C" et "CTRL+V" dans l'éditeur, la différence entre "pipette" et "pinceau" dans SEDS. La différence entre "charge en mémoire" et "enregistre sur ma carte SD" dans runme. Le bouton "L", c'est mon clic droit.

Hold the L trigger in one of my homebrews, and you're swapping between "pull mode" and "push mode". You pull a colour out of the SpriteEditor grid. You push a sprite into a sprite page. You push a colour into the palette, etc. Hold the L trigger on that Lime DS I've been using as gamedev unit for about 10 years and ... nothing happens. I want to pull the colour of a pixel and I push the current colour to that pixel instead. I want to push something to the sheet and I pull the older contents instead. Same if I try to pull the current tile of some spot of a level: I end up pushing the last used block instead. No need to say that this made the last step of "fixing the sand falls" super exasparatingly tedious.

Ce n'est pas la seule, bien sûr. Il y a aussi DarkneSs, qui était numéro 1 pendant AppleAssault mais qui depuis sa chute a pris plus le rôle de distracteur d'enfants mais pouvait parfois ressortir quand un test un peu plus audacieux (nouveau devkit, p.ex.). Un petit swap de linkers, un changement d'adresse IP dans mes commandes de transfers par WiFi et la voici prête à prendre le relai et poursuivre le marathon.

Les réparateurs de DS sont plus rares que dans les années 201x, évidemment, mais mon frère a pris pas mal de galon dans ce genre d'entreprise. Je garde espoir qu'on puisse remettre cette console photogénique en selle d'une manière ou d'une autre. Ses écrans et sa batterie étaient encore parfaitement opérationnels. Ou a défaut lui trouver une remplaçante.

Hopefully, that does not kill all hopes of seeing more homebrew contents from me. I still have my DarkneSs unit and its triggers seem all fine. Just swapping the linker cards, changing an entry in my IP addresses list and it's ready to take over the tasks. I have hope that the faulty trigger of Lime can be fixed, and my brother even offered a third option just in case (I'll have to find a name for a grey device, if we pick that up. Mithrandir might do)... Wait and see.

(Et pour faire bonne mesure, voilà la coque de protection de ma liseuse boox qui tombe en morceaux :/ )

Friday, February 09, 2024

Sand falls

Il faut bien l'admettre, dans toutes ces animations de Bilou qui est repoussé par les chutes de sables et de décor en pseudo-3D réalisé à grand coup de HDMA, la chute de sable tout en pixels statiques, ça ne rendait pas particulièrement convainquant. C'est donc maintenant ma dernière étape avant une petite riliize de ma démo 3-écrans.

Anokolisa mock up, initial reference

Almost every time I posted a video about Bilou being pushed by sandy slopes or about the pyramid background 3D scrolling, I couldn't help being sorry for the flat, uninspired, unanimated sands fall that are present since the first release of the 'three rooms' demo. That's the last thing I want to fix before I release a new one.

ça fait un moment que j'avais ce mockup d'Anokolisa parmi mes images à étudier et j'avais même quelques gribouilles assez réussies de comment ils étaient construits ... mais vous en conviendrez, du miel et du sable, ça ne s'écoule pas granchement de la même manière.

J'ai fini par retourner regarder les graphismes de la Sandopolis Zone dans Sonic & Knuckles ... qui au final étaient assez simples de ce côté-là: un cycle de 4 couleurs dans la palette, un tramage par-ci, une rangée de pixels transparents par là ... j'ai essayé de m'en inspirer et ça rend assez correctement pour une première démo, je trouve. Il me reste encore à animer 'le sable qui descend le long de la pente'. Voyons si le week-end m'offre le temps de faire ça ;)

But it is a bit tricky to find good pixelart reference for such item. For quite some time, I thought I could use something inspired by Anokolisa's Hive tileset, until I realised that it would never flow like sand, no matter how close I could get from that brilliant design. Neither Souldiers nor Megaman could help, but I finally remembered about Sonic's Sandopolis Zone, burried in early reference hunts. A quick check on youtube convinced me that, once in motion, they are good looking. Their design is quite simple, though: wavy patterns of 4 colours that will be palette-cycled. When they have to become half-transparent, non-solid tiles, they are alternated with empty columns or dithered with transparent pixels. That's enough for a CRT screen, but I will likely require something a bit more subtle for the LCD screen of the Nintendo DS. Well, my pattern is more angled, but it seems to be good-looking enough, given mastodon reaction.

Now I have to aslo animate the slope itself, but checking Souldiers again, I believe I might better spawn waves periodically and let them roll down a static ground than trying to animate it all as I did for the sand falls (scoop: I'm not using palette cycling this time)


Wednesday, February 07, 2024

Appleman 2.0

Bon, je me suis enfin refait les animations de l'Appleman dans l'éditeur d'animation modulaire. C'est que déjà avant que je ne m'attaque à Apple Assault, j'avais dans l'idée que Bilou puisse ramasser le corps de l'Appleman pour s'en servir ensuite de projectile. Puis c'est plus cohérent avec le comportement de dumblador qui joue le même rôle dans la School Zone.

Sauf que, vous vous en doutez, ça ne s'est pas passé sans mal. D'abord quelques plantages de MEDS (oui, encore) qui m'ont obligé à tout refaire, puis le niveau qui ne voulait plus rien charger le temps que je lui réexplique où se trouvent les animations demandées et que je corrige celles qui étaient lues en boucle alors que la machine d'état prévoit une transition "à la fin de l'animation".

You could easily claim that this was a cursed sprite and I would almost believe you. See, I've had applemen pixels from over 15 years now, and yet I wanted to upgrade its motion into a compound sprite. The idea would be to make it more like the dumblador, losing its feet when stomped, staying stunned until feet are recovered etc. I expect that it would feel fun...

Then the curse started, with blue screens in the editor as I tried to "clean up" some animations, despite I fixed something similar in September. Then the level would no longer load because some of the newly defined animations were looping and AppleAssault assumed it could wait for them to be done for some transition. And when all that was fixed, with WiFi transfers over RunMe through the NUC, the appleman did not have feet but huge, purple fists instead.

Ensuite, voilà que les pieds de l'appleman sont remplacés par des gros poings mauve alors qu'il devrait réutiliser les pieds de Bilou relookés en brun. La faute à un code encore un peu trop jeune dans le chargement d'un 2eme fichier de graphismes. Les couleurs erronées, ça, ça m'aura pris plus de temps. Je me replonge dans le code d'il y a 2 ans, je vérifie qu'on a bien assez de mémoire vidéo pour charger tout ce petit monde (scoop: oui. On a 16KiB, assez pour 8192 couleurs alors que les 16 palettes accessibles par les sprites n'en consommeraient que 4096)

To get proper images, the first thing is to ensure SpritePages are properly remapped when loading the additional set. For the school zone, that was done with spr.more "school.spr" page8,82 meds+4. Yeah, I know. That's not the most self-documenting line of script in the world ^^". What's important here is page8,82. That is controlling the remapping.

  • The first number (8) indicates that we expect Bilou.spr to feature 8 sprite pages, and that pages for "school.spr" are to be numbered 8, 9, 10, ...
  • The second is not a number: it is a series of digits each identifying a page, and each telling where each page is starting with the 8th slot. Page 8 remains unchanged (since the series starts with an 8), but page 9 will use page 2 instead (where Bilou hands and feet are)

That was for the school zone, but the green zone spriteset did not have hand and feet. Instead, they had to be added as the 11th page within the set ... almost page 20 for the level. Code parsing that was a bit crude too and was never meant for things identifying page number higher than 10. Oh, you could do it, but you might have to identify page 11 in the whole set with ;. I tried to simplify that a bit so that we can actually use spr.more "green.spr" page8,-..---.----2 meds+4 instead. Here,

  • every - in the sequence means "that page holds no sprites. It shouldn't be used by animations".
  • . means "don't touch: that page is perfect as it is". Any sprite page in green.spr has such a dot.
  • And you know about the final 2 already: it identifies one page within bilou.spr that must appear instead of a "draft" page of green.spr and be used by Appleman animations

Definitely, some colors from green.spr were loaded here. We wouldn't have the sprite-branch with colours that close to those of the trunk otherwise. But the yellow worm now has weird blueish outlines and the appleman feet are both light-Bilou-green rather than having one dark brown and the other darker brown. 

Et là, la raison était plus ... exotique, on va dire. Le code C++, rien à redire. C'est presque limpide: ça *doit* ajuster les commandes qui définissent les images et palettes utilisées par les personnages, à condition que le décalage soit correct. Et le décalage, je fournis à la main dans le script du niveau. Mais manque de bol: le compilateur (gcc 8.1.0 ajouté à devkitARM 49 en 2018) produit du code machine qui ne correspond pas à ce qu'il me faut (une fois encore). Vérification faite, le gcc 10.1.0 du devkitARM 54 ne fait pas mieux. Pour avoir enfin mes bonnes couleurs, il faudra que je réexprime mon code différemment pour contourner ce qui semble être un bug dans le générateur de code ou dans l'optimiseur ...

There's a line in the remapPages() function that should deal with that: find "change sprite" instructions in the animation code, isolate the current palette value and add the "adjust palette" computed by the caller. It should work, really, but single stepping through the code with all the optimized-away locals left me puzzled. So I dug deeper, taking notes of the machine code, tracking what register meant what and ... 0_0

and there was no add instruction to be found. Nowhere in the loop. The machine code generated by gcc 8.1.0 would just assign the same green_palette[0] to every sprite no matter what palette they were using. That seemed to happen with gcc 10.1.0 as well... it wasn't too hard to work around, but yet. Troublesome.

Wednesday, January 31, 2024

Hello 2024

Hey! The blog has finally reached over 1M views before it turned 20 years old! Not that it means much since most of the hits are likely scans from automated tools like the Internet Archive (or search engines Google doesn't know about). But yet, it is nice. I totally missed the opportunity to release something significant for the 30th anniversary of Bilou, but it has been an inspiring year and I haven't dropped the dream of a more elaborate game. So Happy new year ;)

Monday, January 29, 2024

Over-engineered ?

Maybe I'm starting that "swim made fun" thing by the wrong end. What I really need is to be able to move Bilou through water and to get him out of the water. Sure it is fun to swim in Rayman Origins, it was pleasant in DKC and a nightmare in TNMT on NES. But unlike all these games, I have no "water level" planned in Bilou: Dreamlands. The reason why I started working on dash-in-water is not because travelling through water would feel empty without it. It isn't even because I have level sketches where jumping out of water is a key mechanics. It is solely because in the current demo, you can't reach the green room exit unless you trigger an unintended double-jump with precise button mashing that should be left to speedrunners.

J'avais donc un beau projet pour les mouvements dans l'eau. Je venais de commencer à ajouter "on accélère si on appuie sur JUMP" et J.L.N a pris "la manette" en main. Il a nagé à droite. Il a nagé à gauche, puis il a voulu sortir de l'eau. Et bien sûr, lui n'a pas attendu que Bilou revienne à l'état "je patauge en attendant" avant de presser le bouton de saut: il l'a fait depuis l'état "bilou nage à gauche", là où j'avais prévu un "fonce dans l'eau vers la gauche" en réaction au bouton "pied"... Bilou n'a donc même pas tenté de s'élever d'un pixel. J'avais échoué le test n°1 de Miyamoto: "the JUMP button makes Jumpman jump". Et donc je me suis enfin posé la bonne question: "Est-ce que j'ai vraiment besoin de tout ça, moi?"

Parce que dans mon cahier bleu, avec les croquis de level design que j'ai l'intention d'utiliser pour Bilou's Dreamland, l'eau est bien présente, mais je n'ai jamais un "niveau aquatique" à proprement parler. Ce qui motive cette recherche sur les mouvements dans l'eau, c'est juste le fait que la berge est trop haute dans la démo. Et donc, garder une mécanique simple "JUMP" à la surface = sauter hors de l'eau et sauter hors de l'eau près de la berge = sortir de l'eau serait impeccable si j'éditais un rien l'écran-démo pour que sa berge soit un tile plus bas ^^" (et éventuellement que j'augmente de 15% la hauteur du saut depuis l'eau, actuellement défini au doigt mouillé)  

I wanted to use the opportunity of changing the level map to also fix an issue I had with the interaction of surface-swimming and following the water flow. I presume that the core of the issue is that the *middle* of the character's bounding box is used to determine whether there's a flow to follow. But "stay at the surface" code maintains Bilou above the flowing tiles. As soon as one pixel of the box enters the "full water, flowing downwards" tile, it starts pushing Bilou upwards.

I made a few bad moves, like trying to have full-water-flow-downwards tiles higher (closer to the surface), but that didn't work at all. Instructing the level that "water-flowing-downwards" can be felt through did work pretty well, I think.

Pendant que je testais cette nouvelle map avec sa nouvelle "berge" moins haute, je me suis rendu compte que depuis qu'on sait nager à gauche et à droite, les remous de la cascade ne nous entrainent plus vers le fond. La flottaison est trop efficace et le centre de Bilou n'entre plus dans la zone qui le tire vers le bas. J'ai un peu chipoté, mais heureusement, il suffisait de permettre à Bilou de "tomber" aussi dans cette zone pour que tout rentre dans l'ordre (enfin, je pense)

Tuesday, January 23, 2024

Input Buffering.

Tout est parti d'un tweet de Case Portman, auteur du jeu "Flynn, Son of Crismon" dont je suivais le développement dans lequel il nous expliquait en quoi le "jump buffering" est fondamental dans tout jeu de plate-forme. Un nom un peu barbare pour les francophones qui consiste plus ou moins à faire du voyage temporel avec votre manette de jeu.

Quand le joueur est au sol et qu'il fait sauter son personnage, on s'attend à ce que le saut soit pris en compte à la frame exacte où le bouton est enfoncé. Pas trop difficile. Supposons que le joueur veuille rebondir sur le sol en finissant un saut. Il sera assez fréquent qu'il appuie sur le bouton de saut légèrement avant de toucher véritablement le sol. Son intention est de rebondir. Le code peut faire deux choses: soit ignorer la demande de saut vu qu'on est en l'air, soit effectuer un saut dès que l'on atteint le sol. Et clairement, les jeux qui suivent la première approche sont désagréables pour les joueurs.

In my notebook for 2022-2023, I had a small page about Case Portman's post on Jump Buffering (link recovered, thanks, search Engine :P), where the author of "Flynn, Son of Crismon" explains:

It's a nifty little feature that will add *a lot* more flow to your game. This can also be applied to almost any action! Shooting, melee attacks, dodge rolls, even menu selection.

Don't let the name frighten you: what it truly means is that you're time-traveling with your  DPAD, pretending than your jump button presses did not happen when they did. If time was a photoshop/gimp layer, then jump buffering would be something like "snap to guide". He went on with a detailed and beautiful gif animation showing how to achieve that and make the game more tolerant on the case where player is about to land on ground and press the jump button in one of the last few frames mid-air. Many 8-bit games failed to do so and feel unfair when played.

Dans mon moteur de jeu, tout celà est pris en compte par le contrôleur "dpad". Pour chacun des boutons, ce contrôleur retient si le bouton était déjà enfoncé lors de la frame précédente, et pendant combien de temps encore il doit être considéré enfoncé. La fenêtre de temps autorisée (6 frames, soit 1/10eme de seconde) sera la même pour tous les boutons. Je me suis refait un petit schéma de la manière dont c'était géré parce que je l'avais complètement perdu de vue. "to[i]" sur ce schéma, c'est le timeout associé à un bouton donné.

I realised then that how my engine does this slipped out of my brain: it was about time to document it and blog it. It all happens in the DPAD controller, where a counter will be started if a "new press" is detected and reset if the button is released. The counter is decremented every frame while you're holding the button. But earlier tests in SchoolRush shown that this is not enough. In some part of the character behaviour, we actually *must* indicate directly whether the button is still pressed. Without that, there's no such thing as "keep jumping higher as long as player holds JUMP button" or "keep floating as long as player holds JUMP button". My engine handles that with a bitmask that indicates which button should report "pressed" instead of "held".

Par contre, on peut définir état par état quels sont les boutons pour lesquels on veut un mécanisme du type "enfoncé il y a au plus 1/10eme de seconde" et ceux pour lesquels on veut "maintenu enfoncé depuis aussi longtemps  qu'on veut. 

Quand on définit "MOVE + FOOT" pour l'état "flotter" (dans les airs, façon super-cape de SMW), ça signifie que le DPAD et les boutons de sauts ne passeront jamais par "decrease timeout". l'état "chevauchée d'éponge" évitera quand à lui de faire expirer "MOVE + HANDS". Et pour tous les états où on a rien précisé, c'est le DPAD et la gâchette droite (qui sert de déclencheur pour la course) qui seront maintenus.

But watch the catch: while the controller code defaults to 'held', the script instead indicates which inputs are expected to be "held", and defautls to "press" ... that's why you see 'using dpad(MOVE|FOOT)' for the FLOAT state, where it prevents the press to expire while floating.

Monday, January 22, 2024

How long before we play ?

Somebody asked The Question: how long before we can play the game (presumably Dreamland). So I picked my secret blue notebook and for every level, I tried to identify what I'm still missing to let you play it. Each of the checkboxes cost about 1 month of hobby time. maybe. I won't try being a project manager here. Not during hobby time. Oh, and blue boxes cost more. Possibly up to 3 months.

Je n'ai pas vraiment envie de jouer au gestionnaire de projet pendant mes temps libres. Mais voilà, la question a été posée: "dans combien de temps est-ce qu'on pourra jouer" (à Bilou Dreamland, je présume). Alors j'ai repris mon cahier bleu, celui des secrets, des niveaux et des idées de gamedesign. Et pour chaque niveau déjà esquissé, j'ai fait l'inventaire de ce qui me manquait déjà. Pour les 3 premiers mondes prévus pour le jeu. Je n'ai encore aucun niveau pour le 4eme (ni aucun pixel, d'ailleurs). Chaque case à cocher sur cette map géante, c'est probablement 1 mois de hobby. Probablement 3 pour les cases rehaussées de bleu. Faites le compte ;-)

edit: avant la prochaine démo,
  • [done] faliciter la sortie de l'eau
  • [done] animer les chutes et les pentes de sable
  • [done] Appleman en CompoundGob

Mais la bonne nouvelle, c'est que certaines de ces cases ne sont pas indispensables pour avoir une version "jouable", c'est à dire où on puisse atteindre la fin des niveaux. Les PNJ, par exemple, sont supposés être optionnels tout comme Yoshi était optionnel. Parfois, une substitution par un élément déjà existant pourrait s'envisager. Certains niveaux de la school zone seraient mieux avec des lattes en guise de tremplin, mais déjà jouables en utilisant les gommes rebondissantes de School Rush, etc.

Sunday, January 21, 2024

De l'eau par ci, de l'eau par là ...

Tentons donc de nager. La première chose serait de pouvoir stabiliser Bilou à la surface sans l'immobiliser pour autant. Ce n'est pas impossible parce que j'ai une bande de 2 tiles à la surface qui est à la fois de l'air et de l'eau. Une ruse pour que Bilou-qui-coule puisse succéder à Bilou-qui-tombait et que la dernière position valide pour l'un soit aussi une position valide pour l'autre. Bilou-qui-flotte à la surface devrait donc éviter d'entrer dans une zone qui n'est que de l'eau ou dans une zone qui n'est que de l'air ? Il lui faudrait pour ça un contrôleur dédié ?

props: 0fc8
props: 8fc4
props: 8fcc
props: 8fcc
using swim
using gravity
using gravity
using float (?)

So, switching between "fall down" and "pushed up by the water" is not quite satisfying to emulate "floating at the surface". Partly because that means every transition between the two resets the animation. Mostly because how leaving water is notified and how that prevents DPAD events to be notified, making things like 'jump out' or 'switch to swim-left' impossible. So I spent time now and then during the week to figure out what I should do to get the desired effect. I do have a row of tiles that are both air and water... could it be enough to try and confine Bilou there when he's floating ? That wouldn't be impossible, but Bilou is 13 pixels high and the row only 16. Not much headroom ...

Mais en fait, ça s'est avéré encore plus simple que ça. J'avais entre-temps réalisé qu'il serait peut-être suffisant de faire tomber bilou-qui-flotte s'il est tout entier dans la bande de surface et de le faire monter s'il est bas dans cette bande ou s'il a commencé à s'enfoncer dans l'eau. Mais en testant, il s'avère que juste "tirer vers le bas dans la bande-surface, pousser vers le haut si on est ne serait-ce que d'un pixel dans la partie que-de-l'eau" donne le résultat qui me convient. Les mouvements de Bilou sont souples et amples, son animation n'est pas interrompue inutilement et sa position est pertinente par rapport aux graphismes.

Hopefully, it turns out that I only need that area for the 'pull down' part of the move. Pushing up can happen anywhere in water because this is the default behaviour in water. I had plan for an extra "surface position" parameter in swim controller instead of a new float controller, but it turned out that was useless as well because the default position (where Bilou is completely in the 'both' row) is just what I need given current graphics.


 

That seemed proper time to try the new 'swim right' and 'swim left' animations inspired by Fury of the Furries. But there I got annoyed again by how other controllers "steal" the focus of an earlier event. This time, the DPAD event notifying that I've pressed LEFT got replaced by an event mentioning that speed changed direction. It did not happen when pressing RIGHT because positive speed to the right and null speed at rest appear to have the same sign.

I cannot possibly express how satisfying it is for me to see that little animation coming to life and respond to my left/right/left/right keypresses. I guess I'm glad I kept up with gamedev so far ^_^