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 :aand 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

Friday, June 05, 2026

La forêt de Castle of Illusion ?

C'est l'histoire d'un screenshot qui arrive juste pendant que je réfléchis à décorer un peu mieux ma "green zone". Il aurait mérité d'être avec d'autres dans la section "études pour dessiner des arbres dans mon jeu" ... ou pas. C'est un screenshot de Castle of Illusion sur MegaDrive, mais pas ce niveau qu'on a tous vu, non le suivant. Celui qu'on coupe au montage. Celui où il va falloir éviter de tomber dans le vide et éviter de se manger les araignées ... 

C'est Régis Monterrin qui avait attiré mon attention dessus avant que je ne note des bizarreries dans les tiles, un peu comme si l'artiste avait fait un chouette truc puis que l'outil pour exporter son travail avait buggé et que personne ne s'en était rendu compte.

Parce que bon, on a tellement de carrés répétés indépendamment de la texture, de transition brutale entre palettes de couleurs aux frontière de la grille-de-tiles que ça en devient presqu'un contre-exemple de pixel-art, où les spécialiste vous donneraient des astuces pour éviter qu'on ne remarque que tout n'est que carrelage aligné sur une grille.

En fait, au fil de l'évolution de ma "green zone", je suis passé par un état un peu de ce genre et j'ai noté que ça me faisait inévitablement penser à ce jeu C64: Forbidden Forest. (et sa suite, sur le screenshot)

Forbidden Forest, c'est le jeu qu'il vaut mieux ne pas regarder de trop près. Alors ok, pour un jeu de l'époque 8 bits, avec un maximum de 256 caractères à l'écran alors qu'il y a place pour plus de 1000 d'entre eux, c'est le truc le plus organique et le plus varié que vous puissiez faire. Là où l'état de l'art, ce sont les écrans interchangeables de "Pitfall" ou la répétitivité de Wonder Boy, ici, on est sur un scrolling continu d'arbres tous différents les uns des autres ... mais aussi sur une omni-présence de l'angle droit.

C'est là qu'est intervenu Aurélien Simon:

Tout ça disparaissait sur un bon vieil écran CRT évidemment. Juger du graphisme de cette époque sur un LCD n'a pas de sens, puisqu'ils étaient créés sur et pour le CRT 

J'avoue que j'avais un peu de mal à y croire. Que le côté "patterns bizarre" du tramage ne pose pas de soucis, oui. Mais ces gros pavés ? ces lignes horizontales et verticales quasi-continues se feraient adoucir rien que par le balayage ?

J'ai cherché un peu sur youtube, des fois que quelqu'un aurait effectivement joué à ce jeu sur tube cathodique ... c'est un des niveaux qu'on avait fait avec J.L.N lors d'un "ludifestival", mais à l'époque, manette en main, on faisait bien sûr beaucoup plus attention aux feuilles-plateformes-géantes qu'au décor. Pas de chance, la seule vidéo que j'aie trouvé, c'est celle ou le joueur a coupé cette séquence au montage.

Mais pendant ce temps-là, Aurélien, lui, avait ressorti son bon vieux Phillips et sa méga-drive et re-joué à Castle of Illusion jusqu'à ce niveau-là pour refaire un screenshot (non?) réaffiché l'image de Régis pour la prendre en photo.

Et là, il faut bien reconnaître qu'à part la ligne horrizontale à hauteur du pied de Mickey, sur la gauche, ça donne plutôt propre. Ni les joueurs ni les testeurs de l'époque n'ont dû y trouver à redire.

Bon, fondamentalement, ça ne change pas grand-chose en ce qui me concerne: puisque mes pixels à moi vont être sur la NintendoDS, je n'aurai pas de flou gaussien pour venir à ma rescousse :P 



Wednesday, June 03, 2026

autocrlf

I have a git folder that is accessed both by a windows host and a linux guest from a VM (as a shared folder). Everything was fine until some git package upgrade started warning about "in the working copy of 'project.txt', LF will be replaced by CRLF the next time Git touches it" (or the equivalent from the Linux guest).

I'd like to avoid cloning the repository twice and I already have something that makes these file LF-only on the master repository. I set autocrlf = false in .git/config, but that does not seem to help.

The manpages of git are heavy, freaky and intimidating to say the least. But I guess if I had rtfm'd them, I'd have eventually encountered the git config --show-origin --get-all core.autocrlf command, which conveniently reports all the files where the given configuration item. I'd have figured out that while I had my local configuration file requiring "do not do auto-CRLF conversions", the system-global configuration actually had the precedence. ... ridiculus, but that's the way it is now.

git check-attr -a project.txt and git ls-file --eol project.txt could be useful to check the current state as well.

With autocrlf=false in Git/etc/gitconfig, I don't have the warnings anymore, but I still have the file that is switching between CRLF and LF depending on whether Windows host or Linux guest is checking it out. It looks like the only way to get the desired behaviour is to edit * text=auto eof=lf in .gitattributes, at the root of the repository. I want that to remain a local decision, and hopefully, my colleagues haven't committed that file yet, so that'll work.

this is the right place for quickstuff