Showing posts with label dr24. Show all posts
Showing posts with label dr24. Show all posts

Thursday, February 06, 2025

smasher pixel study

Fin janvier, je suis tombé sur un élément intéressant dans une vidéo de Ristar que je n'avais encore jamais rencontré: un gros poing sculpté dans un bloc. Intéressant parce que je n'ai pas encore de rendu convainquant pour le gros-bloc-écrabouilleur pour ma pyramide. 

J'ai commencé par le redessiner plus ou moins tel quel avant d'en déduire une version tournée vers le bas (et donc avec un autre genre d'éclairage.

You know, I'm still trying to get something convincing as big smasher for my pyramid level. And after a good deal of not-so-convincing too-realistic designs, I stumbled upon an interesting reference while watching a playthrough of Ristar. A big, closed fist, that looks cut out of a concrete block... Interesting geometry to say the least.

So after first trying to reproduce the design, I tried doing it flipped-down, with adjusted lightning to match it ... I also tried make a sort of perspective shift, observing that the lateral view is also iconic of a closed fist ... None of that has been converted to pixels yet. 

After those, (way after. This is almost necro-blogging) I eventually went into that Super Mario Wonders level with big Bowsers fists all over the place... clearly Mario Wii / WiiU fists had been an inspiration for the original design, and clearly too, the weird look of cast-hot iron won't help me giving my own art a fit-a-pyramid look ... But it shows me right now that 5-fingers fist will never look fit in Bilou's world, where things have at most 4 fingers -- Mickey-style -- when they have fingers.



Bref, c'est joli, mais même avec une permutation isométrique reprojetée, il reste un truc qui cloche ... et peut-être que malgré leurs couleurs inexploitables, les poings de Bowser viennent de me donner la réponse: dans l'univers de Bilou, un poing à 5 doigts, c'est un doigt de trop.

On va donc reprendre le cours de Helm (maintenant qu'il est en ligne ^^), une série de gants de Mickey Mouse et essayer de se construire un gros poing bien lourd et bien bilouteux pour faire du jus d'intrus dans cette fameuse pyramide ...

Et non, ce n'est absolument pas un point prioritaire sur aucun des non-plannings ... donc ... on le fait en moins de 15 jours ^^"

Saturday, January 11, 2025

Dreamland checkpoint

"I can roughly work 1 maybe 2 days on Bilou every time the kids have holidays" was my answer to my step-brother when he asked whether I was still working on my game. So where are we (compared to 2024) ? 

Let's check some boxes, to see that. Note how I realised that I shouldn't try to include that level with 3D books : that would require new tools development and we're now past that kind of change.

Some of the box have been shifted from cyan to green: that means they're still things that will require more significant work to be done, but they're not *mandatory* for a first playable version of the level they're featured in.

And I just read a note I made to my today's self: 

There'd be some fixing on the old maps, possibly some keys or switches by NPCs, but that shouldn't be as ambitious as The Big Green Zone Relooking I've been talking about 3 years ago. The aim would rather to make the game more fun to play, and clearly not to get rid of any magic door.

The geyser thing is almost a "big relooking" thing... "push and flood the level" clearly was. It shouldn't stop me from trying the level.

Monday, December 30, 2024

Et un Bangbash qui marche ! ...

Enfin ... "marcher", c'est beaucoup dire. Mais il bouge, il fait demi-tour en bout de plate-forme le tout dans son environnement naturel. Par contre, la quasi-totalité des animations de transition (atterrir, arriver au sommet de la courbe de saut, etc) ne fonctionnent pas (pour des raisons dont le niveau de compréhension est encore variable), mais bon sang, on l'attendait depuis tellement longtemps que je ne vais pas faire la fine bouche avec un "ouais, mais non, je vais attendre qu'il soit fini avant de poster quelque-chose", hein ;)

Finally! Finally I've got a working bangbash in a Bilou Level! it's not yet fully functional, but there it is, hoping ahead and back. I still needs care for the transition animations but at least it unlocks some levels designed almost 18 years ago. Think about it: bangbash has been waiting to get alive for almost as long as the pendat did!

Bon, par contre, il faudra vraiment que je fasse une révision de Inspector Widget, pour 1) montrer les testpoints dans la zone radar, 2) faire en sorte que le *hot spot* soit toujours dans le radar (et pas le centre du personnage, parce que pour bangbash et pendat, ça ne sert strictement à rien.

I'm a bit ashamed at how long it took me to understand why I couldn't make it turn back as intended. It should really have been as easy as pressing START and checking InspectorWidget. Especially since I still have to add collisions, Bilou detection and bashing animations. If I want Bangbash to have a dedicated move when Bilou is on the top of a pencil, I should better polish my tools ^^".

Là, j'ai dû faire mon débugging en combinant ddd et gimp ... en allant gratter dans les fonctions internes de libgeds. On va dire que côté dever-friendly, il y a mieux ^^". Aucun risque de faire de l'ombre à gbstudio dans ces conditions...

edit: avec un peu plus de travail sur les animations, la position des images par rapport à la "boîte-position" du personnage, ça donne enfin (4 janvier) ce que voulais que ça donne. Bon, évidemment, ça ne satisfait pas J.L.N qui demande "il attaque déjà ? " et "on peut lui envoyer des taille-crayons ?" ... pas encore, mon p'tit loup ... pas encore ...

Wednesday, October 30, 2024

October update

That week off has been pretty B-usy ... The 'three rooms' demo now actually feature 2 additional rooms, including one that is level-sized. There are still quite some things to fix, tileset updates, adjusting to .more loading, and the like... 

Bienvenue dans un post-qui-change... ma petite semaine de congé d'automne aura été bien remplie de p'tits Bilous (entre autres choses), avec en objectif #1 l'ajout de deux "niveaux" dans la démo "Three Rooms", comme proposé en Mars. Evidemment, comme ils datent tout deux d'avant SchoolRush, il y a eu pas mal de mini-couacs à corriger pour éviter de se retrouver avec un niveau au décor psychédélique qui se termine dès qu'on casse une craie

Well, some recent development are incompatible with some old mistakes... especially bounding boxes. I remember being puzzled by what worked and what did not worked when I introduced the 'sand waves', which did require one bbox x y w h command to align the visuals with the slope ... but it really was almost blind guesses.

For some reason, the "box size" bits were ignored, and the "offset" bits were ... well, it will work better with offsets that says "pictures starts 4 pixels on the right in the 16x16 frame. Of course, fixing the size first made most of the offset wrongs until I've got new offsets computed.

Even after one more afternoon of map fixing, there are weird things happening in that school zone level, like 

  • [todo, not critical] Bilou not always hidden by front layer (e.g. hidden if you jump, but not if you're idle or walk)
  • [todo, not critical] Inkjets not moving up and down following rails

Le plus gros morceau, ça aura été de corriger le code qui permet à un simple sprite 16x16 d'être considéré comme étant plus grand ou plus petit ... une modification essentielle pour passer du furblock à la branche mais qui interférait avec les gouttes d'encres d'inkjet et les vagues de sable ...
Alors, voilà: un joli bouton vert vers une nouvelle démo à essayer chez vous. Bien sûr, ça reste très en chantier et vous trouverez pleins de trucs pas au point, mais au moins, les horreurs ont été éliminées. Rendez-vous en Décembre avec une démo incorporant BangBash ?

Ah, and it's not in the school zone, but [done] that ugly pink background showing up in the green2 level, too... I'd rather have that fixed before uploading a new demo...

edit: There we are: 2 work-in-progress levels can be found if you explore the three rooms properly. There is still much to do, but also much to explore if you've never launched anything earlier than School Rush.

Friday, October 25, 2024

Hanging around in the ICE ...

Good thing with the German express trains is that they provide unlimited power and some WiFi. Your trip might not go as you expected, but at least you've got time to sit, think and check your code base to plan what you'll do in your homebrew project afterwards.

Among those "what's next", some are already done now, like "converting furblock to treebump"... which it did not need after all.

For some time, I have this little note in my notebook... Because many of the levels in the design book expect that we could hook and hang to some objects. I'd like it to be stylish, with swinging animation and all. But for the purpose of testing the levels and trying the game, just snapping to the hook and waiting for the player to press JUMP or leave would do the trick.

The train-idea here is for the step just after that bare proof-of-concept: I already have a "radius" controller that keep a character within a given range of a "pin point". Being hung could use that controller rather than being snapped to a static position. 

To do so, we can shoot a new game object, Bilou's hand(s), that will snap to the hook and use that as a pin point for the swing. That means we'll have to hide bilou's hands on the existing hero game object (like we do when he's carrying something) ... or just don't draw the hand at all, and reuse its OAM slot to draw Bilou's eyes separately from his body, meaning we'd gain one extra freedom degree for the animation, and wouldn't have to draw a dedicated body-and-eye sprite for every angle.

Then I started brainstorming about the croc-platform: I'm not satisfied with its current look. I dug some real egypt crocodile pictures (and real statues pictures). I toyed with the idea of having the crocodile head showing sideways rather than front view -- that would have meant it wouldn't stop sands when flapped anymore ... The blue book said it wouldn't harm that much.

But I couldn't convince myself it would work either. When the crocform#1 flaps down, it completely cease to interact with characters. A sideways crocodile head flapping down by 90° wouldn't "disappear" that way. It would still be in Bilou's way, mostly as a small wall, but it should still be possible to stand on the rear of its neck ...

A few spots in the ongoing level design would work fine with crocform#2 repurposed, but in other spot, it would mean throwing the player into spikes, rather than just let them fall down...

And then I thought about a type of object in New Super Mario Bros that would behave quite like what I need for my collapsing platform, and it meant I wouldn't even need to drop the "shut the sand door" idea:




Monday, October 21, 2024

bug on blador

J'ai tout les morceaux pour qu'on puisse à nouveau utiliser la map "anniversaire" de la school zone dans l'exécutable de "Three Rooms Demo" ... mais quand je veux le faire tourner, on ne peut pas vraiment dire que les choses se passent merveilleusement bien. J'ai cru au départ que c'était des choses que j'avais "cassées" en développant le "soft landing" des furblocks (la motivation n° 1 à faire revenir ce niveau *maintenant*, c'était précisément de vérifier l'absence de régressions). Et des choses qui vont de travers, il y en a quelques unes ^^°.

I wasn't 100% confident with the changes I made to special flags used to implement the furblock... So as I'm entering one week off, it seemed appropriate to ensure I have all the required material to revive a School Zone level where all the "monsters" are featured and ensure there aren't regression. So here's the "anniversary" level again.

Mais pour certains bugs, un petit voyage dans le temps avec Mercurial ne laisse aucun doute: ils étaient déjà là avant. C'est notamment le cas avec dumblador, et Bilou qui tout d'un coup se retrouve bloqué et immobile s'il lui atterrit dessus au moment où il devrait pouvoir servir de plate-forme...

Cette fois encore, c'est dans ddd que la réponse est apparue. Si le n° d'état renseigné par InspectorWidget (bi28) est pour "RIDLE", l'affichage de Bilou en train de tomber n'est pas un glitch: on a jamais su rester sur le taille-crayon parce que le contrôleur "onpath" estime qu'il n'y a plus de plate-forme... la faute à une modification pour crocform qui ne s'est pas re-propagée jusqu'à dumblador: le choix du bit d'état qui indique si on est bien sur une plate-forme ou non ...

And well, we do have some regressions, and some of them are quite older than the furblock modification. Today I repaired the ability to stand on a stunned blador, which should have been updated after I implemented the pyramid "collapsing" platform: it reuses bit-testing that allowed stacking dumbladors, but for obscure internal reasons, it did not use the same bit to declare that the platform is indeed valid. Tricky to find, but easy to fix.

Saturday, October 19, 2024

On y est !

Enfin ! Un peu de bidouille, un sprite qui doit encore être invisibilisé, mais j'ai enfin les physique voulue pour cette branche rebondissante! Dites-moi ce que vous en pensez, mais moi, je suis plus que satisfait par son mouvement ^_^

Euh ... non, je n'ai pas grand-chose de plus à en dire, en fait... mais bon, ça traine depuis tellement longtemps que je voulais marquer le coup avec un p'tit post qui reprenne l'image. 

Je ne suis pas sûr que ça mérite de ré-uploader un .nds ... je vais plutôt me faire un jus et me mettre au lit. Ciao tutti ;)

Finally ... Finally, I've got my bouncing branch working with the intended "furblock" physics. Almost everything else is said in the previous post, and you also have a download link there to try the physics on the original furblock ... But this has taken so long, I wanted it to have its own post.

edit: there was a little issue left: if you watch the animation closely, you'll note that the branch makes an extra wobble one time, and no such thing on the next time. It wasn't intended at first, but it felt nice when happening, so I made an extra "smaller wobble" animation to use as a transanim in the "throw->idle" transition. But it still had that odd/even behaviour, doing it only every other time. It turned out that when Bilou lands on the branch during a transanim, it did not reset the transanim flag. This is a desirable feature when making transition animations for Bilou mid-air, but not here. there's an extra anim2.force script line I can add to say "this animation (big wobble) may interrupt any ongoing transanim", but its implementation was apparently broken. Should be fixed now.

edit+: OMG. I just stumbled upon the original bouncyBranch.xcf discussed in the first post... timestamp is 24-08-2020 ^^"

Newer collision flags

It wasn't as easy as I wanted to make the "soft land" mechanism work, and knowing that Bilou will have to attach to an invisible block for it to work with the "bumping branch" rather than to the branch itself will make it even a bit harder. The issue is to allocate new "kinds of collisions" in an already crowded 16-bit space.

That issue is not new: it already appeared when I wanted to add pick-and-throw mechanism together with get-your-feet-back while I was just done with direction tiles for inkjet. Each of these would require about 4 different type of "messages" exchanged between game object and I had barely more than 8 flags left... And the solution had been to use some combination of bits for the different things. So you'd still have 0010 saying "up" and 0020 saying "down", but that would only be valid in connection with 0100 that says "direction tile" and not with 0400 that says "interplay" or with 0800 that has been used to collect feet and animate ink level in pipes.

I've got notes already about addressing that, but they mostly question the fact that there are only two "casts" (read game object lists) in the engine: heroes and foes. And that actually address a different issue (collision performance) although they somehow partition "messages" as well: almost only Bilou can receive a "HURT" collision (well, blador receives it too from spiky pencils tiles so it can align with them and this is likely BadDesign ^^")

And well, introducing bridges and things like that could easily use more casts to keep good performances: both heroes and baddies will collide with bridges, but that doesn't requires baddies to test each others to work. And likely only part of the bridge internal.

I had collected a set of questions on my new notes, and one of the first one got its answer: despite we have only 16 bits communicated to the script about what truly happened in a collision, a full 32-bit number is stored internally. Some of the high bits are already use for special purpose such as "keep checking collision even after a first item was found" or "only consider objects attached to me", but plenty others could be used to restrict the scope, e.g. creating a private "namespace" between blador and blador feet so that the feet cannot accidentally attach to an inkjet (although maybe that's redundant with "must be attached to me"). It makes little sense to keep the upper 16-bits as "flags" and process them the same way the lower 16-bits are processed (a single matching bit and bingo, we have a collision) because we would be unable to identify which flag had a match. Did we caught fire ? or get smashed ? or got an electric shock ? no way to find out.

So the plan would be the following:

  • 8 "casts" (lists) seems a good number. Each test area indicates exactly which cast it tests. If we have casts Evil and Bridge and need to test both for STOMP, then 2 test areas are needed.
  • two three "control" bits: ALL, ATTACH and Reverse-ATTACH (fact-checked against Aug'25 commit)
  • 16 "flags" bit: a collision occur as soon as two masks have at least one in common
  • 8 10 "namespace" bit: a collision occur only if the two area exactly use the same namespace 
  • any other are reserved for future extensions.

Saturday, October 12, 2024

Un furblock qui a du ressort

ah. Voilà qui est mieux... Le saut est amorti, puis le bloc re-propulse Bilou en l'air une fois dans la phase à gravité positive. J'ai encore un glitch temporaire à régler, mais au moins Bilou ne se met plus à rebondir dans le vide une fois sur deux. Alors je suis sûr que vous avez d'essayer ça, donc.

And give it a try yourself. I finally have a bouncy block that is bouncy the way I want, dampening your fall, kicking you up when it is back.

Not only that, it also allows buffering of your JUMP commands so that you get a high-jump if you press and hold the JUMP button anytime while the furblock is dampening. JLN managed to get a high jump on any of his attemps. (of course, he is disappointed that it isn't possible to use the glitch to charge even more jump power and make a super-jump taking you out of the map into a super-secret area :P)

Et si on appuie sur le bouton de saut au bon moment (c'est à dire n'importe quand pendant qu'on est sur le bloc), on part en super-saut. Hahaa... On est prêt pour ramener ça sur la branche aussi...


$BACK->$IDLE on event2 [v1 256 <] ($VTHROWN(0) 0 :1 0:6); // 1 
$BACK->$IDLE on event2 [v6 0 <=] ($VTHROWN(0) 0 :1);      // 2
$BUMP->$BACKLAST on event2 [v6 1 =] (v1 2 / :1 v6 1 - :6 $DIR(D_DOWN));
$BUMP->$BACK_ on event2 (v1 2 / :1 v6 1 - :6 $DIR(D_DOWN));  // 4

$BACK->$BUMP on event2 (v1 2 / :1 $DIR(D_UP) $VTHROWN(VTHROWN 3 * 2 /);

$IDLE->$BUMP on hit0 [w1 0 >] ($VTHROWN(200) w1 512 m :1 $DIR(D_UP) 3:6);
$BACKLAST->$BACK_ on hit0 [w1 0 >] ($VTHROWN(200) w1 512 m 2 * :1 3:6);

The little glitch we still observe is linked to the BACKLAST state. Normal cycle alternates between BUMP where Bilou can stay landing on the block (think as "compressed" state) and BACK where Bilou would be ejected ("expanded" state). There may be up to 4 such oscillations before the block comes to a halt. A former glitch happened when Bilou would fall back while we're in BACK state and react as if it hit an eraser although it isn't close enough.

BACKLAST was intended to fix this: it let the block oscillate one last time, but it doesn't feature the hitbox that would propel Bilou up. Of course, that does not work alone, so I also added a transition that restart a cycle if Bilou still shows up, exactly as if we were idle. But we cannot simply do BACKLAST->BUMP, else we will screw up how the "on grid" controller decide where we should transition.

My last glitch came from the speed division on line #3, that makes each oscillation smaller than the previous one: if we keep the last line's expression identical to that of $IDLE->BUMP, the speed will almost immediately be very low, and we might not hit and propel as intended, hence the additional 2 * to compensate the division that is about to occur as soon as we've reached the "default" position of the block. (still, I'll have to cross-check the collision coordinates: it doesn't feel right that it need that much fine-tuning...)

update: okay, works for the branch as well. Just took 1 or 2 hour of tuning...

Friday, October 04, 2024

furblock de montée

La dernière tentative d'améliorer la branche s'est plus ou moins soldée par un échec constructif. Puisque le week-end de montée m'offre un peu de répit, je vais partir sur une idée qui m'est venue en passant en revue les autres jeux avec des éléments de gameplay similaire: commencer par me faire un "bloc-note" à la SMB3, qui se concentre sur le mécanisme, pas sur l'animation. Et une fois que le mécanisme sera validé, je fait la même chose avec un objet invisible.

So trying to combine physical motion and animation for the bouncy branch proved to be a bad idea. Rolling back. I'll keep my satisfying animation and combine it with an invisible block behaving like the "note block" of Super Mario Bros 3 instead. And I'll prepare that with non-invisible block in an easier-to-test environment, that is the pyramid room.

  • premier fix: je dois retirer les zik.import de mon script pyrat.cmd: ces commandes sont propres à la "trhee rooms demo" qui pré-charge un module de base (bilou.xm) et runMe ne connaît pas (encore) l'équivalent, même après recompilation du dernier modèle
  • deuxième fix: runMe a besoin d'un "../spriteB.spr" explicite pour aller chercher le nouveau fichier (et pas un vieux fichier de SchoolRush dans efs:/moving/spriteB.spr ^^")
  • 3eme fix: ma petite anim' faite à la main doit utiliser la SpritePage 8+2 (parce que le fichier bilou.spr préchargé contient 8 pages)

Bon on y est. J'ai un "furblock" dans le niveau-test de la pyramide. Je saute dessus et il s'enfonce bien puis ... il décole vers l'infini et au-delà (ç.à.d  -2147483648). Ah oui, et il n'a encore un tête de fury que sur DS, pas sur l'émulateur. 

J'ai utilisé pour le réaliser un nouveau contrôleur "grille" qui indique si on est repassé au "bloc" suivant, histoire de passer d'un état "repoussé vers le haut" à un état "repoussé vers le bas", et que le bloc finisse par se stabiliser à sa position d'origine. Mais manifestement, ça ne marche pas encore.

There have been a few "setup" issues, leading to a few TODO items to be processed later (this season?) in my notebook, like runMe not supporting the multi-music commands and the lack of "translate to that sprite page" macro for multi-spriteset that leads to annoying magic numbers. But I have to admit that even with that done, the behaviour was fairly surprising. Well, on the DS, the "furblock" did a downwards bump and then skyrocketed to negative numbers: I needed something to fire an event when the original position has been reached. And that thing could be the "grid" controller that was part of my "how to code bosses" arsenal.

But even with that, the resulting behaviour is emerging and perplexing. I guess I haven't found the proper set of rules yet.

Et nous voilà le week-end d'après encore plus au calme, ce qui m'a permis de décortiquer avec InspectorWidget le comportement émergeant (mauve) et de trouver les corrections (bleues) nécessaires pour que ça marche pour de vrai ;)

Special thanks fly to Wye for his SMW-remake-howto video and how it reminded me that the Springy note block exists in first place, and how they were perfect match for the feature I was looking after. ^_^

Saturday, August 31, 2024

Meilleure branche

Voilà déjà un moment que j'y cogite: faire en sorte que la branche-qui-rebondit soit plus facile à utiliser. Dans sa version actuelle, on doit appuyer sur le bouton de saut au moment où elle nous propulse, pour bénéficier de la hauteur maximale. ça ferait bizarre de se voir propulser plus tôt, l'ennui c'est qu'entre les deux Bilou nous fait un petit rebond casse-pied.

A few notes on how the bouncy branch should be adjusted. But I wanted to try at least one thing before starting to discuss it: couple branch animation and motion so that the actual position of the "solid" hit box of the branch would change over time.

With that done, I could switch Bilou to a "land on soft ground" state where some button press are frozen in time, and when the branch will eventually reach the animation frame where a "throw up" collision can happen, player's JUMP input wouldn't be ignored.

Une des stratégies que je veux mettre en place, c'est donc de lui rajouter un état "atterri sur quelque-chose de mou" pendant lequel il attendrait que l'animation de la branche se termine et atteinge les images où on propulse Bilou.

J'aimerais évidemment que Bilou suive le mouvement de la branche pendant ce temps-là, et c'est en tentant de corriger ça que je me suis retrouvé bloqué par un gros bug pendant les vacances des enfants. Une de mes stratégies pour ce suivi, c'est de faire en sorte que la hitbox "solide" de la branche se déplace au fil de l'animation, un peu comme le faisait le petit ver jaune, premier personnage animé sur DS.

There is "animation/motion" coupling feature in my AnimEDS. It has been introduced so that feet stick to the ground ... But unfortunately, the animation of the branch wasn't drawn with that in mind. AnimEDS expect you to make your walking cycle with the "main body" of your character at fixed position, with hand and feet moving around. Then you'd show one feet and say "this one should be pinned to its position, and all the rest will move around. The bouncy branch was drawn in the other way round: the leaves part (that the hitbox should follow) is moving around and the wooden part (which should be pinned) is already sticking in its position.

Mais la branche, elle est réalisée dans AnimEDS dont les mouvements sont un peu différents. Rééditer chaque position de chaque étape d'animation, ce serait franchement pénible. Mon plan B, ce serait donc de m'inspirer de la plate-forme invisible qui empêche Sonic de tomber trop vite dans le pétrole de Oil Ocean, et générer un objet invisible qui fasse attendre Bilou pendant que la branche, qui ne serait plus solide, termine son animation.

I pushed it to the state where I actually have the animation triggering motion when playing, but it makes the whole branch detach from the tree and move down. Hopefully, I have a plan B : do something like the invisible platform hidden in the Oil Ocean of Sonic. There, it catches you and moves down slowly, allowing you to jump back. Here, it would do the move Bilou is supposed to do. It would be spawn when Bilou hits the branch, too.

edit: je ne voulais pas rester sur un "oah, ça va être trop dur", donc je l'ai fait. 20 minutes de bidouille dans AnimEDS à utiliser les petites croix pour réaligner le bas du feuillage à chaque image, retenir "3 vers le haut, un vers la droite" et appliquer le même décalage à la main à tous les éléments. C'est pénible, mais avec le DPAD, c'est possible de le faire de manière précise.

Ensuite, j'ai récupéré le .spr sur PC et un petit coup de débuggeur m'a permis de comprendre pourquoi using momentum(y to 1024 by 64) ne modifiait jamais la vitesse: j'avais écrit les valeurs pour le pseudo-pad dans le mauvais "registre" du gobscript ^^". Je corrige donc ça aussi et je me retrouve enfin avec une branche qui bouge quand on tombe dessus, synchronisant sa position (pour les collisions) et son animation. Sauf que c'est pathétique.

La dynamique de l'animation est complètement cassée: tantôt la vitesse que Bilou lui imprime est trop élevée et on passe des frames, tantôt les mouvements accumulés sont inutiles parce que l'animation fait demi-tour et on reste "gelé" sur la même étape jusqu'à ce que la vitesse négative soit devenue telle que la suite de l'animation va elle aussi être jouée à trop grande vitesse. Et ça, c'était avant que je ne vienne modifier certaines étapes pour forcer l'utilisation d'un délai cassant au passage la propriété 'position finale = position initiale" ce qui explique que la branche remonte petit à petit dans l'arbre au fil des cycles.

Friday, August 09, 2024

Fixing the Inspector

I've been through another guru-meditation session last night. It's a bit weird to claim "I like it" while it implies checking hex codes between disassembled C++ and numbers shown on the Nintendo DS screen, looking up for virtual table addresses in gdb to confirm some arbitrary location found in the DS registers actually leads to a GobArea rather than a GobState and so. But I actually do like it :P

Eh oui: c'est encore un post avec des captures de débuggeur, du code assembleur, des chiffres sur la DS et des tas de gribouilles sur un bloc de feuilles: c'est la saison des guru meditations. Le fautif cette fois, c'est Inspector Widget, qui se met à regarder dans des zones mémoires invalides dans certaines situations. Dont la situation que je voudrais bien essayer pour vérifier une stratégie pour améliorer la branche-qui-rebondit. Parce que le tuning ne convainc définitivement pas.

Hopefully my "blue screen of death" isn't that dead and I can navigate almost freely in the DS's core memory to follow pointers and such. Hopefully, too, the bug I encountered last week-end wasn't too hard to reproduce. Well, you have to pick a specific sprite (the bouncing tree branch), give it the debugging focus, activate its passive collision box, then activate Bilou's collision boxes as well and frame-step the game until they collide again ... but at least I was doing that intently last time the bug happened.

Mais cette fois, j'ai été attentif à profiter du plantage sur la DS pour partir explorer la mémoire et prendre des petites notes sur un bloc-notes. Repérer les addresses du code sur la pile, prendre le début des différentes structures pointées par les registres, etc. 

ça n'a pas suffit, malheureusement, et je n'ai pas pu reproduire le bug dans l'émulateur, mais au moins cette fois-ci, je savais comment il était apparu et je pouvais le reproduire sur DS. Donc, recompilation, synchronisation des montres exécutables, petit passage par le stick WiFi et je me retrouve avec un setup de méditation digne de ce nom: la RAM sur l'écran bleu de la DS, le code désassemblé dans mon terminal, et un émulateur qui tente de reproduire le problème grâce auquel je peux vérifier des hypothèses comme "le 116eme byte à partir du début du GameObject, c'est le pointeur vers le GobState. Si c'est bon, le devrais y voir 0x0206c16c qui est l'adresse de la table virtuelle de la classe GobState".

But at least, I could upload a recompiled runme.nds to my DS over my wifi stick and have hex numbers that can be directly used rather than playing match-three between .elf debugging in ddd and hex numbers on the NDS. And yeah, that implied graph paper, writing down values, annotating assembly code with registers values and the like.

All of this to figure that I was missing a test against NULL somewhere in the Inspector Widget logic. and then I feel like a hunter coming back with some evaded cows, proud to bring them back only to be welcomed by his relatives frowning, with their arms crossed and a look saying, "Well, maybe if you were paying a bit more attention when crafting fences, we wouldn't have to hunt after our own cows every 3 weeks ! ..."

Anyway ... that was part of an attempt to see whether I could make Bilou better follow the branch position in a new "soft-land" state and it turns out that it will take more effort before it starts working.

Sunday, July 21, 2024

map poked!

map.poke is done. Okay, it doesn't read "map.poke" in the level script but rather block (coordinates) = (hex) so that it mimmics the block (hex) { ... } definition. And that makes it specific to special blocks.

But there it is. After some branches untangling and more commits weaving, I could use it to add a secret exit in the trunk of the 'greent' room without having to go through the now-clumsy steps of patching the level on NDS while editing code on the PC.

Bon, je crois qu'il n'y a pas besoin que je vous dise que quelque-chose n'a pas marché, hein ? vous vous en doutez rien qu'en regardant l'image... En mars, j'avais évoqué la possibilité de reprendre les vieilles maps pour étoffer un peu "Dreamlands" (ou à tout le moins, proposer un peu plus de contenu pour la démo "3 rooms"). Et bonne nouvelle, j'avais fini par retrouver les maps en question. Je m'étais donc rajouter un peu de script qui dise "alors, le bloc de type 11, c'est une sortie secrète, et dans le niveau greent (le nouveau), si on la touche, tu charges le niveau greeny (l'ancien)". Sauf que pas moyen de tester, évidemment, parce que sur greent.map, il n'y a aucun bloc de type 11...

C'était donc l'occasion de se bouger un peu et de coder le mécanisme dénommé "map.poke", à savoir permettre au script d'aller modifier les propriétés d'un bloc du niveau sans rien demander à personne (et en particulier pas à l'éditeur de niveaux ;P). Et oui, la vie est telle qu'il m'aura fallu un bon mois pour que ces malheureuses lignes de code finissent compilées sur le PC qui avait aussi le fichier greeny.map ce matin. Tout ça pour se rendre compte qu'avant de pouvoir faire une "release" avec la vieille map n°1, je vais devoir lui faire un sérieux ravalement de façade pour l'adapter au nouveau tileset ^^"

Oh I presume you don't really recognize the big tree of my so old two-levels demo: since I re-structured the tileset, there are quite some editing to happen there before you can actually enjoy anything :P

Saturday, July 06, 2024

Test tile type from state transition

As I update an old post to explain that yes, cando() finally managed air/water transition I note that the whole blog is still missing a key explanation of how this was made possible. It happens in state machine transition expression (in the predicates, actually) and says "tell me the properties of the world n pixels above my hotspot".

$FALL->$INWATER on fail [2 H WATER ?]
                        (v1 v5 + 2 / :1 0 :5);

$INWATER->$RBOUNCE on event0 [D_FOOT 8 H AIR ? &]
                        (800 ~ :1);

You see it there. H is the new OP_HOTTILE for the GobExpressions. it picks the value on top of the stack, the constant 2 or 8 here. We can then test bits against the constants WATER or AIR with the ? operator.

Without that, the trick about a slice of tiles that are both water and air is useless, because you couldn't make the difference between falling into water and falling on the ground anyway.

(and yeah, I still have to add those get-worldwide-flag and set-worldwide-flag opcodes as well as the roll-the-dice opcode)

Saturday, June 22, 2024

map.poke

I will try to get energy again for DS development. Not that I have dropped any Bilou-related activity, but I would like it to lead to code, and not just sketches. One of the last notes I wrote were about live-patching the map from scripts. That was before going on short vacation and no, I did not have my source code along this times (kids have grown up ;)

I know I've been tempted to dismiss it as "not so important", "low priority", but then I realised: if I want to start working on new controllers like "hanging" or "between", I will likely need special tiles to use them. And if I have to go for a full power- NDS- wifi stick- NUC- emulator cycle every time I need a new tile somewhere, I'll never be done. (proof: it's been two month and I haven't done that a single time).

I already have methods in the FlatWorld class that could take care of updating graphics and physics layers as needed. The thing that has been holding me back so far is the fact that this class isn't reachable from ScriptParser.

But well, things aren't as bad as I thought: GameScript keeps a physWorld reference to the objetct that has the desired interface. We're just one getWorld() call away from being able to implement map patching...

Once I'll have the a tile flagged as "hang here", I'll give a try to a new Hanging state ... Even without fancy swinging animation, it should already take us much closer to the gameplay I want for "dreamland"...

edit: just as I was checking the state of my working folders, I found the old maps I had considered merging into the current demo. So I went on and coded a 'secret exit' special block that could send us to one such old map ... And haven't tried it yet because I of course don't have any block of that type on my map ^^"

Wednesday, May 29, 2024

SMBW: flying hazards

J'avoue que quand Mario Wonder a été annoncé, ça ne me gênait pas trop de devoir attendre 3-4 mois que mon frangin me l'offre. Quand je l'ai essayé chez lui, il était déjà au monde 2 ... la prise en main était plutôt agréable.

Mais en voyant les pikdors j'ai su que j'avais là une pépite de game design dont je blogguerais encore des années plus tard. Et en particulier que ce jeu allait peut-être apporter les références complémentaires dont j'ai besoin pour ma "peak zone".

I wasn't very hyped by Mario Wonder until I played the level with the condarts on my brother's switch. Then I knew behind dubious decisions, I had a pure gameplay gem in hands.

Granted, it's not the first time you see some ennemy breaking things in a (new) Super Mario Bros game, but the diversity of the design patterns they used with the condor-darts was brilliant. By that time, I was somehow in a dead-end with Peaks Zone design, especially monster design, and that Super Mario Bros Wonder might be the inspiration I (deseperately?) need to reboot my creativity.

Il faut dire que des ennemis volants, j'en ai déjà envisagés quelques uns, mais rien qui ne soit suffisamment convaincant. Bon, en soi les picdors n'ont pas un comportement si différent des mini-necky de Donkey Kong Country, juste qu'ils sont dans un Mario et viennent s'ajouter à la liste de plus en plus longue de briseurs de briques du dernier jeu SMB*.

Pourtant, le fait qu'il soient aussi utilisé comme une variation des thwomps m'a finalement donné envie d'avoir ... bin juste des plumes qui attaquent Bilou. Un clin d'oeil aux "esprits volants" du tout premier univers parallèle de mon frangin ;)

Et ça reste dans le thème de la planète bizarre. Vu l'effet que les "corbeaux" d'Ori m'avaient fait, ce sera précieux.

One of those patterns was thwomp-like behaviour but where the bird moved sideways horizontally so it wouldn't necessarily always hit the same place. That also means you may try to lure them and have them hit a target you're interested in.

And so I came up with that little sketch of a feather-eye ennemy that could hover out of jump reach and attack when the player is spotted. Nice, although, I don't think it would work with the "use as lift when it moves back" or "use as extra cliff while it is stuck into the wall" patterns.

And then I came back to the old menacing bird design of 2021, the one that has Bilou-compatible shape (I don't want the peaks zone baddies to be "just birds", they also have to fit the planet's theme) and found a fun way to make it fly. That dude could attack and move quite freely in the sky, be attracted away of its resting position, get stuck in walls and all.

Ah, et oui, pendant que je préparais tout ça et que je suis retombé sur mon espèce de vautour à tête de ptérodactyle (c'était l'idée), j'ai fini par trouver une manière rigolote de lui faire prendre les airs qui ne demande pas d'en faire un modèle 3D.


Saturday, May 04, 2024

Goodboy('s geyser) was here

J'ai quand-même commencé à tenter de dessiner un jet d'eau. J'avais lancé un appel sur twitter, pour essayer de trouver des références. Il faut dire que les cascades de l'époque 16-bit étaient encore plus convainquantes que les jets d'eau de la même période.

J'ai eu une réponse en or, du genre de celles que j'ai eues pour les arbres l'an dernier. Le temps de faire le point, et je vous raconte tout ça ;)

"I can't draw convincing water jet from below" did not sound like a very convincing reason for not using a water jet if it is the proper game mechanic to use. I finally have a good one to pixel study and started doing my own, as you can see on the photo, but allow me to rewind and start where it started.

Un pas en arrière pour revenir à l'époque 16-bit. On préférait souvent éviter d'avoir de trop grosses animations à gérer sur ce genre de machine, et animer de l'eau se faisait généralement avec un dégradé et une modification cyclique sur la palette de couleur (palette cycling). Le foncé devient blanc pendant que le clair devient foncé, le très clair devient clair et le blanc devient très clair...

Back in the 16-bit era, it was frequent to do color cycling to animate a waterfall. Sometimes it worked nicely, sometimes it was so-so. It works best if the raster is long enough and if the animation speed remains movie-quality. At cartoon-12fps, you start seeing as flashing more than falling down water.

But you'll note the bottom of the waterfall is often missing in those scenes. And when you look at the few game art that tried having upwards water jet, you understand why: it no longer works. We expect water to become darker with density increase. In a waterfall, vertical density variation are interpreted as downwards waves, but when water eventually widens up in a fountain-like mushroom cap, it is always more dense at the center and less dense on the "edges". If you do palette-cycling here, you break that.

ça donne une illusion potable de cascade, pourvu qu'elle ne soit pas trop grande et que la vitesse d'animation soit réglée au millipoil. Et si possible, utilisez plus que 4 couleurs pour le cycle, parce que sinon on se retrouve avec quelque-chose comme le décor de Yoshi's Island qui tient plus du clignotement que de l'écoulement d'eau. 

Et malheureusement, la même stratégie est appliquée dans les (nettement plus) rares jets d'eau de l'époque. Je dis "malheureusement" parce que pour un jet d'eau, on va forcément devoir aussi animer le "chapeau de champignon" qui va avec, pour lequel la surface animée est encore plus grande. Et l'effet clignotement encore amplifié. On l'a déjà dans Bubsy, où les pixels isolés clignotants ne parviendront pas à faire oublier le fait qu'ils sont statiques. On l'a dans le final de Link's Awakening et dans le jet d'eau d'un jeu obscur avec la mascotte du Mac Do.

In Bubsy, for instance, the artist sprayed out the water pixels as the water starts falling down. This is coherent with the style, but animating them will just give you blinking static pixels of water. And the stylized 'mushroom cap' used in Link's Awakening and Mac Do game flashes even more aggressively.

Là où ça coince tout particulièrement avec le "champignon", même quand on évite les pixels statiques, c'est qu'avec ce type d'image, le clair et le foncé ne sont plus interchangeables. On voudrait que le bord soit plus clair parce que l'eau y est plus éparpillée. Faites-y du palette-cycling et vous aurez des images qui donnent l'impression d'être en négatif.

J'avoue que je trouve un peu dommage qu'avec les resources graphiques de la SNES, on en soit réduit à ça pour animer l'eau. Mais il faut reconnaître qu'en misant tout sur de la RAM vidéo, la console n'a plus la possibilité de reprogrammer les plages d'adresses (bank switching) pour faire des "animations gratuites" comme la génération 8-bit. Toute animation va impliquer un transfert DMA vers cette VRAM et le budget pour ces transferts est limité (comme toujours).

Truly, the "cap" of the fountain/geyser needs dedicated animated tiles, but we're unlikely to see that on 16-bit engines. 8-bit machines could have done that with more ROM and evolved mapper chip, but 16-bit consoles no longer try to pull pixels directly from the ROM. They put them in dedicated video RAM, and rely on DMA channels to bring animation frames in due time. But the amount of pixels you can transfer per frame is limited. Animating Bubsy's geyser that way at 60fps would consume 25% of your animation power:

On NTSC with overscan mode turned off, there are 262 - 224 = 38 scanlines in vblank. Subtract one scanline for prerender time, and you may end up with 165.5 * 37 = a smidge under 6 KiB per vblank.

6K, sur SNES, c'est 46 blocs-question de Super Mario World. Animer quelque-chose de la taille de la fontaine de Bubsy à 60fps, ça demanderait donc 1/4 de la puissance dans la partie critique du moteur de jeu.

Bon, et après l'époque 16-bit, alors ? Du côté de Super Princess Peach, par exemple, qui est plutôt réussi côté pixel art ? Un jeu ou pleurer est une mécanique de jeu, il doit bien y avoir des jets d'eau dedans non ? 

So, well, my game is not for a 16-bit system anyway, so could there be any water jet pixel art for 32+ game that I could study instead ? Say, in Super Princess Peach ? A game where you cry waterjets sure should also have some geyser-like elements, right ?

Well, it does indeed, in Wavy Beach 2. It uses a "cone" of water that might be animated through color cycling plus a "flower" top that follows the rule "keep the center dark and the edges light". But even then, I don't find it appealing, and I don't see how I could make it match anything but the super-stylized environment of SPP.

Eh bien oui, en effet. Dans le niveau 2 de la plage. Mais je dois bien avouer que je ne suis que moyennement emballé par le style. On a un premier élément (le cône) qui utilise un effet de palette qui ne fonctionne pas trop mal, les traîts latéraux restant sombres en permanence. Puis on a cette "fleur" qui grandit et rétrécit, gardant toujours le sombre au centre et se permettant des éclaboussures au bord des "pétales" sur la dernière frame.

Mais ... bof. Même en corrigeant le truc pour que la princesse apparaisse par-devant la fleur, ça ne me convainc pas. Oh, ça marche plutôt bien avec le reste de l'esthétique stylisée de SPP, mais ce type d'animation dans Bilou ? Pas convaincu.

Et depuis ? Parce que bon, le modèle pour la cascade de Bilou, il ne date pas de 2005. Mais le truc, c'est que j'ai surveillé les cascades en pixel art pendant pas mal d'année, sachant que j'en aurais besoin tôt ou tard. Alors que des geysers, c'est plutôt un truc de dernière minute.

Et c'est là que hot_pengu, l'auteur de Goodboy Galaxy, m'a pointé vers la vidéo de son jeu sur GBA

And so I finally asked hints to people on twitter who might have seen something I could use as a reference, or ever proper keywords to search for one, and to my surprise, I received an answer from indie game developer hot_pengu:

We call it a 'geyser' internally for goodboy, and this (timestamped vid) is how we represent it.

Je jette un oeil, je prends un petit screenshot pas fou mais qui pourrait donner un point de départ, et là,

Here's a better look, if it's useful! (there's two versions, one comes out of a monster)

He added as I posted a quick snapshot for future pixel study, handing the Goodboy Galaxy spritesheet with 2 sizes of exactly-what-I-needed material that you see printed on the top photo. 6-frame stunning animations, with tileable base and stylish top. Even the style isn't that different from the one I have for my waterfall!

Une animation pixel-art moderne, tout en fluidité et utilisant bien les 6 frames, qui peut être étirée en hauteur comme on veut ! C'est celle que vous avez vu tout en haut de cet article, imprimée et que je suis occupé à étudier. Parce que là, j'ai bien mieux qu'une référence pour donner une seconde chance au cas du bouchon: j'ai une idée.

Voyez, ce geyser, je peux le placer au fond du trou, directement, sans avoir besoin de bouchon. Il bouge, il attire l'attention. Pas moyen que le joueur ignore sa présence. Il a un look quelque-part entre la plate-forme et le bumper ... on pourrait toujours sauter dessus, on ne sait jamais. 

I like how it simply requires the player to hop into the proper spot to trigger. Much cleaner gameplay than the "pull the cover" I had thought about, but it remains interactive. Plus, by being already flowing before we interact, there's no more questions about "where does this water comes from, where does it goes afterwards", etc.

Deuxième bon point, une fois que Bilou a sauté dessus, je peux réutiliser le type de comportement que le joueur rencontrera plus tard avec Inkjet: Bilou reste "coincé", la pression s'accumule et wouf! on est projeté vers le haut.

And that would match the way 'inkjet' monsters will lately be used as delayed bumpers in the School Zone ... Since this game will no longer feature a welcome screen with the inkjet, it's a good thing the player can be shown early what happens after the "caught in a boiling pot" animation.

Et si il a raté son premier saut, il peut retomber sur le "chapeau" du geyser et re-sauter de là.

Mieux encore: si le joueur n'est pas resté dans le geyser jusqu'à être projeté, on peut le pousser vers le haut s'il entre en contact avec le "pied" du geyser. Et si rien de tout ça ne se produit, on peut directement réessayer la même manipulation. Pas de risque d'aller se coincer en nageant, de faire redescendre l'eau trop tôt ou quoi que ce soit de ce genre.

Bref, j'avais pensé vous redessiner *mon* geyser sur DS pendant la petite semaine de vacances, mais au final, j'ai juste eu le temps de faire une petite feuille de notes pour illustrer ce que j'imagine comme mécanique avec mon geyser ... parce que les vacances d'une famille 11 + 15, ça ne ressemble pas vraiment à la dynamique 8 + 12 et ses plaines de jeu à surveiller :-P

I expect that the platform-look of the geyser top will invite even the younger players to jump on. I expect that its animation will catch their attention much more than a purple block or handle. Should they fail to use the bump effect to reach the key, they can be caught by the platform-top and jump again. If they jumped out before the geyser happened, they can jump into the flowing geyser and be pushed up to the platform-top. It's flawless ^_^

Now I just need to find enough time in the upcoming evenings to complete it ^^"

PS: if you want to animate something like that, consider animating it without the vertical motion first: just the wobbles and the sparkles, and only then apply the vertical shift to each frame. Unsure I will follow that advice myself this time.