Wednesday, March 31, 2010

- * aouch * -

I'm not going to claim that 'it works! I can't believe it". It's a little too early for that, but at least I've got the framework set up and the boring stuff done. I can have little stars shot away from Bilou when he's stomped by Funky Funghi. There are still weird things to be investigated such as "why doesn't they disappear as expected?" or "why do they look like coming out from Funky Funghi rather than from Bilou?"

Il est encore un peu tôt pour crier victoire, mais ça prend forme. Ces petites toi-toiles s'échappent de Bilou lorsqu'il se fait écraser par Funky Funghi ... les éléments permettant de gérer des objets dynamiques s'assemble ... l'objectif "apple assault" se rapproche. Il me reste à comprendre et corriger quelques effets curieux. Ce serait aussi bien qu'elles disparaissent lorsque leur animation est terminée par exemple ... et qu'elles proviennent effectivement de Bilou.

Source-checking and cross-checking doesn't seems sufficient. I'll have to meditate this.

edit: les petites étoiles sont supposées rebondir quelques fois sur le sol puis disparaître grâce au code suivant:

state19->state19 on fail [v1 $20 >] (v1 $40 - ~ :1)
state19->nil on fail [t]
mais curieusement, ça ne marche (presque?) jamais avec [v1 $40 >] comme gardien et seulement de temps en temps avec le code ci-dessus. Je viens de réaliser que le contrôleur "gravity" ajuste la vitesse verticale lorsqu'on rencontre le sol de manière à ce que la chute se termine sur le sol. Ca casse évidemment tout mon beau mécanisme puisqu'au moment de l'évaluation des transitions, ce n'est plus la vitesse de l'impact étoile-sol que je lis, mais la distance à laquelle l'étoile se trouvait par rapport au sol. Je vais réviser ça. Ca pourrait bien expliquer quelques autres bugs dans le comportement de Bilou et de l'Appleman.

Oh, and btw, here's a small UML snippet of the classes involved in such "extra actions". The 'red path' show interactions when an action definition is parsed, and 'blue path' how the actual "shooting" occurs.

Tuesday, March 30, 2010

Gobs Dynamiques

Pour permettre que Bilou soit assailli encore et encore par (e.g.) des Applemen, il me faut ajouter à mon moteur de jeu le support des objets dynamiques. Jusqu'ici, chaque élément "vivant" du jeu (les "GameObjects" ou "gobs") est déclaré dans le script produit par le level editor. Il possède un numéro d'identification unique qui détermine sa place dans la "table" des gobs. Si ça marche plutôt bien pour les ennemis classique, c'est évidemment insuffisant pour les tirs (pensez à un shoot-m-up), les bonus mobiles (le champignon de super-mario), les petites animations sympa (la petite étoile qui apparaît quand Kirby se cogne trop fort) ... et ... les monstres créés à la volée par un "générateur" (qui sont une variante des tirs, finalement).

J'ai déjà en partie la logique qui permet d'invoquer la construction d'un objet depuis la logique du jeu, je dois encore m'assurer que j'ai la possibilité de décrire le fait qu'un tel objet peut disparaître ... et mettre en place un petit test pour vérifier que tout ça fonctionne bien.

So far, most of the sprites in Bilou are statically defined in the game script produced by the level editor. They have a unique ID, well-established initial coordinates and so on. And that works pretty well, mostly because I haven't introduced anything like "shots", moving bonuses or any run-time generated monsters. One of the key elements of "Apple Assault" is precisely that there will be more and more monsters coming like in a Game&Watch.

I've got some of the logic to bring new monsters to life during the game ready, which has been tested for sound effects. I need to check that such monsters can also be terminated, both during the game (e.g. at the end of an explosion animation) and when the level is completed/restarted.
Then I'll need to put this all together and check it indeed works as expected in a small "gedsdemo".

I'm not pretending it's a tedious task. I'm just a bit overwhelmed IRL to start coding something that allocates memory dynamically after office hours.


Et pour être tout à fait honnête, les parts de Munchkin et autres pizza-buffet initiés par mes collègues sur le temps de midi ne sont pas complètement étranger à l'apparente lenteur sur cette tâche.

Thursday, March 25, 2010

LE Bilou's Book

C'est un cadeau royal que mon frère me fait là! La toute première instance du Bilou's Book, reprenant mes p'tits dessins les plus aboutis sur ces 10 dernières années en un album "extrafilm", avec quelques extraits de ce blog, et une petite rétrospective du projet. Je devrais être en mesure, d'ici quelques jours, de vous permettre de l'avoir vous aussi.

Les épisodes du premier tome ("green woods") sont étonnamment bien rendus, de même que les quelques interventions des soldats-crayon. Je transmettrai à mon frère les fichiers initiaux des planches colorées, histoire qu'il puisse les mettre à résolution maximale. On a par contre été tous les deux un peu déçu du résultat "jpegifié" du pixel art, en particulier avec le fond mauve de SEDS ou du RSD Game-Maker. Si quelqu'un a des conseils dans ce domaine-là, je suis preneur ^_^

I think my brother offered me my best birthday gift ever since I stopped receiving LEGO blocks: the first tome of the Bilou Book, printed on glossy paper, including the comic strips "crayon & sharpenher", "sponge bop",
"inkjet escape" and other blog heroes. It also features a surprisingly hi-quality set of the early "green woods" comics, and of course, bits of this very blog, detailing the story of a 15-year-long project.
We'll work on making it available to all Bilou's fan as soon as possible.

Ca y est ? vous avez compris comment Apple Assault est revenu en première ligne ?

Son vrai titre, c'est "Guru Meditation, a Bilou's Adventure". Les posts qu'il reprend sont donc regroupés sous le label "gmaba".  

Tuesday, March 23, 2010

Apple Assault

A force de compter les moutons pour essayer de me rendormir cette nuit, ils ont fini par se transformer en Applemen ... et Bilou était assailli encore et encore. Et à chaque collision, mon écran de débug confirmait les zones et les testpoints. En rebondissant sur plusieurs applemen d'affilée, la barre de punch de Bilou augmentait, ce qui lui permettait des "finishing moves" assez dévastateurs.

It was another such night, where I just can't get no sleep. It is supposed to help if you count sheeps, and so did I ... until sheeps started turning into angry applemen. They were assaulting Bilou, again and again, and there was no hope to escape them. It was punish or perish. And by chaining bounces over applemen's "heads", Bilou was gaining more punching strength that let him release impressive "finishing moves".

Then the sound got clearer, as letters "R E A D Y" were falling from the sky, prompting me for another round. Small echoes set the rythm, until in a zaash! they zapped to the right, letting the action start again. It was the sound of my bro' String Tracking.

Puis sur un "dit dililit dut dut deut deut" les lettres "R E A D Y" tombait en rebondissant avant de partir en trombe vers la droite sur un "ch..ooOO()()WAh!" et la bande son enchaînait sur la version 6 pistes du "String Tracking" de mon frère.

Ca doit venir du cadeau que mon frère a choisi pour mon anniversaire, qui reprennait ce dessin destiné à Romain. A l'arrière plan, le côté "débordé par l'avalanche de monstres" m'avait servi à illustrer le principe de "Bilouh-lanta" lors du petit sondage de janvier. Titre peu accrocheur supposé indiquer qu'il s'agit en somme d'une opération survie. "Apple Rumble 2" aurait été sympa, mais confusionnant. Ce sera donc "Apple Assault". On verra bien qui de lui ou de "Nuts'n'Bolts" peut être réalisé en premier.

If you followed January's Poll on "what should be the next milestone", you may have identified the "Bilouh-lanta" study case ... Which is more likely to be renamed "Apple Assault". I can't tell yet whether i'll focus on this and come back to "Nuts'n'Bolts" afterwards or whether I'll honour your preferences and keep working on the not-so-obvious-to-code distant clone of Manic Miner. Only time will tell, I guess.

Friday, March 12, 2010

Crumbling Floor ... revisited.

Alors quoi ? Si c'est si simple de faire un sol qui croule dans Manic Miner, pourquoi est-ce la prise de tête ici ? Me suis-je trop compliqué la vie avec mon moteur de jeu et mes scripts ?

L'état est entièrement encodé dans le graphisme

Willy ne tourne qu'à 25Hz, Bilou à 60. A chaque frame, le sol de Willy est dégradé d'un pixel de plus si Willy est toujours dessus. Si je veux faire un autre style d'animation ou si je souhaite quelque-chose comme des morceaux de pont qui balancent quand on marche dessus puis tombent dans le vide après un bref délai, la "technique Willy" n'est plus appliquable. Bien sûr, en 1983, Matthew Smith ne s'était pas encombré avec "mais, on pourrait vouloir faire disparaître le sol un peu différemment plus tard dans le jeu" ^^"

J'ai une approche "bottom-up"

Le programme de Carles est contruit en divisant le problème (coder Jet Set Willy) en sous-problèmes (déplacer Willy, gérer les collisions), etc. Dans mon projet, j'ai une machine (la DS) et un objectif un peu difficile à réaliser directement sur cette machine (Bilou). Du coup, j'essaie de me construire une machine virtuelle (moteur de jeu, langage de script, outils d'édition de maps, etc) dans laquelle le problème serait plus facile à résoudre. Cela se prète mieux à la généralisation à un "game maker" par la suite, mais ça veut dire aussi que tant que je n'ai pas trouvé le bon jeu d'abstractions, les solutions sont bancales.

J'évite de sur-utiliser les sprites
Je pourrais ajouter quelques "actions externes" à mon langage d'expressions qui altèreraient le contenu de la map, et tout gérer avec des sprites. Je marche sur un pont ? hop, le fond disparaît et est remplacé par un sprite du même morceau de pont qui bascule. Si je ne suis pas resté trop longtemps, le sprite "réécrit" le bloc sur la map avant de disparaître. Ce genre d'approche risque d'introduire trop de sprites sans qu'on puisse contrôler combien il devrait y en avoir. Vous vous souvenez du "spinning block" de Mario World ? Imaginez un peu qu'il ait fallu animer un sprite pour chaque block qui se mette a tourner parce que vous l'avez touché ... bonjour l'horreur!

L'idée est donc de rajouter quelques abstractions de base, telles que "une animation liée à une position sur la carte" (pour les ponts, le spinning block, etc.) et "une portion de la map dont je peux changer le contenu" (pour les passerelles que l'on fait apparaître ou disparaître à coup d'interrupteurs comme dans Keen). Les cogitations sont en bonne voie. Le code suivra ... comme les autres éléments de mon énorme "todo list". Derrière la façade de "vous aimez le nouveau look du site", il y a donc une sorte de "bouillonnement" de choses difficile à décrire qui avance dans le bon sens dans les slots de temps libre qu'il me reste. J'espère parvenir à en dire plus long prochainement.

A+

Thursday, March 11, 2010

HD mais pas trop.

Au n° 1 des choses à modifier sur la banderolle actuelle, Gédéon listait "Bilou en gros pixels". Voilà. C'est chose faite. Le crayon et la souche suivront.

J'ai appliqué la même technique que celle qui me permet de faire mes vignes et tout ça : zoomer le sprite puis le sauver et retoucher dans SEDS, ce qui me permet d'avoir un bilou de 32x32 pixels.

Alors je vous le dis tout de suite pour que vous n'alliez pas vous emballer : c'est chiant comme la pluie à faire et je ne vais certainement pas jouer à refaire ça avec tous mes graphismes. La banderolle suffira amplement.

Mais bon, puisque je m'attaque à une nouvelle démo inspirée de Jet Set Willy, autant remettre à jour ce qui sert de "page d'accueil" avec des graphismes vraiment utilisés pour mes jeux ... Le Bilou précédent avait quand-même été dessiné sous Delux Paint IIe pour MS-DOS ^^"

Wednesday, March 10, 2010

B_CRUMBLINGFLOOR

Somehow, I stumbled upon this re-implementation of the Manic Miner / Jet Set Willy engine in Visual Basic. I'm unsure on how I should implement crumbling ground in Bilou (or any block animation in response to character's presence). Let's see how a +20 year old game handled it...

Bon, je l'avoue, je suis intrigué par la quantité d'"éléments spéciaux" présents dans un jeu aussi vieux que "Manic Miner" contient, et la difficulté que j'ai à trouver une manière convaincante de réaliser la même chose dans mon moteur de jeu actuel. Du coup, j'ai mis la main sur une ré-implémentation du jeu en Visual Basic. Voyons donc comment les blocs-qui-disparaissent-quand-on-reste-dessus ont été gérés ...

' block type constants
Private Const B_CRUMBLINGFLOOR      As Byte = 2
Block types are encoded in a separate array, with one byte per 8x8 tile. One such type is "crumbling floor". Other block types include B_AIR, B_FLOOR, B_WALL, B_CONVEYOR and B_NASTY (two of them) and B_SPARE (for switches). Jet Set Willy only has one B_NASTY type, and the other one is converted into B_SLOPE. This is consistent with my own engine.

Carles a construit son moteur de Willy de manière à réutiliser les données du jeu telles quelles -- sans être le code original sous Z80, ça donne malgré tout une bonne idée de ce qui aurait pu être fait. En l'occurence, par exemple, la structure de chaque niveau est donnée par un tableau de la taille de l'écran, indiquant quels graphismes utiliser, mais aussi le type de chaque bloc entre 0 et 7.

B_CRUMBLINGFLOOR est celui qui nous intéresse. En cherchant "crumbling" plus loin dans le code, je tombe donc sur la fonction DoWilly (extrait ci-dessous) qui gère toutes les interactions entre Willy et le monde qui l'entoure. DoConveyors ne fait qu'animer des blocs, de même que DoGuardians se contente de déplacer les monstres. Ce sont les sous-fonctions de DoWilly qui détectent les collisions et altèrent le déplacement du personnage. Exactement le genre d'approche que j'utilisais dans Calimero et Bilou en QuickBasic.

What's interesting (for me :-) in Carles' approach of redoing Willy's world is that he operates directly from the tape file of the spectrum, so not only it has the "readability" of modern BASIC (i'm not that much into Z80 assembly ^^") but it still explains the logic of the original game (how switches, witches and stuff are encoded).
If (.mode = [eWalk]) Then
  If Not (WillyCheckFeet()) Then
    ' code for falling stripped out ...
  End If
  Call WillyCheckConveyor(keys)
  Call WillyCheckCrumblingFloor
End If
The DoWilly() sub shown above proceed step by step, handling interaction of Willy with every item "present" in the game. That is, we have DoConveyors or DoGuardians as well, for sure, but they merely perform animation and movement job. WillyCheckConveyor makes sure conveyor pushes Willy. That's the real job.
Let's thus have a look at WillyCheckCrumblingFloor just below ...


Voyons donc WillyCheckCrumblingFloor dont le code est ci-dessous. Après s'être assurée qu'il y a bien un bloc friable sous les pieds de Willy, elle va utiliser FXCrumblingBlock pour procéder à l'animation (décalage du tile d'un pixel vers le bas) et transforme les propriétés du bloc donné en "B_AIR" si FXCrumblingBlock lui dit de le faire à travers la variable f.
o = .x + (.y \ 8 + 2) * 32
For c = 0 To 1
  If (m_RoomBlock(o + c) = B_CRUMBLINGFLOOR) Then
    Call FXCrumblingBlock(m_DIBBack, 8 * (.x + c), .y + 16,
                          CAPaper(m_RoomData(o + c)), f)
    Call FXCrumblingBlock(m_DIBMask, 8 * (.x + c), .y + 16,
                          I_BLACK, False)
    If (f) Then
      m_RoomBlock(o + c) = B_AIR
      Call FXRect(m_DIBBack, 8 * (.x + c), .y + 16, 8, 8,
                  CAPaper(m_BlockCA(0)))
    End If
  End If
Next
FXCrumblingBlock
will not be shown here, because it's a pretty dirty function that mixes up game logic, tile animation and rendering engine commands. What I can tell you is that everytime it is invoked, it scroll downs the data of that specific tile, and insert a "blank" line at the top. Once this is done, it scans the whole tile again and sets the "cleared" flag (variable f) to false if it found any non-blank pixel. That's precisely what triggers transformation of B_CRUMBLINGFLOOR into B_AIR.

As the tile "crumbles" exactly one pixel per frame and Willy walks one pixel per frame, it means if you simply walk on crumbling floor, it will be completely crumbled when you're done walking.


Pour moi, c'est là que le bât blesse: FXCrumbblingBlock mélange allègrement rendu vidéo, manipulation des animations et logique du jeu. Je ne la reprend donc pas ici, sachez juste qu'elle décide si oui ou non l'animation est finie en parcourant les pixels qui viennent d'être édités. Si tous les pixels sont "transparents", c'est qu'il n'y a plus du tout de sol et on peut remplacer B_CRUMBLINGBLOCK par B_AIR.

Là-dessus, je vous laisse bras-dessous: il est temps que je prépare ma pitchounette à aller rechercher ma fée à Belle Ile. Ciao.