Thursday, May 28, 2015

Pendat turned dizzy (done)

Got it working ^_^ Pendats turn dizzy when they're jammed at some place they don't belong, and while they dizzy-walk backwards, they either fall to their doom or return to a place where they can safely walk.
Now I need to ensure they react to ink pits and don't try to walk there.


Nous y voilà. Forcez un crayon-soldat à quitter son chemin de ronde et le mode "titubant" lui permettra d'y retourner (ou de tomber encore plus bas). Le dernier hic, c'est le comportement ridicule lorsque le crayon atterit dans l'encre en bas du niveau. Je voudrais qu'il puisse alors s'y enfoncer et disparaître (comme les taille-crayons) mais sans pour autant sombrer dans l'encre qui monte à moins d'en avoir jusqu'au yeux.

remaining todo items:

  • [done] ink droplets no longer stopped by spongebop ? why? wrong flags for collision test
  • [script] Pendats drown in ink
  • [done] Bilou can grab with DOWN+HAND even when facing left
  • [code] Bilou don't get that deep in the ink, please.
  • [done] Fix carried bladors
  • [done] Show Bilou's hands when carrying SpongeBop
  • [code] Intuitive difficulty selection
  • [code/gfx/script] Some sort of scoring

Monday, May 25, 2015

Pendats get dizzy

Première étape vers des crayons "plus autonomes": le compteur de désorientation est implémenté. N'ayant pas encore transféré l'animation "titube", j'ai repris celle où le crayon est éjecté (quand il cogne un mur, par exemple). Le résultat n'est vraiment pas celui attendu :-/

I wrote some gobscript to enforce a "dizziness counter" on pendats. They should be able to walk for 2 blocks after they turned back if they don't want to end up dizzy. But since I haven't transferred the animation itself to my PC, I used "stunned bounce" as a placeholder. The result is some very emergent behaviour, possibly due to some incoherence in body-boxes of the pendat.

Sunday, May 24, 2015

The Ultimate Scrolling Analysis.

Huge thanks to Itay Keren for having written his essay that creates a clear nomenclature of camera techniques in (mostly) platformer games, ranging from Pac-land's position locking to Mario's platform snapping to linear interpolation and beyond.

Grâce au développeurs de Frogatto, j'ai pu découvrir l'existence d'un excellent article sur le scrolling des jeux de plate-forme publié il y a quelques jours sur Gamasutra. Eh oui. C'est ça, l'après Google Reader. Je ne vais pas repasser en revue toutes les techniques qu'il présente, du premier platformer à nos jours -- pour ça, il y a l'article d'origine, mais j'en profite pour mettre à jours mes propres références.

Lerp in action. (C) Itay Keren.
Back then, when I started researching how to move Bilou's camera, my colleague Cyril suggested "an elastic string that would draw back the camera to Bilou's position". One close match is Donkey Kong Country's linear interpolation technique. It still has some "wobbly" effect but much less nausea-inducing than when you lock to the player's position. But this is far from being the only camera mechanic in DK games. Anyone who played the game has noted that some areas of the level are apparently "scripted" with cameras behaviour and that entering some hitbox may suddenly allow the camera to move past some artificial barrier, revealing a hidden area. More subtly, this can also be used to enforce "bottom-locking" in some part of the level, or change the horizontal tracking to the type of gameplay (rush, explore, climb...) of a specific area.

Commençons par une technique que j'avais laissé sur le côté quand elle m'avait été proposée par Cyril -- une "sorte d'élastique qui ramènerait la caméra vers Bilou" -- que j'avais tenté d'implémenter avec le code de poursuite des BerryBats. J'aurais mieux fait de procéder comme dans Donkey Kong Country avec une "interpolation" linéaire qui déplace la caméra d'autant plus vite qu'elle se trouve loin de son point de destination.

When I tried myself to analyze the horizontal scrolling of Super Mario Bros, I thought that there was two 'push-the-screen' positions, depending of the speed at which Mario moves. The reality is a bit different.
two triggers in SMB. (C) Itay Keren.
There is indeed two trigger positions, one -- walking barrier -- that forbids Mario from entering the rightmost part of the screen, and a second that smooths camera movement when Mario starts running. The "early-scroll" trigger doesn't try to keep Mario at its left, though, so he eventually "escapes" to the walking barrier.


Passons ensuite à SMB1, avec son interdiction de revenir en arrière. Ici pas de soucis pour faire demi-tour, mais Miyamoto a quand même pensé à nos jeunes estomacs et a ajouté un démarreur de caméra deux blocs avant la position 'naturelle' de Mario. On y gagne pas pour autant en visibilité pendant la course comme je le pensais au départ, mais on évite un départ trop brusque de la caméra si on revient en courant.

This is what smooth out the movement of the camera by reducing the instan(aus)eous acceleration of the image. I'd be tempted to say screen will move at walking speed until the real barrier is hit. I guess with more CPU cycles and memory, miyamoto's team could have even tried to linearly over time in that region rather than having two-steps, but I doubt most of us would notice the difference, so it's not bad to keep it simple. But no, you don't really have more headroom when running in SMB.

Finally, Itay's model of Super Mario World's camera nicely complement the video document I already found (and not yet re-blogged so far). The camera here clearly has multiple mode, that Shaun categorizes as "platform-snap", "bottom-locked" or "free-moving". I tried and mapped these as an UML state machine, but it lacks one component: the fact that in some levels/parts of the level, some transitions are forbidden -- e.g. in some levels, you will not enter platform-snap and stay bottom-locked.

Les différents mode de suivi vertical de Super Mario World, j'avais déjà étudié par l'entremise de Shaun. Le code est assez sophistiqué pour mériter une machine d'état à lui tout seul. En plus de ça, certaines transitions sont interdites dans certains (morceaux de) niveaux, forçant par exemple la caméra à rester au niveau du sol à moins que Mario ne s'envole dans les niveaux plats. 


What Itay adds to that, is a clear illustration that the camera in SMW has a direction state of its own (moving leftwards or moving rightwards) distinct from Mario's movement. In each direction, there is one barrier that will make you push the screen if you try to go past it, and a trigger that will switch to the other mode if you touch it. When the camera is "heading right", the two yellow lines are active -- Mario is confined within 2 blocks. As soon you hit the dashed line while turning back, the camera switches to "cyan mode", and then you have the screen adapting as quickly as the camera's max speed tolerates because you're about 64 pixels away from the push barrier for that direction (still picture shows a point in time where such catch-back occurs).

L'analyse de Itay est plus précise en ce qui concerne le scrolling horizontale. Il illustre parfaitement le mécanisme des deux "poussoirs horizontaux" décentrés (un pour chaque direction de caméra) et les déclencheurs qui forcent la caméra à changer de direction quand Mario a fait demi-tour de plus de 2 blocs. Il semblerait qu'on ait ici aussi utilisé une "interpolation linéaire" pour adoucir le mouvement de la caméra quand elle atteint à nouveau la position de Mario.

With this scheme, the player always have at least 1/3rd of the screen in the direction he face and half-a-screen-plus-one-block in most of the cases. That works quite well with exploration games like Commander Keen, imho.


If you're doing game design in some way, I strongly recommend you to spend some of your "research points" reading Scroll back : the Theory and Practice of Cameras in Side Scrollers.


Tuesday, May 19, 2015

Life-changing books [3/3]

1998. Bilou devient la cerise sur le gateau du projet "Ultimate Game Maker". Pour le réaliser, j'ai attaqué très sérieusement la lecture des documents (et les sources) de TRAN sur le mode protégé du 80386, les moyens de passer en mode "unreal" (code 16 bits avec données 32 bits) et ce genre de choses en ligne droite de la démoscène PC.

Many game development studios faced a hard time switching to 2D to 3D at the end of the 90's. Things were quite troublesome for my little self too. I had at last access to massive knowledge about VESA, sound cards and newer tools such as DJGPP compiler and early mikmod player source code ... but it was clear 320x200 MS-DOS games were gone for good. My quest for an improved Game-Maker software turned into a quest for a better operating system to run both game engines and game development tools. Filesystems that would make sharing of samples across a large bank of tracked songs trivial, etc. The cornerstone book for that shift is Andrew Tanenbaum's book on operating system, found somewhere in the university's library, and it will stay at my home, studied dailynightly as the Clicker 32 operating system project shaped up.

Je tombe ensuite sur un bouquin à la bibliothèque universitaire qui présente les structures de système d'exploitations avec environ 2 ans d'avance sur la matière dans mon cursus. Pendant à peu près 8 mois, le bouquin sera emprunté presqu'en permanence, et je remplis des carnets entiers de notes de lectures, d'idées pour aller au-delà des techniques habituelles avec l'idée de construire un système idéal où les politiques de gestion de mémoire et de temps CPU peuvent être échangées en temps réel (comprenez, lors du démarrage ou de l'arrêt de Bilou pour revenir au game maker).

Je vais ensuite tomber sur une description assez détaillées de Linux pour me permettre de définir les objectifs avec assez de précision, et identifier les aspects originaux de mon propre design. Un grand nombre des idées de base visent à donner une sensation de programmation Amiga sur une plate-forme multi-threads x86, avec les pilotes de périphériques vus comme des sortes de co-processeurs. Cette quête va m'occuper l'esprit jusqu'à mon travail de fin d'études et au-delà.

A second book, detailing the internals of the Linux system further refined what I did not wanted to have. Like a monolithic system, purely based on function calls. I wanted to give the programmer in the Clicker operating system the feeling to work on a virtual Amiga-like platform, with programmable co-processors for virtual memory, sound mixing and window compositing tasks, where you could hot-swap the process scheduler.

All this started 100% assembly, but that project taught me to use the C language for what it is and to avoid assembly whenever possible. The reason was you are too much bound to what you write. Do you realize there's a mistake in your algorithm ? you'll be to go through registers allocation planning and pipeline optimization once again.


Le projet Clicker sera aussi celui qui me fera lâcher l'assembleur pour chercher à comprendre le véritable fonctionnement du langage C grâce au bouquin de Kernighan & Ritchie. Les algorithmes utilisés pour la gestion de la mémoire deviennent tout simplement trop sophistiqués pour rester écrits en assembleur. Corriger une erreur de conception dans un code de recherche "best fit avec back-tracking" revient à reprendre le design d'une page blanche, re-réfléchir à l'affectation des registres et revoir tous les efforts destinés à assurer un comportement optimal sur le double pipeline du Pentium. C'est tout simplement intenable.

Saturday, May 16, 2015

pendats in the detail.

 Avant la release finale de School Rush, il faudra que je corrige un glitch dans le comportement des soldats. En ajoutant la possibilité aux crayons de prendre Bilou en chasse, je leur ai aussi donné la possibilité de quitter la petite cage dorée dans laquelle le level design les avait placés. Du coup l'approche "façon frogatto" de faire dans le simple plutôt que de chercher à faire des personnages ayant une IA capable de s'en sortir dans toutes les situations.

I believe the game engine issues are now fixed. That gives me the time to go through the remaining gameplay issues and glitches. One thing that may easily occur is to get Pendat stuck at some ridiculous place when he's beeng chasing Bilou, jumped off its designed platform and lands in some place where it cannot walk around. That could either be because the place is too small for a full walk cycle or because it is some area designed to force the pendat to turn back.

Pourtant, il est évident qu'un crayon-soldat devant un intrus ne s'arrêtera plus à son petit chemin de ronde. Difficile de faire en sorte que l'ensemble du niveau puisse accueillir un pendat atterri par erreur quelque-part. Je me retrouve avec des crayons-soldat qui font la toupie parce qu'incapable de se mettre à avancer sur un sol trop incertain.

At first, I thought it was something wrong with the state machine but no. It's just I'm missing an "escape move" that would be valid in place where the regular walk doesn't work, and that can be perceived by the player as a valid excuse for seeing the pendat doing silly things like jumping down a cliff, reaching either safety or sink. Being dizzy could explain that. I have temptative animation in the pipeline.

J'ai commencé une animation d'un soldat ayant la tête qui tourne, donc incapable de se rendre compte s'il y a ou non du sol sous ses pas, et donc pouvant quitter la zone inconfortable même si c'est pour se jeter dans le vide.

Good thing, I don't necessarily need to add new test-points: I simply need to add a sort of "temperature counter" that increase after each turn back and cool down while walking.


Thursday, May 14, 2015

Un Mario sans Checkpoints.

Petit tour sur nesmaps.com ... Il y a un jeu Mario qui n'a pas de check-point, ni visible ni invisible. Un seul dans toute la série 2D où il est nécessaire d'aller du début à la fin du niveau en une et une seule vie: Super Mario Bros 3.
Thanks to Bri Ray, I remembered there's one 2D Mario platformer that do not involve in-level check points: SMB3. I checked the average level size on nesmaps.com .. most levels are around 2560 pixels wide -- vs. 4096 for School Rush levels. There are a few levels with an extended size -- somewhat 3500 pixels -- is a bit closer.

La plupart des niveaux sont assez courts ici. En moyenne 2560 pixels, soit légèrement plus de la moitié des niveaux de Bilou School Rush. Je me souviens de quelques niveaux plus long. Les sables mouvants, par exemple avec dans les 3500 pixels de large.


We have that extended length mostly on levels where Mario is chased. By lakitus or by the Angry Sun, for instance. If I map this distance on School Rush level. it correspond to the location of the two-inkjets obstacle at the end of level 1. This happens to be the location where first-timers fail reapeatedly. It would be tempting to believ that it is because of the length... like they couldn't focus for more than a long Mario level, and then mistakes start to occur.

... That sounslike a pleasing lie to myself. That would be hiding the fact that this very place is simply more hazardous and more prone to trigger instant death. As a result, people would love to see a respawn point near.

The real question is: what happens if I refuse to offer them that ? I guess Locomalito knows better than myself.


Si je superpose le niveau "*deline" de School Rush avec ce niveau-aux-lakitu de SMB3, l'écran de fin correspond avec l'obstacle des deux encriers. C'est aussi dans mon jeu l'endroit où l'encre a atteint son niveau maximum (au réglage de difficulté "normal").
Tout ce qui suit est donc "en excès" par rapport à un jeu bien calibré mais sans checkpoints. Etonnament, ça coïncide assez bien avec l'endroit à partir duquel les joueurs commencent à échouer dans le niveau ... (notez que map2png.pl ne fait pas le rendu de l'encrier et de la gomme qui font office de "boss de fin de niveau" ici).

Friday, May 08, 2015

Hi. I'm Bilou.

Salut à tous! C'est un peu la pagaille dans le "moteur de jeu". Permettez que je laisse Bouli s'occuper de tout ça et que je vous raconte un peu comment tout a commencé.

Hi there. It's me, Bilou. Bouli says the "game engine" is wrecked, but since I'm just the pilot here, there's little I can do to help, so why wouldn't we use that time to know each other better ?


On est en 1993. Deux potes se rencontrent à l'école. Ils partagent une passion pour la musique et le désir de créer des jeux vidéos. Le frère de l'un va se retrouver l'interface entre le PC familiale, les idées de gameplay et les conseils de programmation du nouveau mentor pour tenter de donnée vie à tout ça à grand coups de DATA ...

It all started in '93, with two class mates sharing passion for music and video game design that turned friends. One's younger brother will become the idea-to-machine interface to convert all those ideas into a bunch of GOTOs and DATAs to bring the game to live. His handle was 'Pype' so far, and he's our host today.

Pour une raison nébuleuse, le frangin en question. Notre hôte, connu aujourd'hui sous la signature de "Pype" manque d'être rebaptisé "bilou" pendant cet après-midi. Si bien que c'est automatiquement en "BILOU.BAS" que seront sauvés mes premiers pixels sur processeur Intel... Encore quelques heures et le nom de "Bilou" sera définitivement transféré de Pype a ma propre bouille ronde.

But on that very day, he was about to be re-named "Bilou" by the two friends. That nickname was used so much on that afternoon that he used it when it was about to save my very first implementation on PC ... "BILOU.BAS". Hopefully, with a few more hours, *I* turn to be Bilou and he can remain "Pype".

C'est le début de l'âge d'or. Quels que soient les projets qui trottent dans la tête des membres de la toute nouvelle équipe -- PPP Team -- c'est moi, Bilou, qui suis au centre. Bilou Ski, Bilou Karting, Bilou's Adventure, Bilou's Quest, Biloutris. Tout y passe. Les lignes de code se cristallisent ... les démos deviennent jouables.

Somehow, it was the golden era. Whatever game the team dreamt of, I was the star in there. Bilou's adventure, Biloutris, Bilou Ski, Bilou Karting, Bilou's Quest, Bilou's Sky Quest ... name it, you'll have it. Code line piles up and demos start to be playable.

Malheureusement, les outils de développement de l'époque sont loin d'avoir la flexibilité et la convivialité des Unity d'aujourd'hui. On se bat tantôt avec l'espace mémoire, tantôt avec le nombre de couleurs, tantôt avec la puissance de calcul insuffisante... les grands projets piétinent.

But unfortunately, even the compilers that turned "calimero" into an executable will fail on the increased complexity of my world. Every additional colour on the gamefield requires a re-write of the engine and of all the level designed so far. Despite an all-shiny Master Boomer, they struggle to bring background music to the game ... It all looks unfinished to the foreign eye.

Les potes de PPP Team mettent alors la main sur un outil qui va les occuper pendant près de 2 ans: le RSD Game Maker, qui permet de suivre une nouvelle idée de jeu dans la semaine où elle germe... On dessine ses niveaux directement ... on les teste dans l'après-midi. Mais les interactions sont limitées et ce type de gameplay n'est pas pour moi. Mon destin est de sauter sur la tête de chenilles géantes et de me faufiler sous des champignons et des gommes sauteuses... Pas de tirer au lance-flamme sur des tronc rampants.

A few month later, the PPP Team get their hands on another tool that will keep them busy for 2 years: the RSD Game Maker. With a few clicks and some improved understanding of English, they can build a 4-level game in a single afternoon, and a Commander-Keen-sized quest in a couple of months. New heroes appear, pastiche and tributes alongside original characters. But the engine cannot be bent to my signature move of caterpillar-stomping and my world of bouncing mushrooms and switches: it's an engine for flamethrowers, weapon level ups and locks.

Quand j'y repense, je me console en me disant que le game-maker lui-même portait dans ses limites sa propre obsolescence. En 1997, Pype se met en tête d'exploiter ses nouvelles connaissances en Assembleur pour construire un Ultimate Game Maker, haute résolution, son HiFi stéréo, plus de couleurs, des monstres au comportement dignes de Super Mario World ... et la liste s'allonge au fur et à mesure que le jeu vidéo vit sa Grande Mutation de la IIIeme Dimension. Ça tourne à la définition d'un OS complet, qui aurait les bon format de fichier pour tout ... qui serait moins lourd et plus convivial que Windows ... Je me retrouve à jouer le rôle de simple mascotte en attendant mon heure.

But even that was meant to end at some point. In 1997, as the PPP Team is about to split, Pype has gathered some assembly language tools and decide to start designing and building the Ultimate Game Maker, with high definition graphics (that is, 800x600 by then), millions of colours, hi-fi stereo Impulse Tracker modules with up to 32 tracks, parallax scrolling and large sprites with behaviour comparable to Super Mario World ... And the list keeps growing as the video game industry's IIID revolution is re-shaping the platforming genre. And rather of growing bottom-up, all this digs deeper and deeper towards the building of a full operating system kernel that could run either the game, or the development tools... And I'm left being a mere sketch on the logo, even though I'm at the top.


Et puis un jour, un coup de crayon un peu plus affirmer vient me sortir de l'oubli. A court d'idées de griboulliages en attendant un cours de réseaux, Pype se dit "pourquoi pas faire un mini-strip qui raconte le parcours de Bilou".

And then, all of sudden, a line of pencil draws me out of the shadow. Out of T-shirt design ideas while he's waiting for a course to begin, Pype wonders "why not a comic strip that relates Bilou's adventure ?". Old characters get a revamp, New non-playing characters appear, a back story grow up ... and a couple of pages appear on a website -- although it never quite turned out into a web comic. This is the first milestone towards an art blog that will then host some Nintendo DS sprite editor developments before this very blog spawns to bring me back to full activity.

Les anciens personnages se font un lifting. De nouveaux intervenants apparaissent... L'idée plaît. Un mini "web-comic" vient s'ajouter aux réalisations de la branche "demoscene" de PPP Team. Plus tard, ça tournera au blog et sur ce blog, on se dira que, quand-même, ce serait rigolo de se faire un Sprite Editor sur Nintendo DS .. la boucle est bouclée.





Tuesday, May 05, 2015

reverse emulator bug ?

Je connaissais le bug d'émulation. Vous savez, ce genre de bug qui ne se produit jamais quand vous testez sur émulateur et qui crashe lamentablement le programme dès qu'il tourne sur une vraie plate-forme (généralement parce qu'elle a de la vraie mémoire).

Why? I can explain easily a bug that happens only on bare metal, but not in an emulator, but this time, it's the opposite. I spent 3 evenings trying to figure out why the emulator crashed before I could explore any issue with DDD. However, on the Real Thing, I can play the game without any issue... 

If I find a way to re-build that emulator from its source, it could be interesting to implement a ring of last N jumps/calls so that we can actually track the reason of such crash. But do I still have the source+compiler combination do to so ?

Là, il semblerait que je viens de passer 3 soirées à tenter de comprendre l'inverse: un bug qui ne se produit que sur l'émulateur. Mais qui crashe l'émulateur, pas le programme émulé, sans espoir de placer des breakpoints ni rien de ce genre. J'avais fini par m'imaginer qu'un vrai "guru meditation screen" serait plus instructif que ce rapport de crash généré par desmume. Et euh ... rien. Pas de bug. Je fait les 4 niveaux deux fois, avec des morts ici et là. Sans que ça ne s'arrête. Au moins, le nouveau système de gestion de mémoire (merci, PAdM) m'a sorti d'un mauvais pas.

Saturday, May 02, 2015

attach/deleteme explain the double-free issue ?

There are a number of things that looks odd in the current animation management code. Why do we try to unregister a new animation every time we're done testing a special block ? How comes Engine::delanim() is invoked both at GameObject destructor and Animator destructor.


But that wasn't enough to fix the NastyBug I had, that jammed the game as you approached the end of level 1. At that point, I knew that some object -- the power-up at the end of the level -- was restored with a invalid state and animation. I mean, that wasn't even a true state. Parts of it made no sense, while other parts were perfectly sound. I wrote a safetycheck functions that confirm some memory area can be a valid GobState or GobArea, using virtual table addresses as a signature, then scanned every states when the level is ready.

But quite mysteriously, although all the states were valid, the powerup was still waking up with invalid state! In fact, I had *two* of them -- and that explains why the bug did not occurred when you'd beat the level at once -- that had the same identifier "33". One, listed from GameScript's static list of objects, and one that triggered the bug. You can guess what happened from there: the power-up actually survived the level reboot, but because I re-parse all the game logic when the level is rebooted, all the state machine that phoenix-object was referring to had gone, swallowed in the bowels of the memory manager, recycled into other parts -- which precisely depending on the number of inkdrops and other dynamic objects alive when the level is terminated.

I feel better now. It will take some time to come back to a list of things that need some polish, but at least, I can envision a release of School Rush soon enough.


Je pense avoir enfin mis le doigt sur l'horreur qui provoquait l'arrêt complet de Bilou: School Rush dès qu'un jeune joueur s'approchait de la fin du niveau 1. En fait, le power-up ajouté en fin de niveau était en mesure de survivre à la destruction du reste du moteur de jeu lorsque le joueur échoue. Une particularité liée au fait qu'il s'agissait d'un objet statique, mais qui n'était ni HERO ni EVIL. Résultat, dès sa ré-activation dans la "réincarnation" du niveau, il était toujours là, mais son environnement -- animations, machine d'état, etc. avait été réaffecté à un autre usage. Résultats: comportement incohérent du moteur de jeu, voire accès mémoire invalides et écran rouge "guru meditation" qui me pourrissait la vie depuis les premiers essais du "big punch"...

Sauf qu'il y a encore quelque-chose ailleurs ToT.