Wednesday, December 30, 2015

Je peux améliorer mon C++

Grande différence entre mon "nouveau" boulot (depuis Mars 2014) et mon ancien poste universitaire: ici, il y a des revues de code. Et mes collègues "Hergé et Jigé" ont un sacrément haut niveau en C++ comparé au mien. Alors autant profiter de mes deux semaines de "Super Papa Bros" pour essayer de remanier le code de mon moteur de jeu, le rendre plus fiable, plus lisible, et peut-être plus efficace.

J'avais introduit un mécanisme de gestion de mémoire inspiré du cours "compilateurs" : le "tank", avec un seul bloc de mémoire qui est découpé progressivement en sous-blocs qui auront tous la même durée de vie. L'ennui principal, c'est que ce "tank" n'a aucun moyen de retenir quels objets ont été créés ni d'appeler les destructeurs en fin de cycle. Du coup, tout objet "standard" présent dans les morceaux du tank sont une fuite de mémoire potentielle.


Parmi les "nouveaux trucs" appris cette année qui pourront m'être utiles, il y a la fonction "foreach", les fonctions template (et en particulier leur utilisation pour faire de la programmation assertive), les namespaces anonymes, et les structures-internes-pour-masquer-l'implémentation.


Let me collate a few C++ tricks I practiced this year and hope to use in my hobby tools/game engine to improve them.
If it make sense to have a function applied on all members of a collection, foreach can help:

- for (vector<Tire>::iterator it = wheels.begin(), e = wheels.end(); it != e; it++) {
- checkPressure(*it);
- }
+ for_each(wheels.begin(), wheels.end(), checkPressure);


Template function do exist. Template functions do not need their template argument to be specified when it can be inferred from function arguments. E.g.

template<typename T>
void assert(T a, T b, const std::string msg) {
  if (a != b) throw AssertException(msg);
}

can be invoked as
+ assert(myCar, TimeTravellingDelorean, "timed' out");
-assert<Car>(myCar, TimeTravelling ...);;

Template integers exist too. If you want something to behave completely differently depending on whether you're on a 32-bit or 64-bit system, you might consider the following function that can be invoked as getLibraryPath<sizeof(int)>():


template<int> path getLibraryPath();
template<> inline path getLibraryPath<4>() {
  return "/usr/lib32";
}
template<> path getLibraryPath<8>() {
  return "/usr/lib/x86_64-linux-gnu";
}

And as we're talking about templates stack overflow's question on puzzling template error messages can help.

You don't need to declare your functions static to avoid interference with other translation units of the program. Simply put them in an anonymous namespace.

You don't need to explicitly track the "object setup sequence" with an init_level if you can do it with contents of the regular members of the objects,


Car::~Car() {
- switch(init_level) {
- case TIRES_MOUNTED: RecycleTires();
- case ENGINE_INSTALLED: RecycleEngine();

- // FIXME: what do you do for default: ?
- }

+ if (tires!=UNDEF) RecycleTires();
+ if (engine!=UNDEF) RecycleEngine();

PS: UNDEF could just be 0 for pointers to components.

You can have compact structure initialization with (optionally-)named fields but it must be *trivial*, e.g.

  • you may not swap the order of components;
  • you may not omit a field if there are other field after it
  • but you *can* omit items at the tail of the description

If you want a class/struct to look more like a first-class citizen, think about
  • copy constructor : Car(const Car &that) : engine(that.engine), tires(that.tires) {}
  • comparison operator : bool operator==(const Car &that) { return that.tires==tires && that.engine==engine; }
  • ostream-compatibility: this requires a additional std::ostream& operator<<(std::ostream& os, const Car& that) { os << "powered by " << engine << " on " << tires; return os; } function. Note that it is *not* a member of the Car struct/class and that it will need to be declared friend of the Class in case of a class.


Something thrown as throw new std::runtime_error(..) is caught by catch (...) { releaseResources(); throw; }, but not by catch(const exception& e). That latest one only catch stack-allocated exceptions, e.g. throw std::runtime_error(...);. Reading more on this I should.

I should remember that namespace ds = PPPTeam::LibGEDS is the way to say import PPPTeam.LibGEDS as ds. And that ostream & operator << (ostream &out, const Complex &c) is the way to tell how the class 'Complex' should be printed.

Oh, and I shouldn't use std::unique_ptr on stack-allocated object. ever. unique_ptr will eventually call free on the pointer it holds.

 

In case of doubt on performance, remember that Quick-Bench.com does exist.

Tuesday, December 22, 2015

Usage: 15% ; Leakage: 12%

I guess you all know what a "memory leak" is. Well, you might not have a lot of gameplay updates in the following weeks: I just enabled a sort of report that measures how much of the state created when parsing the title screen of School Rush. 12%. I've got some code-cleanup to go through.

Bon, bin les premiers résultats de l'analyseur mémoire intégré à mon système de test-de-code-DS-sur-x86 sont précis, mais aussi assez effrayant: 12% de la mémoire allouée lors de l'initialisation de l'écran-titre ne sont pas rendus à la fin du niveau. Dans un cas pareil, la mémoire de la DS (4Mo) finit systématiquement par être saturée après un certain temps d'utilisation du jeu, ce qui ce traduira fort probablement par un crash.

Allez, joyeuses fêtes à vous aussi. (Et, euh, non, n'espérez pas trop une version "spéciale Noël" de School Rush avec de la neige sur les bancs et des bonnets à ponpon sur les gommes sauteuses, du coup)

PS: I suspect this could be linked to the migration of most state-machine data structure into the "tank" memory allocator: because the tank doesn't know objects themselves, and that it's quite unlikely that it invokes their destructors when "flushing" the tank. I'll have to make sure that structures that were pushed into the tank are flat enough or that their sub-components are allocated in the tank too.

Monday, December 21, 2015

Rayman Designer

Quelque-part en 1997, Ubisoft sort "Rayman Gold", avec un éditeur de niveau. Curieusement, je passe mon tour. Pas trop envie d'acheter une 2eme fois le jeu que j'ai toujours pour pouvoir avoir l'éditeur de niveau ? Pas trop envie de me contenter de faire des maps dans un univers qui n'est pas le mien et d'en être réduit aux seuls ennemis déjà existant dans le jeu ? J'avoue que je ne saurais plus trop dire.

Years before Mario Maker was Rayman Designer. I never owned it, and it never quite appealed me to play custom maps, although I loved very much the original game. It's a bit hard to say why, but I think it could be reduced to two things.

First, the core gameplay is different, and the player is asked to collect every ting (read "golden coin" if it was a Mario game) to reveal the exit of the level. Okay, I love it when you have something more to do than reaching the exit, but being forced to grab every whatever to complete the level always felt annoying. I already found it lame near 2001 when I played Rayman II and discovered that without collecting all the tings of the games I couldn't access the last levels. But here you have to collect them all *level per level*. Oh, okay, you can select levels freely, but still. And the "colored tings that open gates" felt artificial, even more abstract than typical "keys and locks" and much less integrated than Commander Keen's coloured keys.


Pas de cages dans cet épisode, mais des "tings" de différentes couleurs, pouvant ouvrir des barrières quand on a récolté tous les tings d'une couleur donnée. Du coup, le level design ressemble assez fort à un mélange entre pacman et rayman. Un aspect qui m'a assez refroidi du côté de 2007 quand j'ai découvert tout ça sur wiki.

The second thing .. what would player's level look like. I did some game making myself between 1995 and 1997, and I know people who got granted the super-powers of creating levels tends to build impossible missions that they only can beat (sometimes cheating like being the only ones to know that lava is not quite lava in the 3rd pool and that the player needs to dive there to get access to the end of the level). Checking youtube videos of "Rayman by his fans" proved that this was mostly not the case, but instead aspiring level designers forgot to hint on where the tings are to be found, leaving the player to explore the map again and again everytime some magic happened to make things appear or disappear, and ultimately rely on some flying potion to collect the last tings somewhere in the top of the map where regular platforming just can't let you get them.

Mais j'étais curieux l'autre jour de voir un peu à quoi pouvait ressembler les niveaux intégrés dans l'édition "Rayman Forever" -- niveaux de fans repris sur galette. Sont-ils du même tonneau que les missions impossibles de Mario Maker ?


Pas exactement. Pas ceux que j'ai vu, en tout cas. Par contre, il y a usage abusif de la "potion magique qui te donne des aileuus", présente presque systématiquement, et contrairement aux designers de Ubisoft, qui prenaient soin de guider le joueur vers la suite du niveau une fois qu'on a ramassé le "ting-qui-fait-apparaître-un-pont-quelque-part", on risque ici de devoir ré-explorer tout le niveau chaque fois qu'on entend la petite fanfare qui annonce que quelque-chose a changé. Bof pour moi, donc.

Tuesday, December 15, 2015

The missing frame.

Why is my backtrace-recording code not properly recording backtrace ? And the true question is ... is it really not back-tracing correctly ?
  • malloc < new() < __gnu_cxx::new_allocator < Vector_base < std::vector ... " is missing __gnu_cxx::new_allocator.
  • "malloc < new() < TestBasicScript() < main() is missing TestBasicScript.
  • malloc < GameScript ctor < TestBasicScript is complete. good.
  • malloc < operator new  < GameScript ctor < TestBasicScript < main is missing the ctor.
Having a look at the disassembled code explains already some of the things. For instance, remembering me that neither the constructor calls operator new, nor the operator new calls the constructor. No. The function constructing an object, TestBasicScript, calls both the "operator new" (_Znwj) and then the constructor.

Next interesting thing, operator new is systematically the function whose caller is missing. That can be explained if operator new itself is not creating some stack frame.

void TestBasicScript() {
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   56                      push   %esi
   4:   53                      push   %ebx
   5:   83 ec 20                sub    $0x20,%esp
/home/pype/DS/tests/BasicScript.cpp:6
  BufferReader *ir = new BufferReader("print \"hello\"\nend\n");
   8:   c7 04 24 0c 00 00 00    movl   $0xc,(%esp)
_ZN12BufferReaderD0Ev():
   f:   e8 fc ff ff ff          call     _Znwj
  14:   89 c3                   mov    %eax,%ebx
  16:   c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)
  1d:   00 
                        1a: R_386_32    .rodata
_ZN11InputReaderD2Ev():
  1e:   89 1c 24                mov    %ebx,(%esp)
  21:   e8 fc ff ff ff          call   _ZN12BufferReaderC1EPKc
_ZN12BufferReaderC2EPKc():
  26:   89 5d f0                mov    %ebx,-0x10(%ebp) 

Sunday, December 13, 2015

Emunit-testing

I am stuck with bugs in the two approaches I planned to use to allow shop-for-bonus in-between levels. Kind of bugs that are difficult to track with regular debugging, and that may even crash the emulator or the debugger itself.

http://problemkaputt.de/gbatek.htmSo it's time for me to start doing more professional testing on my code base, dropping rendering and things alike so that I have more control on memor allocation and objects lifecycle. For that I need that access to NDS registers can still be performed although it will be a regular x86 program running under linux. I thought I could use a custom linker map to force the declaration of a regular area where the registers are expected, which you use with -T linker-script-file. But being sure that all of C++ sections will remain in place might be harder than creating a custom layout for an operating system kernel.

http://sourceforge.net/p/dsgametools/hg/ci/c3d54a0c1b14173735513f8227cdd2f8f93d6645/Hopefully, the memory map is somewhat compatible with the default locations for a 32-bit linux process. A few mmap calls and I can have valid read/write memory mapped at the place where NDS registers are expected. That should be all I need.

I will need to track what memory area are still alive after the end of a level, to know whether some could still reference dead objects and lead to memory corruption. I'll need too, to know who allocated such block so that I can understand their nature and purpose. I remember of Tim Robinson explaining how he embedded a call trace leading to *alloc. I'll try and do the same. It's not quite completely working at the moment.

Friday, December 11, 2015

Handmade Hero

I discovered "Handmade Hero"'s channel promotion. It sounded like something I'd love. A game from scratch, coded day after day. Still, I'm disappointed. So many videos on side topics such as font alignments, debugging techniques, etc. Titles doesn't say a lot on what is happening, we see text editors most of the time during explanations. Things could easily be clearer to follow. Sessions are quite long compared to Bisqwit's coding speedruns, and to be honest, Youtube lists doesn't get as useful as a cloud tag.

Ç'aurait dû être une super découverte. Un gars qui veut faire son moteur de jeu lui-même, "à l'ancienne" ... qui s'y met un brin tous les jours. J'ai essayé quelques vidéos, certaines qui m'ont fait réfléchir, d'autre nettement moins.

J'en viens à me dire que la vidéo n'est pas un bon média pour ce genre d'information. Trop difficile de passer d'un sujet à l'autre. Presqu'impossible de retourner sur l'élément précédent. Une base de code de la taille d'un moteur de jeu, il va y avoir une énorme partie qui n'apparaît pas à l'écran. Je doute fort qu'il soit possible de garder ça en tête au rythme d'une heure et demie par jour.

You see, that's why I keep opting for homebrews. True gaming hardware makes it easier to focus on what makes a game a game. Sure I can write a pitch bender or a volume adjuster. But I like it so much more when I have mixing hardware instead.

Wednesday, December 02, 2015

Spherical Goats

C'est une histoire qui commence dans les années '90 lorsque mon frère fera tourner pour la première fois le jeu "Spherical" sur C64. Il s'agit d'une sorte de puzzle-platformer, où le joueur (incarné par un sorcier à barbe blanche) transforme son niveau (en créant ou détruisant des blocs) pour guider une boule vers la sortie.

Je n'y aurai pas joué beaucoup, puisque c'est systématiquement sous le nom "Wizball" que je le cherchais dans la pile de floppies récupéré de chez nos copains qui quittaient l'ère 8-bit. Je ne l'aurai jamais vraiment reconstruit non plus: un jeu de puzzle qu'on fait soit-même, c'est rarement aussi intéressant qu'un jeu de plate-forme qu'on fait soit-même. Pourtant, dès les premières images, j'ai été subjugué par le genre, tout nouveau pour moi.

I wish I had more opportunities to play Spherical on my C64, back in the '90s. I loved that grid-arranged puzzles with simple mechanics. I loved how it combined with self-moving objects to bring an extra layer of deepness compared to what pencil-and-paper puzzles could provide. Nowadays, I guess I could run Escape Goat 2 and support Ian Stocker in his indie game adventure. There is a lot of very interesting game mechanics at work, and a nice extension to the classical push-me, blow-me blocks I'd put in a Logic Labyrinth.

C'est une histoire actuelle, aussi puisqu'elle parle de Escape Goat 2, un jeu indé sous le feu des projecteurs de RealMyop et CoeurDeVandale. On y retrouve ici aussi niveau très en carrés, avec des blocs qu'on va déplacer pour se frayer un chemin ... même si c'est beaucoup plus indirectement.

En fait de sphère, la chèvre manipule ici Henri la souris, partiellement immortel, capable de déclencher pour nous les interrupteurs des nombreux mécanismes, d'arrêter les tirs d'ennemis etc.

Je note
  • des blocs-caisses qui se font détruire par les blocs qui tombent, mais qui peuvent aussi retenir les même blocs alors qu'il n'y a rien sous la caisse.
  • des interrupteurs qui sont activés par n'importe quoi, et d'autres seulement par le joueur.
  • des blocs-circulaires qui continuent sur leur lancée une fois mis en route, comme dans Johnny Biscuit d'ishisoft.
  • des blocs que les tirs des ennemis font exploser ou brûler de proche en proche.
  • des blocs qui glissent et écrasent les monstres façon Boulder Dash.
  • du sol qui s'écroule ... de proche en proche.
  • des portes à sens unique ... avec ou sans fermeture automatique.
  • un monstre qui peut pousser les blocs que le joueur ne peut que faire tomber 
Côté graphique,  j'aime beaucoup la présence de gros engrenages, à l'arrière du décor, qui se mettent en mouvement quand les interrupteurs provoquent le déplacement en cascade des blocs mobiles.

Sunday, November 22, 2015

La progression

Peu de chance que je clôture School Rush avant fin 2015. Mais par rapport à ma todo list de janvier, je pense que j'ai plutôt bien avancé. Il reste encore beaucoup à faire, mais le point sur les power-ups touche presque à sa fin. C'est surtout sur le feedback au joueur, et la gestion de l'écran tactile que ça va se jouer, maintenant.

Compared to the state at the start of year 2015, the core game is ready. What still lack is feedback, a bit more of polish on the gameplay and level design ... and integration of the hand-drawn art to bring flesh to the bones with a storyline, an ending and those kind of little things that draws the line between a game and a demo. That's not gonna be packed within a month or two, I'm afraid.

Oh, btw, I wish so much phabricator we use at work could render tasks dependencies on such a graph.


Plus pratiquement, avec la migration d'OS sur mon laptop combinée à la migration de SVN à mercurial, je me retrouve avec 3 ou 4 emplacements sur lesquels les développements se sont étalés. J'ai commencé à rassembler tout ça vers une seule tête. Ça commence à reprendre forme. Heureusement que j'ai eu un bon entrainement sous la houlette de "Hergé et Jigé" (pas les dessinateurs, bien sûr).
With a recent home directory switch and a migration to mercurial, my first task is to bring all those experiments into the tip of the source tree. It wasn't trivial but I think I'm almost done now.

Monday, November 09, 2015

Quelle récompense pour le joueur ?

Dans la série "déterrage de vieux topic", je tombe sur la question de Nawak: comment récompenser le joueur?. , une question qui rejoint la quête du bon power-up et la compréhension des bonus.

Il est facile de donner au joueur des pouvoir supplémentaires. Dans la plupart des jeux que je connais qui utilisent des pouvoirs modulables en intensité ont tendance à les utiliser pour titiller le joueur, comme récompense pour un effort donné, en quelque sortes. Ou du moins, on aimerait le considérer comme tel.

Last week, when I was reading "now try a more difficult quest" on SMB1 end screen, with Mario being kissed by the lady, I thought they meant something metaphorical. Like 'get a life, find your own princess, please her and receive her kiss. Good luck'. A friend's wife completely surprised me talking about a "second quest" in SMB1 where all goombas were turned into fire-proof buzzy beetles. Could I have missed that for that long ?

There was an argument about giving rewards to the players, and whether the power player could feel bored of receiving an additional fire power when she never lose it because she rules at the game. It sounds artificial to say 'well, if she wants a challenge up to her skills, why don't she ignore the fire flower altogether ?'. Switching goombas to buzzy beetles essentially produces the same sort of effect: you still get the power-up, but its use is reduced.


Here be Goombas.
Pourtant, si je prends SMB1 ou SMW, le bon joueur est récompensé par ... un jeu plus dur. Voire (dans le cas de SMB1) une variante du jeu où un des power-ups les plus puissants devient inefficaces sur les ennemis les plus communs, les goombas étant mués en tortues ignifugées (merci à l'épouse de JB pour le tuyau ^^"). Et si on y réfléchit bien, ils sont légions les jeux 8-bit et 16-bits où les niveaux "bonus" étaient bien plus durs que les niveaux "normaux". On se voit par contre assez mal placer dans un recoin du niveau un switch qui fait tomber des ennemis pour "récompenser le bon joueur avec un challenge plus à sa hauteur".

Double-checking the level layout of SMB1 levels, however, make me doubt about the whole idea that "power-up are a reward to the dare player". Coins do have this effect. But power ups ? When there is some risk in going for the power-up, it is in the sense that you may encounter ennemies crawling on the ground, and could have gone over the collection of blocks safely otherwise. Compared to Commander Keen's "dare-to-catch-bonuses", this is almost a joke. I don't see it much more "risk/reward" in world 5. Simply that the amount of P-UP to find is strongly reduced.



C'est vrai qu'augmenter la puissance de l'avatar ne marche qu'un temps ... avec le joueur qui n'a pas le niveau requis pour battre le jeu, en fait. Quelqu'un qui termine SMB1 en une vie en petit Mario n'a que faire des fleurs de feu, des pièces d'or ou des 1-UP. Est-ce à dire qu'il ne jouera plus au jeu ? Pas forcément.

De même que le fait de bien maîtriser un morceau de musique sur un instrument ne veut pas dire que vous ne le jouerez plus. C'est plus ou moins la raison d'être du speedrun.

Pour donner envie au joueur -- même aguerri -- de prendre un risque pour atteindre un power-up, on peut faire en sorte que les power-ups soient d'office limités dans le temps, celà dit, au même titre que la super-étoile. SMB3 va un cran plus loin dans cette idée avec les étoiles que l'on peut enchaîner sur toute la durée du niveau à condition d'avancer suffisamment vite.

J'avais déjà noté que donner plus de contrôle au moment où le power-up est utilisé. Ce petit détail qui fait que l'objet le plus recherché dans l'univers de Zelda est peut-être bien ... un flacon de verre. Eh oui, le Félix Félicis serait de bien faible utilité si on avait pas le choix du moment où on le boit...

La réflexion n'est pas achevée, donc en guise de conclusion, je dirais "le joueur est là pour s'amuser. Si tu veux le récompenser, donne-lui du fun". Ce n'est pas tant les 10 pièces d'or d'une cachette qui rend les tuyaux secrets intéressants dans SMB1: c'est le fait de pouvoir les chercher. Si on veut récompenser un joueur pour avoir trouvé le passage-secret-dans-le-passage-secret, le mieux sera de faire en sorte qu'il ait l'impression que l'endroit qu'il vient de dénicher est spécial. Pas forcément parce qu'il contient une vie, mais par son look-même. Je pense à la pyramide interdite de Keen. Et pour les nouveaux Mario, c'est aux pièces étoiles et aux pièces rouges qu'est attribuées la mission de récompenser le joueur audacieux, certainement pas aux power-ups.

Friday, November 06, 2015

... interlude ...

Bon, j'avoue ça n'avance pas très vite ces derniers temps. Une petite modif' par-ci par-là pour les animations de l'encre qui tombe. C'est à peu près tout. C'est que je me suis senti interpelé par les citations de Level Up du genre

« Le temps et le travail qu'un RPG demande explique pourquoi la plupart des jeux amateurs ou indépendants sont des jeux principalement d'action, de plate-forme, de réflexion, bien plus faciles à gérer. » - Zim
ou
« Ce jeune a compris en quelques jours ce que certains mettront des années à accepter : il est quasiment impossible de créer en amateur un bon rpg. »  - Gaetz


Du coup, j'ai eu envie de comprendre: qu'est-ce qui fait qu'un RPG est un RPG et qu'on y joue (ou pas) comme à un RPG? Qu'elle est la quintessence d'un RPG ?

Je n'ai pas la réponse ultime, mais j'ai au moins compris quelque-chose qui me semble fondamental: c'est le temps perdu pour son avatar qui le rend si important au yeux du joueur.
Dans un Zelda/metroïd/mario, on sera attaché à l'emplacement jusqu'où on est allé, mais on ne se retrouvera probablement pas dans la situation de se dire "wow. J'avais jamais eu d'aussi bonnes armes dans ce jeu" si on l'a déjà fini.

Par son côté aléatoire et le fait que les caractéristiques du héro découlent des choix du joueur, le RPG peut rendre le héro unique et précieux au yeux du joueur. Enfin je crois.

Every new visit on the 'Level Up' forums greets me with a quote. And the one about "RPG requires so much time and work. This is why most amateur or indie games are mostly action, platforming or puzzles, which are much easier to manage" pushed me into introspection mode. In many short-development projects, being succesful implies capturing the _essence_ of the corresponding gameplay, and focusing on what's part of this essence. But what is the essence of RPGs ? My deepest thought so far is St-Exupery-like: 'the time you lost for your avatar is what makes your avatar so precious to your heart'. That makes it apart from zedla/metroid/mario games where the _place we reached_ is what we value, not the state of the ever-dying-and-respawning avatar.

edit: just stumbled upon ihobo's blog post of 2015 who seem to be talking of the same issue. 

@Anokolisa's project
edit++: Anokolisa might have just captured it by shrinking navigation and scenery to a connected network of locations where things occur, and giving just a little of lookahead/look-aside to allow for planning.

That will still require plenty of art to be drawn for the various encounters and collectibles, of course.

Saturday, October 31, 2015

Undefined behaviour ...

Adding a few sound samples for Bilou's jumps shouldn't have led the game to crash. Really. It shouldn't have. And yet, it had. And with a flavour of deja-vu ...

I was using the back() of a std::vector while there was nothing pushed yet. And this is undefined behaviour. My C++ skills still need training. It coud explain my un-ability to produce .nds files working on real hardware when building them out of the good-old-directory.


Oh, le vilain bug que nous avons là. Un pointeur négatif ? Alors qu'il devrait provenir d'un vecteur de régions allouées précédemment ?_? Le vrai hardware de la DS n'aime pas du tout ça, bien sûr. Ce désassemblage a un air de déjà-vu, et pourtant, je suis surpris de ne pas avoir trouvé la raison du problème jusqu'ici, tant c'était évident. Enfin, une fois qu'on a pris le temps d'aller lire la doc de vector::back() et qu'on a souligné trois fois en rouge "comportement indéterminé" dans sa tête.

En clair, "comportement indéterminé" signifie que le résultat va dépendre d'autre chose que juste le code que vous avez écrit. Il peut s'agir de l'emplacement précis où le code se trouve, de ce que fopen a mangé ce matin, de l'âge du cache-pitaine ... n'importe quoi. Et donc on peut très bien avoir un nouveau sample dans les effets sonores qui tout à coup fait crasher le jeu.

Vous me pardonnerez le côté auto-flagellation de ce post: j'ai besoin de pouvoir me le rappeler à mon moi-du-futur.

Sunday, October 25, 2015

segfault.

J'ai tenté une des deux approches me permettant d'avoir une animation d'attente pendant le chargement des niveaux. Et c'est un échec. L'émulateur se plante sur une instruction non-définie en cours de chargement du niveau 1. Le débuggeur fait crasher complètement l'émulateur avant même d'avoir atteint cette instruction.

Failed attempt to have some background task running while level loading is in progress. Something simple like moving some sprite on the bottom screen, playing samples to count the score, etc. But it changes quite a lot the execution context for the loading, and as of writing, it makes the emulator crash when loading level 1 and the debugger makes it crash even earlier. That's a job for some automated testing and I have plans to bring such techniques to my DS development since I had the opportunity to see it in action at work.

Je pense que ce serait un cas de figure à étudier avec l'approche de tests automatique inspirée de mes travaux au boulot, avec une couche d'abstraction du matériel pour que le test se passe en natif sur le PC. Mais c'est un peu gros à mettre en place: je préfèrerais que ce genre de développement ne mette pas en attente le jeu "school rush". Il me reste une deuxième piste à explorer succeptible de tout simplement raccourcir les temps de chargement: permettre de réinitialiser la map et la position des ennemis sans ré-interpréter l'entièreté des machines d'état.

Yet, I have another approach I could follow, which would make the whole loading process faster. I think I will try this first, and fall back to the auto-testing system if that doesn't work either.

PS: bonne nouvelle pour les lecteurs francophones: le message sur les bonus a été traduit.

Saturday, October 24, 2015

Pourquoi des bonus ?

They are good-looking, they balance the colours of the level while giving the golds some good reason to attract player's eyes. They are the bonuses. They make friendly sound when you collect them, but as of writing, that's pretty much it. In the previous "anniversary level" game, bonuses had a puprose: they measured how well the player explored the game and rewarded her with a deving history treasure.

There are too many of them in School Rush to keep that "completion gameplay" idea. The game is too large, too. The "completion goal" was inspired by Prehistorik 2 one-level demo and how having hidden bonuses and a completion percentage at the end of the level kept us playing the same 5-minute level for days and days.


Ils sont bien brillants, d'un joli jaune qui attire l'oeil et complète le spectre des couleurs du jeu School Rush, et sont plutôt plaisants à ramasser. Il s'agit bien sûr des lettres-bonus. Pourtant, à l'heure actuelle, ça s'arrête plus ou moins là. Si dans le niveau anniversaire ils permettaient au joueur de découvrir une image plus ou moins vieille selon le niveau d'exploration et d'exécution atteint (un rôle inspiré de la démo de Prehistorik 2), je ne sais plus rien mettre de tel ici: les bonus et les vies sont trop nombreux(es) pour que ça puisse avoir un sens. Le jeu est trop long, aussi. Alors bien sûr, le jeu étant exempt de 1-UP secret, je peux proposer le classique "100 lettres contre une vie", mais j'ai envie d'aller un peu plus loin que ça quand-même. 

With only 3 lives at the start of the game and no 1-UP hidden, they could receive the obvious purpose of granting one-ups if you collect enough of them, but I wanted to offer a little bit more than this. Chatting a bit with my brother -- who suggested that they could slow down ink rise, and possibly even inverse its flow -- lead me to thinking that they would indeed turn 'cool' if they allow to counter something that the player could think "unfair" from the game.

And at the time, the most unfair thing I can think of is the fact that falling in the ink make you lose all the power-ups you had collected, so because the coins are preserved from level to levels and even through failure (Kirby Kid call that suspension), they can be used in a sort of shop where the player can re-fill her stock of power-ups.

When can we enter that "shop" ? When can the player use what she "purchased". This will have an important result on how valuable the 'shop' feature (and thus, the letters themselves) are to the player.

Mon frère m'avait suggérer de ralentir l'encre en fonction du nombre de bonus récupéré. Je n'ai accroché qu'à moitié, mais il y a là-dedans un point essentiel: faire en sorte que les bonus donne au joueur la sensation que le jeu est moins injuste quand il en ramasse que quand il les ignore. Et quoi de plus injuste dans le "School Rush" actuel que de perdre tous les power-ups durement  gagnés parce qu'on est tombé dans l'encre. Le nombre de lettres ramassées, lui, est préservé à travers les niveaux et les échecs, au même titre que les pièces d'or de Super Mario. Pourquoi donc ne pas en faire une monnaie d'échange pour que le joueur puisse récupérer certains power-ups entre deux essais ? Reste à déterminer quand et comment.

  • I want something that allows me to definitely remove the "auto-granted power-ups" from the title screen, as they proved perplexing for the players.
  • I opt for some inter-mission shop. Trading level-collected bonuses against level-useful power-ups takes place between play sessions, as a way for the player to take a break.
  • I opt for something that is not automatic: the player can chose not to receive a 1-UP and save her letters for more power-ups for the later levels as she thinks it would be a better strategy.
  • I opt for something where the player doesn't need to _beat_ the level to enter the shop. It's there between play sessions, not between levels. I feel it essential so that the player gets the indemnity feeling after a mistake.

Je sais que je veux permettre au joueur de choisir sa stratégie. Pas de vie supplémentaire automatique: on doit pouvoir garder ses 100 lettres pour s'offrir plus de power-up dans le dernier niveau si c'est de ça dont on a besoin pour finir le jeu. Je veux aussi que l'on ne fasse l'échange qu'en dehors des niveaux, mais qu'il soit possible de "racheter" des power-up même quand on a raté le niveau, pas uniquement quand on en change.

L'habillage de ce "magasin à power-up" est venu par après. J'ai bien ri en moi-même comme j'imaginais Bilou pendu à un marque-ta-page, nourrissant le livre de lettres pour atteindre l'élément convoité. Il ne restait plus qu'à trouver une disposition livre/marque-ta-page/bonus/Bilou qui soit telle que le joueur comprenne immédiatement qu'il ne peut y avoir qu'un seul achat par choix.

Voilà pour l'idée. Maintenant je dois coder tout ça.

I started considering what the 'shop' should look like in a big laugh, as I visualized in a flash Bilou hanging at a bookmark, feeding the book with collected letters to make the bookmark move and reach the selected item. While peeling vegetables, if you ask. If you're serious about game design, make sure you have vegetables to peel. A lot of them.

This had to be refined. For the player to accept this idea, it must be obvious that only "paying back" the book is the only way to reach the bonus. It must be obvious that there's a choice to do, and that no smart movement should allow to grab several items at once it physically impossible, not an arbitrary restriction. Having the bookmark dragging Bilou upwards, for instance, doesn't work well, because Bilou has the Jump Power and reaching items hidden high is something he's got many options to do.

Now I have to address the technical aspect of it:

  • [todo] the action must take place while the next level is being re-loaded. 
  • [todo] Animation is involved
  • [todo] player clicks what she wants
  • [wish] letters flowing to the book are the ones you collected in the level

Saturday, October 17, 2015

Palettes fix

With this fix to GameScript's graphic chip initialization, SchoolZone's colours are back to normal despite the new ink pipes tiles that use the same colour numbers as the browns used for "owl background". I thought at first that I was using a too small memory bank for extended palettes, but no. VRAM_E_LCD is 64K and only 32K are used when mapping as VRAM_E_EXT_PALETTES. But I wrongly set "BG_WRAP" while tile planes are always wrapping (unlike bitmap planes), and for the plane used for the owl background, it forces sharing of the palettes of the playground plane.

Voilà. Une vieille erreur dans l'initialisation des plans de décor de corrigée, et mes couleurs sont enfin comme elles le doivent sans "couleur interdite" pour l'avant plan. Je vais pouvoir passer à la programmation des bouchons et des vaguelettes.

Et au passage, je retombe sur un outil en ligne de planification pour la mémoire vidéo de la NintendoDS assez pratique. Voir dans les commentaires pour ce qui me semble le plus intéressant pour la suite du programme.

Saturday, October 10, 2015

School Rush Story

Bon, mon jeu n'a pas la reconnaissance de Rick Dangerous, mais il y a une ressemblance amusante avec les croquis de Simon Phipps.

The idea of "turning off the ink" starts to get real. With some details on the level design, I hope to be able to explain "why is there so many ink here", and "what happened to turn something normal into something dangerous. Time for some more Pixel art ...

edit: Got fair art drawn, but unfortunately, I'm using the few 16 colors (same as the inkjets), which happen to be trashed by the background art in the current code. There is no good reason for this to happen, given that we have now extended palettes (16*256 colors for every individual plane). I'll have some code-digging and potenially refactory time ahead.

Edit: ok. Cork switch closes the level. It doesn't let you see ink draining away from the pipe, though.

Tuesday, October 06, 2015

pixel art waterfall

I will need something that shows where all that ink comes from, and build a story about getting the School Zone a dry place again. It is not so easy to come with pixel art liquid flow, but I know from a while that iSohei did a great job drawing some. In my case, the narrow and straight flow is possibly the best choice.

The flow is rendered here by a highlight area in curvy and noisy v-shape that twists left to right as it moves down. The picture here shows the individual frames of the animation when vertical movement is canceled.

I could have that with a sprite shot from the top of the waterfall over some otherwise static ink area. I could shoot _two_ of them simultaneously, but that moves down at slightly different speed so that you get the illusion of a wave that widens as it falls down, too.
well ... now it's analyzed. Let's make it so.


Bon, j'ai fait une première tentative désastreuse pour animer une chute d'encre (indispensable pour le dernier niveau de School Rush). Puis une deuxième encore pire... alors je retourne chercher une référence de "Pixel art waterfall" pour voir ce que je peux faire. Le mieux, ce serait sans doute d'appliquer la même technique que iSohei pour sa troisième cascade: un sprite en forme de v qui se tortille en descendant. L'avantage c'est que je pourrai alors utiliser un vrai sprite et avoir une animation d'autant plus fluide.

Edit: coding attempt: having the falling wavelet 'rewind' to the top of the fall/pipe when reaching the ink is nice, but is not sufficient because 'the ink' is actually there only when the 'inkfall' is on-screen. Remember ? ink waves GOBs follow the camera.

Saturday, October 03, 2015

Confirmation pour Double-B(ig-punch)

Petite soirée chez les parents de JB, console en poche. J'y retrouve N, A et L de la S-team, mon équipe de beta-testeurs attitrés. La nouvelle technique de "planer en gardant le bouton enfoncé" est adoptée par tous. Les nouvelles trajectoires pour le lancer n'ont perturbé personne et ont permis aux nouveaux-venus de récupérer pas mal de power-ups alors que jusque là, les P-UPs laissaient plutôt les joueurs indifférents.

Presque tous les plus jeunes, à l'instar de Zim, essaient de continuer à ramasser des taille-crayons même après avoir gagné "Big Punch". Ils se placent juste sur le blador et appuient sur B encore et encore, ajustant leur position. Mais sans se rendre compte que Bilou ne ramasse plus rien dans ce cas-là. Inévitablement, les pieds du blador se rapprochent, il se réveille et blesse Bilou, souvent plusieurs fois d'affilée le temps que le joueur comprenne ce qui lui arrive.

Je peux soit faire en sorte que un coup de poing nécessite un double-B ou veiller à ce que donner un coup de poing dans un blador assomé le ramasse ... mais il faut que je fasse quelque-chose.

S'accrocher aux éponges est passé pas trop mal chez le nouveau joueur après que je lui ait dit que

  • oui, on peut grimper dessus
  • tu tiendrais mieux dessus si tu t'accroches
  • j'ai dis "tenir dessus". Là, tu essaies de l'attraper par en bas. 
Il y a un petit coin du niveau 1 ou j'ai placé quelques lettres qui mênent du balancer d'une éponge à une plate-forme en hauteur, c'est un bon moyen pour aider un joueur inexpérimenté à réussir cette action pourtant fort délicate.

This week-end featured some social beta-testing session with kids between 7 and 15, including the S-team. Compared to earlier release of the game, the power-ups were much more used and seeked by the players. The "straight-throw" mechanism was set as default throw and it pleased the players. Only the eldest player asked me how the former "ballistic-throw" could be achieved and used it in a few place when short distance was preferred.

I take note that young players will tend to stick on "pick up bladors" even though they gathered a BigPunch power-up. With the current mechanics, however, they will stun the blador again and again with no effect, wondering why they can't pick up that blador now, getting closer, and completely missing the facts that blador's feet are getting dangerously near. When the blador finally wakes up, odds are high that Bilou will be recovering a BigPunch blow and that he'll get hit by the blador's move, no matter how fast they spam the B button. I think this stems for BigPunch invoked by a Double-B mechanic while single-B remains "pick up" through the whole game.

The alternative would be to ensure that punching a stunned blador means you pick it up. It sounds both more perplexing (you lose the mechanic's individuality, which is an important factor of cleanness)

Wednesday, September 30, 2015

Deuxième essai pour StraightThrow.

Je n'ai pas grand-chose de solide à opposer au commentaire de Zim comme quoi le lancer de School Rush manque de punch. En fait, en voulant faire les petits dessins-tutoriels pour l'action "lancer un taille-crayon", je me rends compte que la seule façon de le montrer, c'est avec un taille-crayon qui part en ligne droite vers sa cible. Un "Straight Throw", en somme.

Je fais donc un essai de gameplay: B fait un Straight-Throw, UP+B fait un Classic-Throw. Ainsi, je fais du cas de figure le plus important l'action par défaut tout en donnant de la marge pour planter un blador sur un crayon ou placer une SpongeBop pas trop loin dans l'encre.

  • [done] rebondir sur un ennemi pourrait faire sauter plus haut
  • [done] lancer manque de punch (ça ne va pas très loin), si l'on pouvait contrôler la distance et la direction rendrait le maniement plus jouissif (l'impression de faire ce qu'on veut)
  • [done] lancer en pleine course pourrait augmenter la portée du "projectile" (il me semble que c'était pas possible)
Lancer plus fort en pleine course ne donnait rien avec le Classic-Throw, parce qu'il devenait impossible de juger de la trajectoire. Avec Straight-Throw, ça ne devrait plus être autant un soucis, et ça encourage le joueur à prendre de la vitesse, ce qui est le point central de School Rush.

Remember I said "straight throw" as a power-up didn't convince me ? Yet when it is time for me to illustrate "you can stun pendats with a blador", what naturally comes out is a straight throw. So it seems Zim wisely pointed out the lack of power in the current (classical) THROW. I changed the way impulse from Bilou is conveyed to thrown items so I can have "straight-throw" by default and "classical throw" on-demand with UP+B. That feels much more natural in this game, altough less original and possibly less suited to the Big Adventure that is yet to come.


Edit: I'm not sure players will feel that the blador is thrown further as they move faster, but at least they will not get the feeling that they're reaching it back.  Another mechanic to change in a similar way would be to require double-B to use Big Punch.

Note to future self: remember how you spent displeasant hour trying to figure out the reason for a Guru Meditation after you compiled this TryThrow.nds from the mercurial sources in Trusty Tahr. Remember how you promised yourself to spend at least equivalent amount of time on a "build.sh" script that would make the start-of-work from a fresh hg clone reliable.

  • [done] update spons.cmd.c so that it also obeys two-dimensional impulse as the bladors do.
  • [done] merge in "hang-on-spons" when Bilou miss an AIRHOP auto-move.

Saturday, September 26, 2015

1st Mercurial Commit

Oh, the first one for this hobby project, I mean. I'm using mercurial happily for about 18 months at work. It is smoother to use than git, to my taste.

And it brings a first step for the "quick navigation" widget, that is the rendering of the map. It just need to be turned into a widget and migrated to the right window.


Bon, bri-coder un outil supplémentaire pour mon éditeur de niveau assis dans les escaliers parce que c'est le seul bon endroit de la maison pour le faire, ça faisait longtemps ... Mais les enfants voulaient jouer dans leur chambre, et rentrer trop dans la chambre, c'était devoir refuser "la vie la vie" sur youtube toutes les 2 minutes.

Par contre, cette fois encore, il manque criamment un mécanisme permettant à plusieurs contextes (les 'windows') de collaborer à travers une structure de données ou un widget commun. 

Oui, j'abandonne SVN au profit de Mercurial, avec lequel je me sens désormais bien plus à l'aise. Et puisqu'il me faut lâcher ma LTS de 2010 pour me risquer en Trusty Tahr, j'en profiterais pour basculer en bash et définir EDITOR=vim dans mon profil, au risque de choquer ceux qui ont fait de l'admin système avec Sheriff... 

PS: on ne laisse pas vim pourrir ses fichiers en jouant au sauvage avec les tabulations

Tuesday, September 22, 2015

Magic Feet ?

Je cherche un moyen pour que le joueur de School Rush voie immédiatement s'il a un power-up ou non. Il y a bien sûr l'idée géniale de mon frangin d'utiliser l'écran du bas pour montrer les possibilités que Bilou gagne au fil du jeu. Quelque-chose, si on utilise l'habillage d'un "livre d'histoire", qui se marie assez bien avec les bonus-tutoriels que je cherche aussi à ajouter.

The next Big Thing I truly need to bring into School Rush is a way to view which powers Bilou can currently use. That's something Zim pointed out. That's something latent (you remember how the S-Team wasn't using power ups at all) since I introduced the power ups. I keep thinking that my brother's idea of using the bottom screen is a great way to avoid tutorial texts/screens. But I'll need something more.

Mais ça me semble incomplet. Il manque quelque-chose de visuel. Mais pas des petites ailes dans le dos, ni un chapeau à la Kirby. Pas non plus une sorte de bouclier élémental à la Sonic 3 ... Pas de changement de couleur à la Megaman. Rien de tout celà ne serait compatible avec le personnage que j'ai en tête. L'ennui, évidemment, c'est qu'en fait rien de ce genre n'a été envisagé dans le design d'origine, sauf peut-être les lunettes noires qui accompagnent l'astro-flasheur. Ce n'est pas vraiment une surprise: les pouvoirs de Bilou n'étaient pas prévus alors pour être temporaires (plus similaires aux missiles de Samus que de la fleur de feu de Super Mario, donc).

I know I don't want color swaps like in Megaman, nor little wings (Kirby-like) or a sort of colored shield (Sonic-like). That doens't fit my own perception of Bilou's character. I could accept, however, blinking magic feet or blinking magic hands, with trailing sparkles. It doesn't look too bad on this mock-up. I'll dig further how to properly implement that knowing that the multi-palette technology makes it a bit harder (requires memory un/re-mapping synchronized with screen updates).

Je fais donc un petit essai. Des pieds légèrement brillants et qui laisseront derrière Bilou de petites étincelles vertes pour le pouvoir 'FLOAT' alors que 'BigPunch' fera pareil avec les mains et de petites étincelles bleues. Il faudra sans doute quelque-chose d'un peu plus calme mais je crois que ça pourrait marcher.


  • [cancelled] given the GameEngine structure, I'll have to register a post-vbl callback
  • rather opted for custom idle animations

Monday, September 21, 2015

L'avis de Zim: définir l'animation

Deuxième point du feedback de Zim:

Mon conseil serait de mieux faire comprendre par l'animation du perso sa panoplie de mouvement, développer les actions d'attraper et sauter, supprimer celle de frapper (peut-être courir), et de faire en sorte que tout cela soit impeccable (actions qui sortent de manière fiable, pas de bugs de collision, etc.). Un jeu de plateforme est excellent lorsque c'est un plaisir intuitif et immédiat de manier son personnage, il faut vraiment insister dans ce sens.
- attraper en l'air est possible vers le bas (je l'avais compris avec les nuages), mais pas vers l'avant, même si on n'a pas encore ramassé le power-up
- attraper pourrait être boosté en l'action rendant multi-directionnelle (si vers le bas et les côtés, pourquoi pas vers le haut) et également peut-être en augmentant sa portée au moins un peu

Avec ces mains-en-plasticine, c'est vrai que Bilou ne montre pas particulièrement fort ce qui se passe lorsqu'on essaie d'attraper quelque-chose. En relisant les propositions de Zim, je me rends compte aussi qu'il peut y avoir confusion entre ramasser et s'aggripper, qui sont en réalité deux actions distinctes mais proches au niveau du gameplay. Un "air grab" permet de faire l'un ou l'autre selon l'objet considéré. Un "ground grab" ne fait
Ramasser, premier essai. Trop lent.
Ramasser, version actuelle. colle bien au hit-boxes de l'action.
Attraper en l'air, qui se concentre sur la direction "vers le bas"
Pour le "gros poing", la main de Bilou enfle et ne laisse aucun doute sur l'interprétation du mouvement, mais ici, la main utilisée pour "attraper / ramasser" pourrait aussi bien mettre un uppercut. Ma première réaction est "oui, mais le gros poing est un pouvoir spécial. Il faut que Bilou sans ses pouvoir ait l'air de ne pouvoir compter que sur son astuce et son courage".

What if Zim@alexzone and I do not have the same understanding of a "multi-directional" action. I thought so far that 'AIRGRAB' is multi-directional in School Rush, because when you press B mid-air, there are 3 directions checked for something to grab: in front of you, below you, and behind you. Those three areas are supported by the places where Bilou's hand move during the attempt to grab things. But multi-directional could also mean "you pick which direction the action takes place using your d-pad".

This is clearly not the case for air-grab. It would make sense for a wider-range grab, which Zim is advocating for: the animation could take place in a limited area (good for reading), and still reaching further pixels. You could need to do "UP/RIGHT + B" to reach some sponge bop and "DOWN + B" for some others, though.. and time your button press accurately to grab something. In comparison, current GRAB is a proximity action: move your player next to the item to grab and hit when you're close. That's all I require.

Enforcing the direction with the keypad also allows to draw a larger hand, that better conveys the idea that we're grabbing things. Ideally, we could understand what the move does by watching it in the void. Like you check kick and punch buttons on a beat-em-all before you follow the "GO->" arrow for some action. 

A mieux y réfléchir rien n'interdit que Bilou ait déjà le pouvoir de soulever des choses plus lourdes dans ce jeu-ci, qu'il le conserve de façon permanente et que ça se traduise par une main qui devient plus grande quand il veut attraper les choses. Des doigts visibles, légèrement écartés, pour maximiser les chances d'avoir ce qu'on veut... c'est sans doute ça qui exprime le mieux l'action, comme on l'aurait fait dans une BD.

Voyons le côté "multi-directionnel", maintenant. J'ai tendance à penser que le "grab" est multi-directionnel parce que quand je presse sur B, Bilou attrape ce qui est devant lui, sous lui ou au même endroit que lui. Mais ça fait une animation où il est difficile de voir la main. Multi-directionnel pourrait aussi vouloir dire "dans n'importe laquelle des directions choisie" (avec le D-PAD).

Ça représente malgré tout une modification assez importante. Je pense que je vais dans un premier temps essayer que Bilou puisse s'accrocher par-dessous une éponge (y compris lorsqu'il la touche par le côté) avant de commencer à faire ce genre de changement.

Saturday, September 19, 2015

I need the Rainbow Road

I started working on a last level for School Rush, where you'd have to climb up for safety. It was tedious, because navigating in the level in LEDS can only be done with L+DPAD at the moment, in 64-pixel increments. Yet this time, I had to move through 1024x8 pixels of emptyness before I reach the "bottom" of the level everytime I want to migrate something from the title screen.

And then, i tried to copy the current game on my brother's DS using my not-so-smartphone, so I lost that map. Sigh. I'm not re-doing it that way. I will first bring on a new tool in the Level Editor. Something like a "Quick Navigate" option. I thought a "Rainbow Road" would work okay. level structure is depicted by two rasters (one horizontal, the other one vertical), and auto-zooming so that you a square area covered with stripes, and touching one pixel of that square brings you immediately to the corresponding area of the level.


Bon, perdre un niveau qu'on édite, ce n'est pas drôle. Devoir recommencer en faisant des centaines de fois L+bas pour retourner au fond du niveau, ça l'est encore moins. J'ai pris un peu de temps cette semaine pour réfléchir à un moyen de se déplacer rapidement d'un point à l'autre de la map pendant l'édition, en tenant compte des ressources vidéo déjà largement sollicitées sur l'écran d'édition. Je propose la RainbowRoad: un carré sur lequel sera représenté le niveau en utilisant un dégradé bleu-rouge pour l'axe horizontal et un dégradé foncé-clair pour l'axe vertical.

As far as software engineering is concerned, I face once again the need for a given event (update of level coordinates) to be produced by any of M sources and consumed by N receivers. M and N are small, and constant once the program is built. A bus pattern could work, or possibly something like an object that sends notifications when updated.

Color selection in SEDS could also benefit from this pattern.

Post-Scriptum thoughts:
  • [dont] Having QuickGo out of MapEditWindow allows to keep level edition full-screen. I have very limited options to introduce yet another window over MapEdit.
  • The drawback is that currently MapEditWindow doesn't show when you toggle to TilesetWindow.
  • [done] The transient "layer selection" overlay (available when map edition in "copy" mode) could host it as well.
  • Maybe replacing one of the rasters with a overview of how "dense" the area represented by one pixel is (with transparent-to-white) would give a good feeling of where we will go ... 

Saturday, September 12, 2015

L'avis de Zim : le coeur du jeu.

Un appel à travers le cyber-space ... Zim de Level'up se demande ce que devient le jeu de Bilou ... je passe annoncer la version actuelle de School rush et je reçois un avis super-détaillé ... Les power-ups de Bilou et les mouvements possibles sont le noeud du problème. Le coeur du problème, même, devrais-je dire après avoir lu l'article traduit dans les forges d'Antoine. Il y est question d'identifier le coeur du jeu, et de filtrer les idées de gameplay suivant la question "est-ce que celà renforce le coeur du jeu".

A moins que je ne me trompe, les deux actions de base sont attraper, sauter. Deux accessoires sont frapper, courir.
En ce qui concerne le fait d'attraper, je n'avais pas compris qu'on pouvait le faire, puis comment le faire (en maintenant bas), ce qui fait que je n'avais pas pu finir le premier stage, où il s'agit de s'accrocher aux nuages. 
Mon avis, s'il peut être utile, serait d'enlever l'action de frapper, et de faire d'attraper l'action principale, et de bien l'exprimer par l'animation. Et de la renforcer, pour qu'elle permette de tuer les ennemis (les attraper puis les cogner contre quelque chose en les jetant), et aussi en la rendant multi-directionnelle, et en lui donnant une plus grande portée, et en permettant qu'elle soit multi-directionnelle.

Je suis en fait desservi par le power-up automatique "frapper" offert sur l'écran de menu. Il n'est pas perçu comme un power-up (le jeu reste silencieux à ce sujet jusqu'ici). En proposant d'amener "attraper" à devenir plus central, Zim suggère d'en faire le coeur du jeu. Ce autour de quoi tout le gameplay tourne... Un peu comme "tout tourne autour des bombes dans Bomberman" et "tout tourne autour de la canne de Picsou dans Duck Tales", histoire d'éviter que le joueur ne se retrouve dans la confusion face à la panoplie de mouvements possibles qui est trop complexe.

Un "CATCH" capable de tuer des ennemis à distance, c'est Ristar, mais aussi le costume de Robin dans Mickey Magical Quest, avec son grappin. C'est le power-up "poing-lasso" que j'ai décidé de laisser sur le côté pour ce jeu-ci. Peut-être à tort.

La question qui me turlupine c'est "est-ce nécessaire d'avoir un coeur unique dans le jeu ?". Y-a-t'il un coeur dans School Rush ? ou plusieurs pôles qui se disputent l'attention du joueur ? Y-a-t'il un coeur dans Fury ? dans Rick Dangerous ? dans Commander Keen ? Miyamoto aurait-il du refuser la fleur de feu parce qu'elle ne renforce pas le coeur du gameplay (le saut) ?

Je crois que la fleur de feu a son rôle à jouer dans Mario parce qu'elle permet de choisir de ne pas sauter pour un bon nombre de situations ou mini-mario n'aurait pu que sauter (voire attendre pour les plantes piranha).

Le coeur de Fury, c'est de changer de personnage en fonction des situations. Le coeur de rick dangerous, c'est d'éviter les pièges. Mais si je dis ça, je ne fais référence à presqu'aucune action directe du joueur.

Pour revenir à School Rush, le jeu est construit avec des couches. En mode facile, la première couche de gameplay nous autorise à terminer tous les niveaux uniquement avec le saut. Dès le niveau normal, s'aggriper aux éponges devient essentiel, et le niveau difficile est impossible sans courir. Quant au coeur de l'action dès le mode "normal", je dirais que c'est "exploiter la force des autres personnages", ce qui se décline en de nombreuses actions.

Thursday, September 10, 2015

Pixel! HUD

J'avais été complètement charmé par "Pixel!" d'Arkedo. Le style graphique rétro mais parfaitement lisible, l'humour par les graphismes et les petites musiques chippy... N'ayant pas de PS3, par contre, je dois me contenter de l'étudier de plus près via youtube.

I hope you have a PS3. Because if you do, you are able to play arkedo's Pixel! game. In addition to its marvelous look, I want to point out the way the developer hint the player about a SHOOT ability that you earn by stomping monsters. You may easily miss the way the red gauge fills up, but what will not miss is the moment where it gets full, as it starts pulsating, turns yellow and produce little sparkles.

That's not only drawing your attention: that's also designed to make you feel the urge to press the Y button on your gamepad, as all of sudden, a button-shaped icon appears and gets animated with "press"-style motion while the icon of your cat animates as well.

I find it efficient, engaging and fun. I wish I had the idea to bring something like that for Apple Assault, and I'll have to look for something similar in School rush.


Un élément du gameplay de Pixel!, c'est que chaque rebond sur un monstre remplit un peu votre barre de Meeow! (en rouge, à côté de l'icône de votre personnage).
http://38.media.tumblr.com/251dfd1f0284f7e2e1aa618ab2a181f3/tumblr_nbxrwkx5CO1tliyz4o5_r1_500.gifCe que je trouve particulièrement réussi, c'est la transformation que cette jauge subit quand l'action MEEOW! devient disponible:
  • la couleur change, et passe au jaune
  • la barre "pulse" et brille avec des petits pixels blancs
  • l'icone s'anime
  • un rond représentant un des boutons de la manette apparaît et est animé pour montrer qu'on l'enfonce.
Bref, tout est là pour indiquer au joueur qu'une nouvelle chose est devenue possible... ça aurait très bien convenu pour les "shurikens" de Apple Assault.
Je dois maintenant réfléchir à quelque-chose de ce style pour les power-ups de mon School Rush.

Thursday, August 27, 2015

The song of Times.

We had grown up. We used to be 30-years-old young men with plenty of money available and some leisure time in the evening. They knew it. They converted most of our kid's toys into full-length blockbusters, no matter how ridiculous that would be. We used to have time to blog about the games we play(ed), the music we discovered, the ridiculous blockbusters we watched and which of our 8/16-bit processing device we dusted off.

We have grown up further. They are following, and more importantly, we are overwhelmed with kids' bed times, cleaning up all the things, planning the next evolution of the house, car, whatever. Who among us will play any of the Ludum Dare entries rather than just watching them on Youtube while swapping dishes out of the dishwasher.


Il me reste encore des amis. Dans toute l'agitation liée aux enfants qui grandissent, je ne les vois plus autant qu'au début de mes 30 ans. Leurs commentaires par rapport à mes petits Bilous se sont fait rarissime, et je ne peux pas vraiment leur en vouloir. Je me rends compte que je m'y prends mal pour faire la "promotion" de ce qui se passe encore ici. Il y a bien une page facebook mais je ne suis pas très doué pour la rendre vivante.

J'aurais bien passé la main à un pote qui aurait jeté un oeil ici de temps à autre et qui aurait fait les "public relations". Mais nous sommes sans doutes tous autant les uns que les autres débordés de responsabilités, avec si peu de temps pour tester un nouveau .nds (voire m'en réclamer un si le dernier date d'il y a un mois), faire des vidéos de présentations qui soit d'un bon niveau, être le conservateur du Musée de Bilou...

Wednesday, August 26, 2015

J'ai tenté le "straight throw"

Une impulsion de départ un rien différente, et je me rapproche du "lancer horizontal", dernier élément style "power-up" auquel je pensais pour School Rush. Mais ça ne marche pas. Vérifiez vous-même. Ok, on a fortement élargi la portée du dumblador lancé (la zone où sa courbe croise la hitbox des ennemis), mais le même lancé pour SpongeBop donne quelque-chose de complétement inutilisable.

I tried giving thrown bladors more range ... something towards "straight throw", but it is quite a failure. it works fine when used as weapon, but all the other throw-related actions (floating spongebops, bladors turned into platforms) become impossible to use due to the difficulty to guess where things will land -- and whether you'll be able to reach the "platform" you created.

C'est qu'il ne suffit pas de lancer Spongebop pour flotter sur l'encre: encore faut-il être capable de sauter jusque là. Et assez rapidement, ça cesse d'être possible à moins de faire un saut couru parfait. J'ai tenté de donner aux deux une trajectoire distincte, mais le résultat n'est vraiment pas convaincant.

I had plans to have Straight Throw available as soon as you collect a BigPunch power-up. Your punch power has increased, so you throw faster. But that makes the elementary "regular throw" harder to master because you'll have to learn two curves rather than just one. The solution for making them both available when BigPunch is collected is quite obvious: have Straight Throw activated by charging your throw. But I precisely noted that I didn't want to introduce another mechanic in School Rush. Maybe holding the button down to charge would work correctly in this game ?

Saturday, August 22, 2015

Throw down.

Implemented a nice little feature, suggested about one year ago by my nephew: throwing things downwards. This way, when you're carrying a spongebop, you can save yourself from a deathly ink pit by throwing down the spongebop you're carrying... and safely landing on it.

Aah ... un petit ajout rondement mené. Ce sera un peu chaud à maîtriser (bas + B pendant un saut), mais ça permettra au joueur qui le tente de se sauver inextrémis d'une mort par noyade en lançant un SpongeBop transporté vers le bas pour atterrir dessus plutôt que de tomber dans l'encre.

Wednesday, August 19, 2015

Zeldas are MetroidVanias ?

DOWN+B for pendats, UP+B for spongebops ?
I've been reading guide to metroidvania style lately, and reading that the author considered the Zelda series as games following the overall rules of metroidvania quite puzzled me. It means that the kind of menu navigation to pick the proper item that feels acceptable in Zelda and annoying in Megaman X is not bound to the perspective or the fantasy theme of Zelda. It means that the deviations from pure menu-ing seen in Link Between Worlds (where you gain the ability to use 2 items plus your sword, to define "quick selection" range, etc.) could apply to Bilou. I'll have to investigate that deeper.

Si on en croit Kynan Pearson, Zelda pourrait être assimilé à un MetroïdVania. Un monde ouvert et des items permanents à trouver qui permettent d'accéder à de nouvelles zones ... Si les items de Link sont un peu plus variés que des tirs plus ou moins puissants, avec ou sans missiles, je dirais que ça risque d'être surtout une impression. En terme de gameplay, on retrouve de la vulnérabilité ou non à tel item, une portée et une vitesse qui permettent de connaître "l'espace-temps" d'aggressivité de chaque item. Finalement, armure gravifique ou bottes de pégase, c'est surtout une question d'habillage scénaristique.

Ce qu'il y a d'intéressant, c'est que les menus de Zelda n'était généralement pas aussi ralentissants dans le gameplay que ceux de Megaman X. Du coup, les solutions intermédiaires de Link Between Worlds pourraient aussi s'appliquer à Bilou pour réduire les changements d'item sans pousser jusqu'à imposer une nouvelle combinaison pour chacun d'eux.
Ce serait l'organisation des niveaux, ne réclamant qu'un seul objet-clé et laissant l'autre au libre choix du joueur, laissant assez de temps d'exploration entre deux changements d'objet.

Peut-être que d'autres genres (shoot-em-up) pourraient eux aussi proposer des variantes du power-up utiles pour Bilou, du coup.


I believe what makes it work is the size of the area that can be played with a given item selection when you've picked the right item. LBW dungeons work great that way. Maybe it is time for me to play some Metroïd, after all. Maybe power-up techniques from other genres could help adapting input patterns to power-ups and game design.

NB: ce qui est amusant, c'est que j'aurais plutôt eu tendance à décrire les metroïdvanias comme "un Zelda avec de la gravité"

Saturday, August 15, 2015

Todo list des vacances

Petit arrêt au calme au milieu des écureuils. L'occasion de faire un peu le point sur "School Rush" et de ce qui manque pour compléter le jeu en faisant le tour de mes petits calepins:

  • [don't] BigPunch => StraightThrow. Une façon d'encourager le joueur à continuer à emmener des Dumbladors avec lui même après avoir obtenu un "BigPunch".
  • [done] Rallonger l'effet d'un "air punch" sur les Pendatz.
  • [how?] Implémenter quelque-chose de similaire sur Verso.
  • Une "danse de la victoire" à la fin du niveau
  • [done] Autoriser le FLOAT à partir du High-Jump (inkjets, gommes-bumper)
  • [done] Passage à FLOAT automatique quand Bilou obtient le Power-up FLOAT
  • [how?] quelque-chose de similaire pour BigPunch
  • Indique l'état des power-up sur le "HUD"
  • [done] Eliminer les Pendatz en mode "dizzy".
  • Donner une utilité aux bonus à récolter.
I played some School Rush this week, and read back scribbled notes to isolate todo items I still have to address. Many of these are related to the power-ups, the way to ensure their state can be understood by the player and to have coherent behaviour accross the game.

I would like to augment the GameScript class, too -- the level parser -- with a "reload()" method that would keep the state machine structures, but reload maps, evaluate expressions and reset GOBs to their scripted positions, so that we can efficiently retry the level when the player failed.

I also analysed the layout of my two first levels. I want to add a layer of collectibles that would give gameplay hints:

  • you can pick up a stunned blador
  • you can throw bladors at pendats
  • you can ride spongebops
  • have you tried to throw a blador in spikes ?
  • bladors can un-wire spongebop
and in the level 2:

  • hold (A) and you'll float at the top of your jump
  • big punch can defeat pendats
  • DOWN + (B) let you grab bladors although ou have Big Punch
  • sponges do float
  • bladors can stun inkjets.
The idea would be to have it look like a star-coin in NSMB, but also reveal a small drawing when discovered.

Tuesday, July 28, 2015

Good Ending / Bad Ending.

Much like Pac-Man, Pharaoh's curse and Apple Assault, my current game -- Bilou's School Rush -- has a limited number of maps and wraps back at map #1 when the player has cleared them all. Like in the games mentioned above, this wrap is completed by an increase in the difficulty of the game. Here, this is the ink raising faster, forcing the player to complete the game faster or to find new routes. I believe this is a nice way to build a game people can become good at while keeping an amount of game content that matches what a single person can create.

Quel est le point commun entre Pac-man, Pharaoh's Curse et Bilou ? Le retour du niveau N au niveau 1. Désolé pour les grincements de dents, mais pour avoir joué à quelques jeux de plate-forme homebrew qui ont tenté directement le mode "aventure", le résultat s'est révélé insipide, si bien que je veille à ce que mes jeux actuels offrent une plage de difficulté suffisante pour qu'on puisse y revenir plusieurs fois et y trouver du divertissement même s'ils n'ont que 4 niveaux.

But this time, I don't want to stop there. I have plans for an ultimate level that is not accessible to "easy" (and possibly not even to "normal") difficulty level. Only when completing that final level will the true story be revealed and the happy end unlocked. And with Sourceforge's SVN finally restored, I can push the tuning that makes such alternate ending possible without adding artificial branching in the game. The "bad" ending being simply the story-compatible excuse for restarting the game at higher pace.

En cherchant une façon de justifier ce "retour en arrière avec difficulté augmentée" par une petite histoire dans School Rush, j'ai commencé à imaginer une véritable sortie, avec une "vraie fin". Il faut dire que contrairement à Apple Assault, School Rush finit par devenir injouable si l'encre monte de plus en plus vite (au point que Bilou n'a plus moyen de courir assez vite).  J'ai finalement apporté les ajustements nécessaires pour ouvrir la voie vers cette fin alternative. Le décor pour le dernier niveau progresse lentement, mais sûrement... je vais pouvoir m'attaquer au level design ... et sans stress puisqu'il n'y aura visiblement plus de "retro compo" de chez NeoFlash ...

Sunday, July 26, 2015

Concept art : pyramid zone

C'est plus calme à la maison... j'en profite pour faire un peu de "concept art" pour la pyramide qui essaie de se trouver une identité propre et un gameplay. Le clin d'oeil à Fury semble enfin avoir trouvé sa place dans l'aventure de Bilou ... Voyons si pharaoh's curse peut m'apporter un peu d'inspiration.

There is definitely something odd with this huge, pyramidal building Bilou and Bouli found in the desert. Not only runes start to shine on monoliths, not only some cage change the color of those square-shaped beings that seem to have the power to open doors and move blocks around, but there are also those furballs all around the place. Not that our B dudes seems to complain, but it looks like some of them shouldn't be where they are.