Showing posts with label appleman. Show all posts
Showing posts with label appleman. Show all posts

Saturday, July 18, 2026

The July Demo

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

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

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

Sunday, June 14, 2026

Funghi vs. Appleman

Funky Funghi, un des plus anciens personnages de la Green Zone sur DS, vient de se ramasser une pomme. Jusqu'il y a peu, la pomme serait juste passée à travers, mais alors que ce blog va sur ses 20 ans d'existence, j'ai rajouté les quelques lignes de code script qui manquaient pour que l'interaction proposée début 2022 devienne une réalité: on va pouvoir dégager les champignons du chemin à coup de jets de pommes.

Throwing apples around is a bit more fun since they've started rolling when hitting the ground, but one thing has felt odd so far: seeing the appleman crossing the path of a bouncing Funghi without triggering any effect. Since early 2022, I had the idea that we could have Bilou *bouncing* when hitting the hat of Funghi rather than being hurt, and that implied of course that a thrown apple should bounce as well. It was now time to implement that.

Post by @PypeBros@mastodon.social
View on Mastodon

Ah, and yeah, I've played a good deal of the original Rayman, including throwing fist at bouncy plums and yin-yan balls to make them reach the place I wanted them to be. With all this new bounciness, Funghi is no longer just a hazard and you might actually want him to be *somewhere* rather than just wanting him away. Some of the initial ideas -- such as having the hat deflecting apples and only the foot being the target to hit if you want him moving -- quickly proved unpractical, and uselessly tricky to do, especially for a World-1 interaction.  

Bon, j'avoue que comparé aux "prunes rebondissantes" de Rayman, on est sur quelque-chose de nettement plus détendu: Funghi ne risque pas d'aller rebondir contre un mur et de revenir vous écrabouiller. Il ne reçoit que la moitié de la vitesse de la pomme et ralentit de moitié à chaque rebond. Juste ce qu'il faut pour passer d'une souche à "entre les deux souches" en une pomme. Mais ça devrait être marrant quand-même vu qu'il y a moyen de ramasser à nouveau la pomme et de la lancer une fois de plus. D'autant plus que maintenant, il va aussi être possible de rebondir sur le chapeau de Funky Funghi! (c'est peut-être encore un peu fort, d'ailleurs).

Post by @PypeBros@mastodon.social
View on Mastodon

La solution à laquelle je suis arrivé à coup de débuggeur d'expression est un rien intimidante ... entre autres parce qu'elle dérive de la collision destinée à faire rebondir Bilou, et que pour Bilou, je voulais que l'angle change selon qu'on arrivait plutôt sur le bord ou sur le centre de Funghi, comme s'il était vraiment un bumper de flipper. Pour ça, on va préparer deux valeurs et les combiner avec | dans le byte haut et le byte bas d'un entier 16-bit avant d'écrire le tout dans la 10e variable de Funghi avec :a. C'était rigolo avec l'appleman, mais ça devenait compliqué d'y ajouter le transfer d'énergie ... donc au final, pour l'appleman, Funghi agira toujours comme un mur qui absorbe 50% de sa vitesse horizontale et n'a aucun n'effet à la verticale. Et sur l'énergie absorbée, la vitesse acquise par Funghi est moitié moins importante que celle qu'avait l'appleman ce qui nous permet de calculer qu'un Funghi pèse à peu près 2 Applemen ;P

state0->state0 on found$apple [C_THROW we 0 >= w0 0 < & &]
                  (w0 2/ ~ $ff00 & w1 256 / $ff & | :a w0 4/ v0 + :0)
state0->state0 on found$apple [C_THROW we 0 < w0 0 > & &] 
                  (w0 2/ ~ $ff00 & w1 256 / $ff & | :a w0 4/ v0 + :0)

I ended up with something simple for Funghi/Apple interaction: half of the speed of the appleman (w0) is transferred to Funghi, and the other half is bounced back. But since Funghi is bigger, the half it takes only result in 1/4th of the speed. Not pushing him very far, I'm afraid. And well, that's only the part w0 4 / v0 + :0. All the things that happen before are reusing the "protocol" defined for throwing things where the thrower decides of the direction of the thrown object I already used for dumblador. The X speed and the Y speed will be set in the 10th register of funghi with :a and later used by the appleman with

$RTHROWN->$LTHROWN on hit0 [C_THROW wa 0 < &] (wa $ff00 & :0 wa 256 * :1)

Mais dans le code de l'appleman, j'ai quand-même gardé un code générique qui se contente d'appliquer le vecteur-vitesse qu'il trouve dans la 10eme variable de ce qu'il a heurté. ça pourra me permettre par la suite de faire en sorte que les branches rebondissantes puissent elles aussi renvoyer les applemen ^_^. Petite subtilité: la transition hit de l'appleman est testée avant la transition found de Funghi mais c'est found qui fournit le vecteur vitesse que hit va utiliser. c'est pour ça qu'il y a un test qui s'assure que wa < 0, pour que lors de la première frame de collision, l'appleman conserve sa trajectoire pendant que Funghi calcule l'impact. A la 2eme frame, wa est défini et la trajectoire de l'appleman pourra changer.

Et pour la collision Bilou/Funghi, c'est la distance entre le centre des hitbox (we) qui va déterminer l'angle de l'impulsion que Funghi va nous imposer, entre (-3,0), (-2,-1), (-1, -2), (0, -3) 

The idea inintially was to use the same behaviour as the one I coded for Bilou, where the angle you're bounced depends on the position you hit Funghi on. That's decided in Funghi's script with

state0->state0 on found$bilou [C_THROW we 0 >= &] (we 4/ 256* we 4/ 3 - $ff & | :a)

where we is one of the collision-specific parameter (rather than an internal variable of the collided object) containing the center-to-center distance between Bilou and Funghi, ranging from -24 to +24. At the very edge of Funghi, you'll get bounce horizontally by (+-3, 0), and at the center of his hat, you'll be bounced by (0, -3). In between, you could get (+-2, -1) near the edge and (+-1, -2) near the hat. And yup, it's got the overall expr_1 256* expr_2 $ff & | shape again to put both together in a single variable.

I still had to do something for how static Funghi looks when hit by something. My first attempt failed because transanims with characters that are made of a single sprite, and so far, Funghi was still like that. But behold, Funky Funghi 2.0, remade in AnimEDS after I separated hats and feet, so that I can animate it more freely, at in-between frames of some sort, etc.

It doubles the amount of memory it takes, but I think it's worth it. 

Il me restait un truc à régler: Funghi donne l'impression d'être en béton et que rien ne peut lui arriver même quand on rebondit dessus ou qu'on lui lance une pomme. J'aurais bien essayé de réutiliser l'animation "rebondit au sol" dans un sens ou dans l'autre, mais Funghi est toujours un "SimpleGob" premère génération, et je ne leur ai manifestement jamais ajouté le support des transanims.

Je profite donc de la p'tite canicule du week-end pour redécouper un peu Funghi dans le Sprite Editor, refaire ses animations dans AnimEDS et rajouter un "fait rebondir un truc qui arrive du haut" ainsi qu'un "fait rebondir un truc qui arrive sur le côté". Ce n'est pas spectaculaire, mais ça donne plutôt bien quand-même.

Saturday, April 11, 2026

Better THROWN->ROLL transitions

 Since the introduction of the appleman ROLL mechanics, there was something I couldn't completely fix: if you managed to throw the appleman straight into a "jump thru" platform, it would stop as if it was a wall, while you'd expect it to roll over the platform or fall through it instead.

I envisioned a number of solution to this problem until I realised there was one quite obvious one: just bounce the appleman upwards a little bit when that happens. It will then be able to advance sufficiently into the platform so that it is then in the normal "thrownroll" transition. If instead it was thrown into a solid wall, the bounce will be visible, but have no lasting effect

Au début, ça ressemblait à un petit détail: au moment de se mettre à rouler, un appleman pouvait se retrouver bloqué bêtement par un sol qui trainerait en l'air. Mais si, vous savez: ces plates-formes qu'on ne peut franchir que de bas en haut, mais qui vous retiennent quand vous allez de haut en bas.

Eh bien pour vous retenir, il faut qu'elle soient solides au moins pendant que vous tombez. Et à ce moment-là, elles ne font pas dans la dentelle: pas question de venir avec un "oui, mais non, mais regarde: en vrai je ne peut pas atterir, là: c'est juste le côté de mon haut qui passe de quelques pixels dans le bord de ton bas ... j'fais qu'passer, quoi!". Nada. Je me retrouve avec une pomme qui était lancée à vive allure et qui s'arrête nette sur un plan d'herbe à travers lequel elle passait sans problème quand vous la portiez sur la tê♪te, la pomme ♫ i' faut pas'l'nier.

And let's be honest: it would have been a nightmare to debug without the recently introduced GobExpression debugger. You can quite easily end up in a situation where you expect some speeds to have been non-null in some condition and realise that, well, no they're null here.

The alternatives I had envisioned were globally more complicated, like holding the speed for some time and then restoring it. More complicated in the sense that they required introducing new states in the behaviour or even new controllers. Here, it's just one extra transition that says "stay in THROWN state if {conditions}, but update velocities as follows"
 

C'était devenu un sujet de cogitation dans mon carnet, et un assez bon exemple de ce qu'on pourrait vouloir faire avec un contrôleur "around" pour contourner les obstacles. Au final, ça se passe de ce genre de complication: il suffit de redonner une petite impulsion verticale, juste assez pour que la pomme monte d'un demi-bloc et puisse atterir sur la plate-forme plutôt que de passer à travers.

Tout ça grâce au nouveau débuggueur d'expressions que vous voyez dans le bas de l'animation, qui représente chaque opcode par un caractère qu'on fait avancer petit-à-petit avec la touche L et qui complémente agréablement ce bon vieil Inspector Widget :P 

Sunday, January 25, 2026

Corrigeons l'appleman ...

Bien, j'ai pu un peu montrer l'appleman qui roule à mon frangin lors de l'anniversaire de J.L.N l'autre jour, et il avait plutôt apprécié. Surtout les interactions supplémentaires que j'envisage avec les autres ennemis du jeu.

We have rolling appleman now, and both my son and my brother do like it. But before I start adding all the fun interactions I envision (and they're awaiting) using that new mechanics, I have some clean up to do.

Mais avant de m'attaquer à ce genre de jeu, il me fallait d'abord corriger quelques étranges bugs apparus près de ces plateformes rajoutées dans le niveau de l'arbre creux en construction.

Le premier est un curieux alignement: au moment où la pomme commence à rouler sur une plate-forme à sens unique, elle se retrouve curieusement alignée fort bas. Comme si le bas des tiles était le sol, plutôt que le haut comme prévu. Ou comme si la géométrie de la pomme était beaucoup plus plate que ce qu'il faut.

Two bugs were requiring some attention. The first affected the ground height of the rolling appleman on jump-thru platforms. A quite perplexing thing which I expected to require tracking of coordinates and tile properties as the debugger would let me dig within some of the more complex functions of the engine such as "do_slopes". So I went on posting debugger screenshots as bread crumbles for a non-existent time machine. 

Post by @PypeBros@mastodon.social
View on Mastodon

C'est le genre de situation où je sais que je vais devoir regarder en détail ce qu'il se passe dans les fonctions do_slopes ou cando, parce que c'est là que se prendront les décisions. Et je sais d'expérience qu'il va me falloir une idée précise des coordonnées impliquées, où noter les résultat intermédiaire etc. 

Je suis donc reparti à me faire des petites annotations dans mon carnet et une série de captures d'écran du débuggeur qui me servent de machine à voyager dans le temps. Et on retrouve bien les deux problèmes: la bounding box definissant la taille de l'appleman grandit entre l'état "lancé" et l'état "roule", ce qui veut dire qu'il se retrouve automatiquement avec les pieds dans le sol. Mais en plus de ça, la hauteur du sol n'est effectivement pas correcte. Un résidu du passage au nouveau système de propriétés du décor qui n'avait pas encore été corrigé.

After numerous breakpoints and conditions and instructions stepping, after using a second emulator in parallel to figure out coordinates, check bounding box size and the like, I eventually noted that the height for a "direct" tile like those used for jump-through  is 0. That's intended for "look at what's beyond" when walking on some ground. That's fine for water or air or maybe even vines to be climbed. Not for any sort of ground. Easy to fix.

Now, the second one the appleman didn't pretend to enter the "jump-thru" platforms while being carried. That led to weird situation where it would push on Bilou, preventing him from even approaching the platform. Here the issue was in the properties we told the gravity controller to test for. It doesn't need to be AIR for the appleman to move through. In fact, anything the carrier could move through would be equally fine for the carried object. In the capture below, I only fixed the state when the appleman is facing right, so that gives you a nice fixme/fixed comparison.  

Autre effet bizarre: l'appleman ne voulait pas entrer dans ces régions "jump-thru" pendant qu'il était transporté. Un choix malheureux des propriétés recherchées qui insistait sur le fait que "ça doit être de l'air". En fait, non: partout où le joueur peut passer, ce qu'il transporte doit pouvoir passer aussi.

(la petite capture animée montre un état intermédiaire où j'ai utilisé ddd pour modifier les propriétés recherchées quand on est tourné vers la droite, mais pas encore quand on est tourné vers la gauche, pour vous faire un "avant/après" plus parlant)

Vous noterez peut-être dans ces petites captures un moment où Bilou se retrouve avec 4 mains. C'est le problème que j'avais cherché à (et cru) résoudre en Mai dernier ... manifestement, ce n'est pas encore complètement au point. 

Friday, December 05, 2025

Funnier Apples

Depuis le début de mon carnet en cours, j'ai un objectif "rendre les pommes plus fun". ça passera par des interactions révisées mais aussi par des compléments d'animation. Entre autre, quand on lance un appleman et qu'il arrive par terre. Le comportement actuel est tiré de dumblador, qui glisse légèrement sur les surfaces planes de l'école avant de s'immobiliser assez rapidement.

Finally! that little sketch of an appleman rolling away when hitting the ground has been teasing me for month at the start of my notebook, but now I've finally sketched something in AnimEDS. Hopefully I could try to integrate it in the prototype this week-end.

It should trigger when you've thrown an appleman and its hitting the ground. The current way it slide for a few pixels before settling feels incompatible with the spheroidal nature of an apple but I still have to decide whether it will bounce-roll or just roll. Likely "just roll" will work better with slowing it down. Or maybe it should just keep rolling until off-screen or stopped by a wall ? 

Mais soyons clair: ça ne donne rien de convaincant avec une pomme sur le sol de la forêt. D'où l'idée que la pomme roule un peu en atterrissant ce qui 1) est fun et 2) lui donne un peu plus de portée qu'un projectile classique, ce qui est toujours le bienvenu dans un monde 1.

Alors tant qu'à faire dans le fun, on pourrait même laisser rouler la pomme jusqu'à ce qu'elle rencontre un obstacle, non ?

(En tous cas,  J.L.N approuve ... et apprécie le fix qui évite à Bilou de se retrouver figé dans un mur pendant qu'il nage) 

edit: The pull mask feature should allow me to make eyes and stem either in front of or behind the apple's "body" more easily. I had forgot it exist and made a messy animation where sprites are swapped, which makes it blink in the editor ^^"

Now, that simple animation opens up a lot of new options in terms of gameplay and interplay. What happens if an apple rolls into another apple ? and into a bopping funky funghi ? 

Game design brainstorm from 2022 suggested that you could "push" a funghi by throwing an apple at him when it's mid-air, but shouldn't it bounce the apple back at you if he's grounded ? and what if you're hit by an apple that's rolling back at you ? shouldn't that hurt ?

That starts making the appleman looking a bit more like a koopa and a bit less like a goomba, doesn't it ? My brother even suggested that it could be the core mechanics of a dedicated puzzle game ^_^

Ah. None of these are available yet, of course ^^"

 

Saturday, May 31, 2025

May the demo be with you

Well, I can't really call it "a release", but there's something new waiting for you to download it on sourceforge: an update of the "three rooms" demo with more Applemen.

Stomp them, stun them, pick them, throw them. I won't claim that they're working flawlessly, but at least they're working, compared to the many attempts that took place last month.

It should also allow you to try the water jets and the hooking mechanics if you manage to find the "hidden" second green zone "level". And if my records are correct, this is also your first opportunity to face Bangbash yourself, because last demo was last year, just before I started working on making it move!

Oyez oyez! voici un nouveau fichier téléchargeable pour explorer vous même toutes les petites mécaniques de jeu qui ont fait le buzz lors des "Screenshot Saturday" de ces derniers mois! Ramassez et lancez des Applemen ! Défiez Bangbash ! Bondissez grâce aux branches, aux jets d'eau ! Accrochez vous aux racines !

La dernière fois que vous aurez eu autant de fun, c'est quand vous étiez dans une plaine de jeu !

Parce que, bin, on ne va pas se mentir, ça reste une démo-plaine-de-jeu pour vérifier que les mécaniques principales du futur "Bilou Dreamland" fonctionnent bien sans devoir traverser un niveau de 2048x1024 pixels pour s'en convaincre. Mais ... mais ça pourrait bien changer prochainement. 

Vous allez voir qu'il y a encore plein de petits détails pas au point, surtout s'il vous vient l'idée de lancer des pommes dans l'eau. C'est assumé. C'est parce que pour la prochaine démo, je vais me faire une version "brouillon" des niveaux qui sont déjà dessinés histoire qu'on puisse voir ce qu'ils donnent avec la physique actuelle de Bilou. 

Tuesday, May 20, 2025

GobExpression debugger

Throwing apples does not work the way they should. There are likely bugs in the state machines transitions, and -- once again -- they are tedious to isolate. So here a screenshot of a first step towards a tool that would let me step through guards and actions at bytecode level.

The colored line just below shows those opcodes, one character at a time.

I've got such bugs to fix in the past, of course, but that's always been a pain. InspectorWidget can only break when a specific transition is taken, but not before its guard expression is evaluated. And something in my C++ code prevents gdb from stepping through the expressions evaluation function.

Juste avant de partir en vacances, j'ai fait des petits tests avec des lancers de pommes, mais il faut reconnaître que ça ne marchait pas comme prévu. Et faire du debugging de transitions, avec les outils actuels, c'est le truc le plus pénible (en dehors des 'guru meditation', peut-être). Il était temps que je m'attaque à un "side-project" esquissé pendant les valises: un véritable bytecode debugger dans lequel on sélectionnerait son expression comme si on explorait des adresses mémoire: n° de gob, n° d'état, type de transition puis choix de la transition.

On aurait ensuite la possibilité de mettre des breakpoints au niveau "instrution", mais aussi de faire du step-by-step dans les expressions pour voir si l'évaluation se produit comme prévu ou non.

La capture d'écran ci-dessus vous montre bien qu'on en est qu'au tout début: faire en sorte de pouvoir utiliser les caractères programmables de la DS pour pouvoir renseigner 'constante n° 2' ou 'décaler de 3 bits vers la gauche' sur le même espace qu'un des caractères ASCII.

So far, it's really the first baby steps: video mode switching and character reprogramming so that opcodes can each be shown on a single 8x8 character. Part of them could fit within the extended ASCII range, but there's some room consumed right after that for the 'screen maps' themselves, that cannot be assigned to any character.

But the idea is to half a screen of these expression, see a cursor step as you press the 'forward' DPAD direction, see the stack fill, the reads and writes from object variables, etc. Long is the road ;)

I don't want the expression evaluator to be slowed down by extra tests, so I'll do the kind of tricks 8086 debuggers were doing: inject breakpoint opcode at the next instruction and remember what was there instead. Next time the debugger is invoked, it will restore the saved opcode, show us the new state and tell the expression to retry current instruction when we give a green light.

Wednesday, April 23, 2025

appleman 2.0.1

A little bit of work on the Appleman last week-end (at last, you could add and I wouldn't blame you). I've got the "shocked" animation revised, added "carried" animations and gathered infos about where these are in green.spr.

I'll still need to see why there is no "bounce" when it is shocked (reason: it's just using stopper and the animation is supposed to do the job) and patch the greent.cmd level script on the SD card of DarkneSs, because it still show the appleman with big purple punches instead of feet. (appleman.cmd must be correct, since level 2 doesn't seem to have any similar issue).

Voilà donc enfin le moment que je prends pour compléter les animations et le comportement de l'Appleman pour le projet Dreamland. J'ai corrigé l'animation "étonné", j'ai ajouté les animations "transporté", tout ça attend dans un petit fichier green.spr le prochain passage du WiFi. Je note au passage que le fichier "greent.cmd" qui décrit le premier niveau des "3 salles" a besoin d'un petit rectificatif pour ne plus me montrer un appleman aux poings mauves ^^".

La prochaine étape sera d'ajouter les animations des "pieds perdus". J'ai aussi retiré la commande de boucle pour l'animation "assommé", mais j'arrive trop tard: c'était bon pour compléter le comportement "Apple Assault" où les applemen se réveillent seuls, mais c'est inutile pour le comportement construit à partir du fichier "blador.cmd". Car oui, le nouvel appleman est plus ou moins la fusion des deux.

So let's add tonight "undead feet" animations, check a "do not loop stunned animation" that must be over 1 year old in my notebook. I've got another notebook where I've written down blador's behaviour ... let's merge that into appleman's script and we'll cleanup the resulting code mess once the home mess is tidied up.

edit: adding the wandering feet turned out extremely annoying. They're one-sprite objects, unlike most of the things I animate with AnimEDS, and it seems the software still handle that in a very different manner: touching an sprite in the side panel adds a frame with that item, rather than changing the current frame. It also breaks relationship between timeline, frame editor and buttons in general. I'll have to get that fixed: it really breaks the user experience...

edit': pick up works, stun works, wandering feet work. Apple/water interaction is a catastrophy, throwing only work from times to times, and there's something odd when you stomp on a stunned apple (blador acted as a platform there, appleman won't). That feels like it should roll instead ... A good thing animation 2.0 freed some frames ;)
 

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.

Saturday, August 26, 2023

Apple Bop ?

Une pomme qui vous fonce dessus, ça fait mal. Forcément. Une qui vous tombe sur la cafetière également. Surtout quand elle est aussi grande que vous. Si vous lui tombez, dessus, là, c'est elle qui tombe dans les pommes. En disant ça, j'ai couvert 75% des interactions possibles entre Bilou et les Applemen dans Apple Assault.

If you get an apple on your head, that hurts. If you're thrown an apple in the face, that will hurt too -- especially if the apple is almost as large as yourself. Chances you won't get hurt if you stomp on an apple while falling but that will likely do the apple no good. All these cover 75% of the interactions between Bilou and the Applemen in Apple Assault.

Now, what if Bilou run into an apple. Should he still get hurt ? I know it is the default behaviour in platformers: if Mario runs into a koopa, it gets hurt no matter what direction the koopa was facing. You can only kick a koopa shell if you stomped the koopa first. You can create stories about it like "yeah, as you kicked the koopa, it clawed to the ground, turned back so fast you couldn't react and bite you. You're dead", and by '86 standards, they would work. But does it mean we should continue like that ? Can't we find something more fun ? It's an apple, after all. It's not all covered with deathly spikes!

Mais si c'est Bilou qui arrive dans le dos de la pomme ? Est-ce que le choc devrait aussi lui faire mal (à Bilou) ? dans Apple Assault, la réponse est "oui". Dans la plupart des jeux de plate-formes, la réponse serait "oui" aussi. Un koopa qui bouge, c'est un blesse, qu'on l'approche par-devant ou par-derrière. Mais est-ce que c'est forcément la bonne chose à faire ? Est-ce qu'il n'y a pas moyen d'être plus *fun* que ça ? C'est une pomme, après tout. Pas une chataigne couverte de pics.
En plus, maintenant, il y a un précédent avec les Pendats de School Rush: on est blessé quand ils nous foncent dedans ou quand on tombe sur leur pointe. C'est plutôt logique. on est blessé aussi quand ils font demi-tour, mais de nouveau, vu la violence du mouvement, un mauvais coup est vite parti. Par contre, tant qu'on est dans leur dos, on pourrait presque les pousser, on ne se fait pas mal. Alors si c'est vrai avec des soldats, ça devrait aussi être vrai avec des pommes, non?

When you consider that, in School Rush, pendats -- despite their aggressive and spiky appearance -- will not harm Bilou (only block him) if he comes in their back, it would make the whole game more coherent if we would equally have the back of Applemen harmless. Plus, it could actually be pretty fun to see an Appleman slightly bounce forward on such a collision, as if Bilou had kicked him in the back while walking, and only then actually turning back, being surpised to see Bilou and finally attacking.

Voilà donc ce que j'ai envie de faire pour Bilou: Dreamland (et la green zone dans le futur): si Bilou bouscule un Appleman dans le dos, c'est l'Appleman qui fera un bond et Bilou ne subira aucun dommage ... dans l'immédiat. Parce qu'en revenant sur le sol, l'Appleman fera alors demi-tour et, voyant Bilou, lui foncera dessus (comme il fait depuis 2009). Ce qui n'empêche pas le joueur de sauter par-dessus l'Appleman, peut-être même suffisamment tôt avant que celui-ci ne se retourne, et qu'il ne se rende donc compte de rien. ça,, ça a le potentiel pour être bien fun ^_^

Thursday, August 11, 2022

Funghi v2.0

 Bon, il est temps que je blogge les cogitations de nouvelle année, vous ne croyez pas ? Je m'étais installé pépère dans le canapé pour récupérer un peu, agenda-cahier sur les genoux histoire de faire un peu le tri de ce qui doit encore être dit et ce qui doit être transférer dans la nouvelle année, mais c'était compté sans J.L.N.

Le p'tit bonhomme venait de se rendre compte qu'une SpongeBop, si on la repeind en vert, ça fait comme une branche d'arbre et que donc on pourrait en mettre dans la forêt! Il n'a pas tort, mais j'ai voulu vérifier ce qu'il connaissait déjà des autres habitants de la forêt de Bilou. Après tout, à part quelques parties de Apple Assault, il n'a pas encore eu beaucoup de contact avec la green zone.

Il y a Funky Funghi, notamment. Le champignon sauteur. Si je permets de ramasser les applemen à la manière des dumblador dans School Rush, que se passe-t-il quand on lance une pomme sur un Funghi ?

Sketches in this post were actually drawn on January 1st, while I was brainstorming Green Zone with my nearly-9-y.o. son. He's been mostly playing the School Zone so far, and only bits of Apple Assault. So little that he suggested I put a green spongebop as a spidey-branch platform of some sort.

At my first drawing of Funky Funghi, he'd almost immediately suggest that we can jump on his hat and use it as a platform to climb higher. Not a bad idea, but completely incompatible with the Commander Keen-inspired, decades-old setting where the whole funghi is highly toxic and that any contact should be avoided. But that was at a time where a Manic-Miner clone was considered.

L'idée de base, celle de la version BASIC, c'était que le champignon était ultra-toxique. Tiré assez directement de Commander Keen, je dois bien dire. Le moindre contact est dangereux pour Bilou. On ne peut même pas lui sauter dessus.

Mais bon, avec le recul, pour un premier niveau, c'est peut-être un peu exagéré. Je n'irais pas pour autant jusqu'à proposer que l'on puisse monter sur la tête de Funky Funghi et s'en servir comme plate-forme. Ce n'est pas franchement dans le caractère du personnage d'accepter ça.

Pas question non plus de permettre à Bilou de simplement 'pousser' Funky Funghi comme il le ferait avec un encrier (même si je n'ai toujours rien implémenté de la sorte ^^")

Faire se déplacer un ennemi sauteur invulnérable en visant correctement, voilà qui promet d'être fun. En tout cas, c'était fun dans Rayman.

I still would like to avoid a platform-like behaviour -- I even already have another mushroom design for that. And I now have throwable monsters in the rest of the game, meaning it would be good that we could pick up and throw applemen in Green Zone (that was the plan from long ago, before I came up with Apple Assault mechanics). That means something fun is bound to happen if you throw an apple at a funghi. Right ?

I bet being able to knock the otherwise-camping mushroom to an alternate location should be both fun and interesting (I take it from Rayman). But beware, said my bro: we don't want to end up locking the progression by poorly "chosing" where we put the funghi. And with an all-toxic one, chances that we lock ourselves are much higher. Especially with limited supplies of applemen in the level.

Mais contrairement à Rayman, on joue ici avec des "munitions" limitées. Il ne faudrait donc pas que l'on bloque un Funghi dans un coin du niveau où il peut nous empêcher définitivement d'avancer! Une solution pratique contre ça, évidemment, c'est de placer un 'trou à champignon' au bout de la zone-bac-à-sable dans laquelle il est prévu de le déplacer. Quoi qu'on fasse, il ne peut aller plus loin et on a remplacé "passer par-dessous l'obstacle" par "passer par-dessus l'obstacle", qui est en théorie plus accessible.

Final thought: if Edward is true claiming that goomba were picked mushroom-bumper-shaped because that should suggest the players they'll be safe jumping on them, making my bouncy-funghi hurt you when you stomp him won't be a neat way to teach the players they're in a traditional platformer when they're playing level 1 of Bilou's Dreamland. (not to mention that mushroom=bumper has been over-used in all platformers after that, to the point that it's almost more natural to try using them that way than trying to eat them and expect to grow or shrink, nowadays).

So let it be bouncy. But only his hat (foot is still toxic and you shouldn't try to push Funghi like you'd do with inkjet). And bumping you to the side as well. If you want to have a Funghi ride, you'll have to master it first. Else all you'll get will be a funghi-rodeo. 

Mais tout ça devient secondaire si - une fois déplacé - Funky Funghi devient utile. Bon, comprenons-nous: ça reste un PNJ peu fiable et dangereux sous les bords. Disons par exemple que son pied reste toxique (on ne le pousse pas à la main) et redoutable (on ne reste pas trainer en-dessous). Mais son chapeau, lui, avec sa jolie tête de bumper pourrait ne réserver aucune vacherie et agir effectivement comme un bumper. Mais un qui soit susceptible de nous propulser vers l'arrière ou vers l'avant si on ne le prend pas bien comme il faut. Bref, un bumper qui amène une touche d'imprévu pour le joueur inexpérimenté, une touche de challenge pour le paddawan, et une variable supplémentaire à intégrer pour le Maître.

A méditer.

A implémenter ;)

Thursday, April 30, 2015

Vieux vieux pixels ...

Quand je vous disais qu'au début de l'aventure de Bilou, je réalisais mes décors sur des feuilles millimétrées. Je vous ai retrouvé le tout premier "tileset" de la green zone...

Here come some oldies ... tiles on a millimeter-grain sheet of paper, waiting to be converted into list of numbers. 

That's how you develop video games when you're allowed to use the computer at most 1 hour a day... and don't have a colour screen. 
Monsters were designed in the same way, but it wasn't easy to make sure animations would work well. That's why I shifted to modular animation instead for the BASIC version.

Et en bonus, le tout premier appleman, le boss de la green zone et SpongeBop du temps où elle trainait par terre.

Wednesday, June 27, 2012

pitchenette

I managed to animate the ink in the school zone, target reached. AnimEditor should now be fixed and will be able to manipulate .spr files without dropping information, although I still need to track some memory-related bug.
So why not have a break and try that counter-stuff to better manage the number of applemen on screen.


au menu:
- on garde les berry bat;
- on revient à l'ancien comportement des pommes (merci SVN ;)
- seule la moitié des pommes entre direct dans l'arène;
- mode "pitchenette" pour repousser les pommes quand on a plus de punch-power;
- j'utilise (enfin?) les graphismes revisités l'an dernier.

Plus qu'à vérifier que ça donne effectivement un gameplay intéressant, corriger les éventuels "bugs de maps" et comprendre pourquoi j'ai parfois plus de pommes au total que prévu compris et corrigé: en augmentant le "nombre de pommes autorisé à l'écran" chaque fois qu'une pomme est morte, et en utilisant uniquement ce nombre (indépendamment du nombre, c7 de pommes restant à générer, c5), je pouvais autoriser la création de trop de pommes en fin de partie si le joueur fait un "combo" avant que les "générateurs" n'aient le temps de réagir.

I've sent beta-testing ROM to some friends, to see whether that's worth a world-wide release or not. It seemed the right time to integrate the new graphics for the green zone, revise maps and to give a new idea a try: the pitchenette ...

Now when you hit (B) when standing, you'll do something, whatever your punch level might be. When you don't have any power left, Bilou simply push a "stop hand", that is merely capable of repelling the applemen. It doesn't have any effect on stunned applemen nor on woodworms, though.

Saturday, February 04, 2012

Berry Bat Things

Hey, there! Cleaning up and tuning in are done. If you enjoyed once AppleAssault, but then stopped playing it because you didn't feel the challenge anymore, here's an update that you might love: AppleAssault -- BerryBat Things. The idea is simple: you've got limited time to clear up a level. As long as you punch applemen out of the arena, nothing bad will happen... But if you get lazy and that the applemen count remains the same for too long, a berry bat will come and tease you. You could manage to get rid of it, of course, but then another one will come soon, and then again another and another, again and again until you surrender (or focus on punching Applemen, after all).

So how comes you're still reading this ? Go and download it! -- oh, wait. Better pick the final release

Bilou! Le revoilou! Ok, je suis supposé bosser sur la School zone, mais j'ai une très bonne excuse pour recycler AppleAssault en ce début d'année 2012. J'ai enfin intégré les "berrybats" dans le jeu. Si vous aviez fini par faire le tour du jeu de 2010, autant vous prévenir tout de suite: vous allez faire une rechute!

A priori, le principe est toujours le même: assommez les pommes en leur sautant dessus, puis expédiez-les hors de l'arène d'un bon coup de poing. Ouaip. Sauf que maintenant, si vous passez trop de temps sans dégommer de pomme, une chauve-berrie (berrybat) viendra vous tirer les oreilles. Oh, bien sûr, vous parviendrez sans doute à vous en défaire, mais il en viendra alors encore et encore, de plus en plus vite. Jusqu'à ce que vous vous décidiez à vous concentrer sur la mission première: virer les pommes.

Prêts ? Moteur ... et .... Action!

Oh, and btw, make sure you're voting for the "success" of the new features in the side panel if you've played to v1.4 as well ;)

Monday, January 30, 2012

Unclump'm

Well, I've been using AppleAssault as a regression test when developing the new collision engine ... really just to make sure I'm not broking everything up, as there's nothing in AppleAssault that could benefit from the new engine, anyway. No pushable/carriable ennemies, no platforms. Nothing.

But of course, being in that source tree again (^_^), I wanted to give some ideas a try. The first one was to integrate berrybats in the game, as a way to force the player to focus on defeating applemen, and not just hop around. It now acts like a sort of indirect timer, appearing when you've been unfocused for too long... and appearing again and again until the lesson has been learnt :)
I'll need to work on the timing, though, so that the game doesn't become completely unfair :P

Un nouveau moteur de collision, c'est pas rien. Alors j'utilise AppleAssault pour m'assurer que tout fonctionne toujours bien au fil des modifications, même si la plupart des améliorations (pousser, ramasser, etc) ne sont pas à l'ordre du jour pour ce jeu précis. Mais, vous me connaissez: à trainer dans le code, j'en viens à me dire qu'on pourrait utiliser les chauve-souris pour forcer le joueur à s'attaquer au pommes ...

Un autre point, plus délicat, c'est de faire en sorte que les pommes cessent de se coller les unes aux autres. KirbyKid a raison là-dessus: ça pousse le non-réalisme vraiment trop loin. Je ne veux pas non plus en venir à un comportement de type goomba: il est prévu que les Applemen puissent se croiser s'ils arrivent en face l'un de l'autre, mais on ne devrait pas pouvoir en avoir 10 sur 2 pixels. Il me faut donc un test de collision entre-applemen, mais je vais devoir être prudent si je ne veux pas me retrouver avec des centaines de tests inutiles et vider la batterie de la DS en un rien de temps.

The second thing is linked to Kirby Kid's comments: Applemen tend to stick to each others, overcrowding on platforms, which isn't very realistic. I don't want to go for goombas-like behaviour: Applemen are design to be able to cross each other. Still, there shouldn't be 10 of them on 2 pixels. So I need to have a sort of applemen/applemen collision detection, but that should be handled with care, otherwise I could easily overload the collision engine with hundreds of (unnecessary) checks and dry the DS batteries in no time.

The approach I picked is to take advantage of a small transient state where the Applemen halts in front of a cliff, checking whether it will jump -- which you'd barely notice when playing the game. Only during these 2 frames, it actively checks for other Applemen in its immediate neighbourhood, and get "knocked out" of the platform if there was. Expect a revised .nds file to download in early February, as now, I still need to remove a *lot* of debugging printf ... and have a shower...
Oh, and some coffee would be nice as well... And a commit :) Cheers :)

Mais il y a dans la machine d'état de l'appleman un petit délai où il fait une pause en bout de plate-forme pour décider s'il va sauter ou non. ça pourrait être le bon moment pour tester s'il y a un autre appleman dans les alentours et se faire "éjecter" de la plate-forme si c'est le cas. On va tenter de vous permettre de télécharger ça début février, mais avant ça, j'ai une tonne de printf à retirer ^^"

Tuesday, December 27, 2011

branch/newcollide : buggy

Voilà environ 3 mois que j'ai entammé la révision du moteur de collision de Bilou, avec pour objectif de permettre la gestion de blocs, plate-formes et autres. Je n'ai pas avancé très vite, mais le code compile et fait tourner AppleAssault ... enfin, presque. Voyez plutôt ....

3 monthes to get a first prototype of the new collision engine. I haven't been very quick on that, but at last, Apple Assault mostly work again ... well ... sort of. I'll let you judge that.
-- btw, I wonder whether desmume-cli --record-movie would be easier to use than byzanz-record for those posts. Please, allow me to debug that on-line:


# stopped by monster-player collision.
statW0->statF2 on found1 (v0 ~ :0 200 ~ :1)
statW1->statF3 on found1 (v0 ~ :0 200 ~ :1)
Makes the appleman bounce when it hurts Bilou
#hit
state4..7->statH15 on hit0
\\ [wc 1 ? we 0 < &] (256 ~ :1 512 ~ :0 0 :6 x1)
state4..7->statH16 on hit0
\\ [wc 1 ? we 0 >= &] (256 ~ :1 512 :0 0 :6 x1)

The collision halfly works, on the video above: the applemen indeed bounces and the collision is triggered. But Bilou isn't affected. Afaik, that's because something got wrong in the guardian expression (conditions between the square braces) that can no longer be true in the new collision engine. Before we actually take a transition to the "hit-to-left" (H16) or "hit-to-right" (H15) state, one must detect where the collision came from (test on 'we', other dude's variable #14, which holds centrum-to-centrum horizontal distance), and whether it was actually something that hurts (test on 'wc', the other dude's variable that indicates the matching collision bits on both active and passive collisions area). For some reason,
case OP_GETCTX:
if (sp>=STACKSIZE-1) return oops("vCTX");
if (c[1].data==0) return oops("!CTX");
if ((op&0xf)>=0xc) stack[sp++]=xcontext[op&0x3];
else stack[sp++]=c[1].data[op&0xf];
break;

Did return at the oops("!CTX") line. In that case, the expression is never true. Bilou won't ever got hurt. I must be missing something that swaps contexts in the code that manages collisions, at the root. Some gc[2]=gc[0]; on line 1742 could do the trick...

that and some silly boolean inversion in the c[1].data =? NULL condition ^^"

Saturday, July 16, 2011

Implémenter les plate-formes.

Aah. De vraies vacances, ça fait du bien, même si ce n'est que quelques jours... qui se terminaient par un peu de baby-sitting à un mariage cet après-midi. L'occasion de refaire un peu le point sur les problème des plate-formes mobiles. Le point essentiel, c'est que -- tout comme le transport d'objets par Bilou -- ces plate-formes dépendent de la possibilité de lier un gob à un autre temporairement. Un micro-contrôleur "follow", donc, qui déplace p.ex. l'appleman à l'identique de Bilou.

At last some day off ... really off. Not even some Bilou thinking until this afternoon "_". And I had no documentation or current code state with me when doing so, which somehow explained why I focused on a fairly remote problem such as moving platforms. The last thoughts came to the conclusion that being carried would involve a dedicated "follow" micro-controller where a Gob is attached to another.

Be coherent
Comment s'assurer que la plate-forme aura déjà fait son déplacement au moment de déplacer ce qui s'est posé dessus ? Sans ça, on risque d'avoir des effets de "décalage" chaque fois que la plate-forme modifie sa vitesse, comme ceux qu'on peut observer dans Zool.

To make that work, however, it is mandatory that the carrying object has moved before the carried object's movement is evaluated. Otherwise, the player will experience zool-like glitches everytime the absolute speed of the carrier is altered. The FollowController must thus be able to detect whether there is an not-yet-processed carrier situation and execute anticipatively the "animation" of that carrier. That will require some more book-keeping at the core of Engine::animate(), but I think it'd be more flexible than pre-encoded priority levels.

Pour y parvenir, le mieux sera de faire en sorte que FollowController::think() puisse détecter si son objet-cible a déjà été exécuté ou non. On joue là au plus profond du moteur de jeu, qui appelle Animator::play() sur chaque objet qui s'est enregistré via reganim(). J'ai déjà une liste "pending" séparée de "todo", il me reste à noter au niveau de Animator lui-même où on en est. Après ça, il suffira de se faire un petit if (target.state==QUEUED) target.play(). L'objet-transporté voit alors son exécution interrompue le temps que l'objet-transporteur soit mis à jour.

Thou shall not follow the NULL pointer
Avec ce mécanisme, je vais introduire pour la toute première fois une référénce directe entre deux personnages du jeu. Jusque là, je passais systématiquement par le tableau GameScript::gob[] ou je me limitais à une interaction éphémère lors d'une collision. Si je ne fais rien de spécial, une plate-forme détruite pourrait amener les objets transportés dans un état incohérent, voire provoquer de sérieux problèmes au gestionnaire de mémoire ou planter sauvagement le jeu.

The second challenge I addressed is to ensure that we can handle the disappearing of the carrier transparently for the carried object(s). We can do that in different ways, some including list of cross-references, etc. but it looks like the best way around could be to delay actual Animator::DELETE requests by one frame so that the former carrier can be caught in DISCARDED state by FollowController::think() method that would drop then the reference.

Je pourrais exiger du "programmeur gobscript" qu'il règle ça lui-même en prévoyant des états-tampons ou des collisions de désolidarisation, mais ça signifierait qu'une erreur de script dans la machine d'état d'un objet pourrait se traduire en un dysfonctionnement du moteur lui-même... à proscrire à tout prix. Ca risque donc de me coûter un Engine::animate() un peu plus sophistiqué, mais l'idée est de garantir que tout objet "qui s'en va" sera présent au moins pendant une frame dans l'état "DISCARDED".