Saturday, December 31, 2016

L'avis d'Eric

C'est la dernière journée de 2016. Une année qui aura commencé (en ce qui concerne ce projet) par du débugging intense de mon moteur de jeu et qui termine ... par du débugging intense de l'outil "runME" histoire de pouvoir reprendre le dévelopement de nouveaux niveaux.

Mais entre les deux, j'ai l'immense honneur d'avoir reçu un feedback direct pour la grande release de SchoolRush par Eric Zmiro, développeur professionnel à temps plein dans le jeu vidéo, qui a travaillé aussi sur DS et qui a fait du game design aussi bien que du level design et de la programmation système.

Here ends 2016. A year mostly of system debugging and tools polishing, but also the year where I finally could make the first fully playable and polished release of School Rush, the Bilou-based game I've been working on since ... 2013. My goal was to have something I could proudly show to video game professionals, and I got the honour to receive feedback from Eric Zmiro, who developed most of the platformers I played on PC when Bilou was first created. 

L'univers est vraiment bien trouvé avec des attributs cohérents (l'encre, les gommes qui rebondissent, les crayons qui piquent, etc.). C'est super dur (et au clavier surement encore plus) j'ai bien avancé le second niveau, mais pas pu le finir !

A mon avis, sorti plus tôt, vous le vendiez !

It's extremely rewarding to hear "it could sell" from someone who's been experiencing the odds of creating games for a living, even when that's modulated with time traveling conditions. Eric described the game as fun (good thing too: I always loved the humour in Prehistorik series) and really hard (which makes me smile, given how many lives I wasted in spikes and fire of his own games ;)

Venant de l'homme qui a conçu les niveaux de "Titus, the Fox", et (iirc) de Prehistorik 2, je prends le "super dur" avec un immense sourire. Et quand je lui demande pourquoi "sorti plus tôt",
C'est surtout la plateforme qu'est en retard en fait. Sur DS tout projet est mort. Autrement, concernant le jeu lui même (qu'est vraiment dur, p''ain, ou alors ce sont les sauts qui sont mal calibrés, mais je n'arrète pas de me gauffrer) c'est plutôt rigolo. Je ne sais pas comment est la suite, mais si on note une progression dans les niveaux, ça peut être pas mal !
Et parmi les bugs/améliorations nécessaires relevés (programmeur système, hein, n'oubliez pas ;) 
  • pourquoi quand on monte sur le truc a patte (taille crayon ?) et qu'il avance, on avance 2x plus vite ?
  • Pourquoi le chargement des niveaux est aussi chaotique ??

Dans un cas comme dans l'autre, ces bugs sont liés à des insuffisance du moteur de jeu. Ce ne sera pas simple de les corriger, mais si ça saute aux yeux des professionnels, je ne peux pas le laisser tel quel.

Tuesday, December 20, 2016

The latest devkitpro


  • [solved] latest runme crash with stack=0 when loading the title screen
  • runme triggers a crash of desmume-cli, version 0.9.11 when --cflash-path is used to grant access to data items
  • same runme can be launched when no --cflash-path is provided
  • same runme works fine when emulated on old desmume (0.9.6, 32-bit, running on old laptop), even with --cflash-path
  • same runme crashes when emulated on old desmume (0.9.6) rebuilt on 64-bit system, with --cflash-path
  • SchoolTest can read the title screen, but suffers the same "stuck-on-the-title-screen" bug as observed on the Androïd emulator
  • desmume 0.9.11 apparently doesn't emulate bad address / invalid instruction. That's not going to help.
Sounds like there will be some guru meditation in the upcoming weeks...

Si les tests automatiques avaient plutôt bien supporté le passage d'un vieux devkitpro à un plus récent, les outils du type "runMe" et le test du jeu s'en sortent moins bien. Il n'y aura probablement pas de "release Noël" de School Rush ...

First step to sort that out would be to make sure I can see last command the parser tried to parse. That should already be mentioned in the "die()" function, but with such a stackless-crash, it is unclear it would be possible to call a function at all.

Second priority will be to figure out whether the "latest devkitpro/libnds-1.5.12"  team still properly support the "register exception handler" feature.

Finally, I'll have to try freshly compiled SchoolTest against my old desmume, just to check where the regression is.

Monday, November 28, 2016

class *Model

It's a bit more complicated to make my level editor test-friendly than it was with the sprite editor... so allow me to recap how I proceeded with SEDS:

hmm ... je pensais que ce serait plus simple que ça d'adapter le code de LEDS pour qu'il permette le même genre de tests que celui de SEDS. En fait non. Sans doute parce que j'ai déjà essayé d'avoir une couche "modèle" pour LEDS mais qu'elle ne correspond pas assez bien à ce dont j'ai besoin.

Guidelines

  • the model captures all the information about internal state of the edited object.
  • the UI code makes no access to the components of the model (i.e. a palette, a spritesheet, ...) without going through one of the model's function
  • code within the model is free from any UI interaction
  • each UI component (aka *Window) has its corresponding model capturing the information it needs. When a component is used by multiple UIs, we'll use a common ancestor (e.g. ModelWithSheet) to capture the shared component.
  • editor-specific extensions to the library component (e.g. EditorSpriteSheet extends SpriteSheet) is declared at the *Model.h level.

Outcome
  • Every operation performed on edited objects can be reproduced out of native UI environment for testing
  • Dependent objects are created together as a *Model, making it simple to ensure they're working correctly with each other.
  • main code no longer needs to maintain and dispatch pointers to shared component all over the place, while components themselves still blissfully ignore where the peer components they're working with are managed.

Tuesday, November 22, 2016

Juju & Peyo

C'est un chouette nouveau (2014) jeu que je (re-)trouve là: Juju and Peyo, que je classerai dans le filon "donkey kong returns" mais plutôt ciblé sur les joueurs moins aguerris, en particulier étant donné la vitesse de marche assez poussive du personnage. Par contre, attaque par boost, éléments à retrouver, petits éléments du décor qui libèrent des bonus à ratrapper (et qui volent, éventuellement en suivant un pattern pré-défini). Ambiance colorée, mais globalement plus lisible qu'un Giana Sisters Twisted Dreams, voire même qu'un DKC returns lui-même. 'faudra que je demande à mon frère s'il trouve ça sur sa PS3...

En plus des mouvements de base déjà mentionnés, notre petit ourson rose peut faire un "mouvement de danse magique". Il assomme les ennemis, déclenche des mécanismes, ouvre des coffres au trésor, etc.
Un élément qui complète le gameplay de manière plus sympathique que des interrupteurs ou des clés, à mon avis, et qui manque dans bon nombre de jeux d'exploration.

Les joueurs rodés pourront utiliser la charge pour progresser un peu plus rapidement dans les niveaux, à défaut d'un bouton de course à la Mario (pour autant que je puisse en juger à travers les 'Let's Play'). Ouf. Par contre, on reste sur des ennemis au comportement assez simple, j'en prends pour exemple les crabes qui sont vulnérables à toutes les attaques là où ceux de DKCR demandent soit une roulade ou un saut selon qu'ils ont les pinces en l'air ou à l'horizontale (et peuvent demander plusieurs hits, en changeant de position entre les hits).

Côté design, j'aime beaucoup les espèces de golems musicaux, spectateurs, partiellement acteurs mais incapable de vraiment interagir avec l'avatar du joueur.

Ils pourraient presque faire partie d'un Rayman Origins. Il y a plein de très chouettes éléments de décors, mais aussi un grand nombre de blocs qui font juste "asset" quasi-générique... je n'ai pas encore mis le doigt sur ce qui a un goût de loupé, de ce côté-là.




Saturday, November 19, 2016

3 days

File copies in progress. I could get the unit tests and the editors of dsgametools succesfully built by the latest devkitpro installed on my BMx, after all. But without the copyrighted content of SchoolRush, the unit tests won't run ^^".

I'm a bit disappointed by 'terminology', the new terminal+file explorer from the Enlightenment project, esp. because its 'set terminal background' command (tybg) doesn't seem to work, neither do the fancy 'tyls' command. 

I'm kinda scared, too, because it looks like emacs is doing weird rendering. And I'm afraid this is something related to my graphical environment rather than related to emacs itself ...

PS: file copied. Unit test succesful

Tuesday, November 15, 2016

7 days!

Here I am, back on my BMX because my 2007 "grizzly" thinkpad is no longer operational. I cannot call it "dead", but the battery no longer works, meaning that using it for arm-chair development in the evening has turned highly improbable (with improbability equal to 42, to be precise).

I'll give myself 7 days to try and compile SEDS and LEDS with the latest devkitpro on this box. If that's not enough, I'll just import my damn' old "devkitpro 32" and keep going.


Me revoici sur mon BMX: la batterie de mon autre ordi m'a complètement lâché. Certains des éléments que j'avais pointé en mai comme posant problème devraient fonctionner mieux maintenant que j'ai restructuré mon code, d'autres ont toujours besoin d'une mise à jour. Je me donne 7 jours pour y remédier. Passé ce délai, je récupérerai mon gros .zip avec l'ancienne version de devkitpro que je traine depuis Apple Assault, et basta.

Saturday, October 29, 2016

Le journal de Link : Cher Bouclier

Je n'oublierai jamais le jour de notre rencontre et je te promets de ne jamais te perdre dans l'estomac géant d'un bibedum.
On en a vu des belles et des pas mûres, tous les deux, et tu m'as sauvé la vie à bien des reprises.

Quand je repense à tous ces squelettes et hommes-lézard qui traînent dans les donjons de cette terre désolée, je frémis rien qu'à l'idée que tu n'aies pas été à mes côtés pour bloquer leur attaques meurtrières. Avec toi, ce n'est qu'une question de patience d'en venir à bout: choisir la bonne distance, ne pas plonger tête baissée, et porter un coup d'estoc lorsqu'ils reprennent leur esprits. Ils peuvent bien tenter de passer par-dessus moi, tu suis leur mouvement encore mieux que Navi.

Heureusement, ils sont trop bêtes pour se mettre à plusieurs pour m'attaquer. Sinon, il faudrait que je commence à me déplacer dans la pièce pendant le combat, choisir un emplacement stratégique parce qu'évidemment, si je me retrouve vraiment au corps à corps, tu ne me seras plus d'un grand secours. garder la bonne distance: tout le secret est là. Assez loin pour que tu sois efficace, et assez près pour que je sois efficace aussi :)

Il n'est pas encore forgé le canif qui nous séparera.


Wednesday, October 19, 2016

Pause Ahead

Très sympathique petit jeu que ce "pause ahead". Un petit labyrinthe, un personnage qui se cherche, et un mécanisme de gameplay tout à fait intéressant de manipulation du temps. La mise en pause n'agit pas complètement sur le personnage: il conserver son inertie et "dérive" sans que plus aucun danger ne puisse les blesser. Un mur pourra par contre annuler leur déplacement horizontal ou vertical.

Au bout de quelques niveaux, malheureusement, c'est devenu trop dur pour moi. La marge de manoeuvre pour construire la bonne vitesse, et le timing autoriser pour y parvenir devient trop juste pour un "casual gaming" du soir.

PS: le temps d'écrire ceci, de finir d'écouter ma fée, mon laptop s'est mis en mode "powersave (800MHz)" et le jeu s'est du coup ralenti au point que j'ai pu avancer jusqu'au boss (final?). que je n'ai quand-même pas pu finir. "Don't dumb it, slow it down", qu'il disait.

Tuesday, October 18, 2016

sprck || fail.

Good news: I managed to reproduce in a controlled environment the corruption of a spriteset. Bad news: because I had no idea what was the possible cause of such corruption, I just went through a random set of deletions and then a random set of recycling of the released blocks. And repeating the process from a sane initial spriteset until the "checker" tool reports something abnormal

One interesting thing, though: what's abnormal is abnormal twice: not only I shouldn't have "cross clusters" in my sprite pages (two slots on two pages actually referring to the same tiles), but I possibly shouldn't have "0" at all (it is reserved on most spriterams) and I definitely shouldn't have some odd tile number since the smallest allocation unit so far is 4 tiles.

edit: Another curious thing, on the "animations" subset: one page makes reference to tiles that are not in the spriteset! possibly unused things that were inserted when the page was first created and then deleted before first saved into the spriteRAM. I guess I'll need to make sure I have some automated test that do something like that, too.

edit++: I think I got most issues fixed now. I'll have to give it a run on a real device and see whether I accidently broke something with all the "refactoring"  ...

Sunday, October 16, 2016

Spongebop-lifts

Entre les améliorations de mes outils de base pour qu'il redeviennent fiables, le tri de mes listes youtube et la lecture de ce chouette texte sur Mario World, je récolte les idées en vadrouille succeptible de faire un bon dernier-niveau-vertical pour cloturer School Rush.

Not being able to immediately start with the new level gives me the opportunity to let comments from "reverse design" and miscellaneous youtube video percolate in my mind to come up with building blocks for the vertical level of School Rush. For instance, Spongebop "moving platform" doesn't really fit a one-screen-wide level. It would be better to have it as an elevator. Good thing is that I actually have all the core logic ready, and just need at most one extra controller.

Ici, c'est SpongeBop qui s'y colle, reconverti en ascenceur ... la logique qui lui permet de se balancer en arc de cercle offre déjà tout ce qu'il faut pour détecter s'il faut accélérer ou décélérer le mouvement. L'ascenceur aura un mouvement un peu plus élastique qu'une traditionnelle plate-forme d'un Mario, mais ça ne me gène pas vraiment.

Friday, October 14, 2016

ngised emaG

C'est une pépite que je découvre et dévore grâce à Kirby Kid: le ""reverse design" de Super Mario World ... comprenez une analyse poussée d'un de mes jeux de plate-forme favoris, ce qui le rend unique par rapport aux Mario précédents (moins d'inertie au sol, physique des sauts simplifiée, etc.) et une quête pour la compréhension du niveau de difficulté et de son évolution au sein du jeu.

Thanks flies to Kirby Kid for re-tweeting something that made me discover The reverse-design of Super Mario World (a.k.a. debriefing a statistical analysis of the game's challenges based on Mario's jump). How high can you jump, and what do you need to get that high ? How large is the death zone (aka d-distance) of a specific jump ? what is the penalty for failing ? is the height difference making the jump simpler or harder ? and how large is the safe landing zone on the target platform ?

Je n'ai pour l'instant que la version "web" du document, mais qui étudie déjà fort numériquement les capacités de Mario dans le jeu, avec les hauteurs (4, 5, 6, N blocs) et longueur (5, 8, 12, N blocs) de saut et propose la notions de d-distance -- la distance horizontale que Mario doit franchir en sautant pour éviter un obstacle mortel -- en plus du différentiel de niveau entre la plate-forme de départ et celle d'arrivée... ou de la distance entre le premier ennemi sur la plate-forme et le bord de celle-ci. Des chiffres qu'il me tarde de comparer avec ceux de Bilou que j'avais décrypté après le play-testing de mes deux premiers niveaux (pour ajuster la difficulté du jeu, justement).

I remember collecting similar figures about my own games between the original two levels of School Rush and the more complete gameplay I have now. But the authors do not only focus on how the difficulty curve evolves over the game. They're also interested in how a gameplay element (e.g. rotating platform or torpedo launcher) can be simplified into its most elementary instance (the standard challenge), increased numerically according to their metrics (aka "expansion": denser ennemies, larger death-distance, etc.) or evolved into something different (where e.g. route planning is involved) that requires additional skills after the standard challenge is sufficiently mastered. They also point out that a challenge may often just be mutated -- that is, turned into something different but that isn't any harder by any metric we can think of. Just the same challenge, but without being annoyingly repetitive.

Les auteurs présentent de manière très juste Mario à la rencontre de l'action pure (atteindre des cibles) et de la plate-forme pure (passer par-dessus des trous). Son mouvement fétiche -- sauter sur les koopas -- combine en une seule mécanique les deux pilliers d'arcades sur lesquels il est construit. De tous les costumes du dernier épisode sur NES, Super Mario World ne retient que 2 power-up: celui qui tire Mario davantage vers l'action (la fleur) et celui qui améliore nos possibilités de manoeuvre en matière de "plate-forming" (la cape). Une dualité qu'on retrouve finalement aussi dans les power-ups de mon petit "School Rush".

La grille d'analyse qui nous est proposée s'ajuste aux "thèmes de gameplay", axés soit sur le timing ou la vitesse, et soit sur l'action ou la plate-forme. Sauter au bon moment, ce sont les plate-formes mobiles. Frapper au bon moment, ce sont les ennemis périodiques. Sauter pour aller vite, c'est le thème de la "conservation du moment cynétique" (pardon pour la lourdeur de traduction).

Based on the fact that Mario's gameplay is a mix between pure action (hitting targets) and pure platforming (mastering gravity to leap over pits), they propose a reading matrix to Mario World's challenges, depending on whether they're requiring timing skills (jump/fire at the right moment) or speed skills (keep jumping because platforms are falling, for instance). I'll need to read more of their examples on periodic ennemies and intercepts to accurately understand why they put one in either category ... I hope it will help me coming with good design for my climb-to-the-source-of-all-ink level ^_^./

Reste l'intercepteur, cet ennemi dont la trajectoire croise celle du saut le plus naturel pour aller d'un point A au point B et qui en module du coup significativement la complexité. Typiquement (mais pas uniquement) un koopa volant par-dessus un trou entre deux plate-formes... mais que j'ai du mal à associer à l'interaction "vitesse et action", personnellement.

A noter que "vitesse" ne signifie pas forcément "bouton de saut" et peut s'appliquer même dans un jeu comme Commander Keen: dès qu'il y a quelque chose qui nous oblige à rester en mouvement (comme des plate-formes qui tombent au bout d'un moment), on est du côté "vitesse" et pas du côté "précision/timing".

Sunday, October 09, 2016

./sprdo && ./sprck

Bon, ç'aurait dû être un post illustré avec Bouli en train de déplacer des morceaux de code et de trancher des dépendances foireuses "comme dans un donjon de Zelda" avant de découvrir dans un coffre le nouvel objet ultime (en forme de grappin) pour aller explorer plus loin dans le code et vaincre le Bug Final.

Mais bon j'ai trouvé suffisamment de mini-bugs avec les deux premiers tests (effacer une page de sprites ou copier un page de sprites) pour m'occuper pour ce week-end.

Maybe I'll eventually illustrate this with Bouli-the-Hero crawling into the Dungeon of Technical Debt, moving blocks of code to separate model from view/controller, attacked by unneeded dependencies as he tries to get his hands on the Unittest Fairies Hookshot, which is mandatory to access the Bug's Lair.

But I'm already deeper into that dungeon, in epic (?) fight against mini-Bugs and trying to collect as many small keys as I can to get hints that will hopefully allow me to solve the dungeon's ridle.

Tuesday, October 04, 2016

HoB-style

The game I'm looking forward to play this season isn't the latest Zelda, it's HoB by runic game. Gorgeous look, explorative gameplay ... on a planet that contains even more secrets than I'll ever be able to pack on Bilou's crash site. And perfectly readable visuals.

I love this mix of huge stone constructions and technology. This architecture made of sharp angles and (arcs of) circles ... this world that looks like a gigantic jigsaw waiting to come back into a single piece.

Ooh ... j'ai vraiment très envie d'y jouer celui-là! HoB par Runic Game. Sans doute même plus que le prochain Zelda. Une planète entière qui est un mystère. Un gameplay fluide et presque parfaitement lisible. une ambiance de mystère, un design intriguant pour le décor qui mélange nature sauvage et ruines technologiques, un mélange combat/énigmes (comme dans un Zelda ?) ... et une de ces mise en scène !

Voyons un peu ... est-ce que je peux utiliser quelques éléments de cette architecture magique, mélange d'angles droits et d'arc de cercles pour pimenter un peu ma propre "Castle Zone" ? Est-ce que ça marchera dans une vue de profil en 2D? Est-ce que je peux moi aussi me permettre des morceaux de tours qui se déplacent sous l'effet d'une technologie qui n'aurait pas dû être là ? ... à cogiter.

I wonder ... Is there some way to use somehting like that to make my own Castle Zone more interesting without making it look like a HoB-Zone ...
- damaged architecture is more interesting than completely built
- there may be some people still surviving in that environment, chances that they're struggling and will be hostile to Bilou
- and such environment also attracts wild life.

Sunday, September 18, 2016

Testing & Refactoring

Astrocruiser needs some refactoring
Pas beaucoup de nouvelles côté développement du jeu. Parce que je veux mettre en place un système capable de tester de manière systématique les éditeurs en plus du moteur de jeu. Les makefiles pour la recompilation mieux organisées, c'est fait, je m'attaque maintenant à la structure même des programmes, sortir ce qu'il reste de logique de la partie du code qui dépend directement des interactions avec les boutons... l'idée d'un "sprdo" où on pourrait indiquer une série d'opération élémentaires représentant un scénario d'édition du genre "load spritea.spr, page 3, block 8, store.block 9, save spritea-edit.spr"

I guess Bilou doesn't find it so funny that the engine and the tools need to be deep-checked. I started with revision of the build system -- and that's almost handled. Now I've started to migrate whatever is not GUI-handling out of the *Window class (into corresponding *Model classes, if you ask) so that I can more easily emulate some use cases...

Thursday, September 15, 2016

Le journal de Link: Cocorico: Sheik. Et après

 Cher  Journal,

Bon, je veux bien : j'ai passé 7 années en-dehors du temps après avoir fait la plus grosse boulette de ma vie, à savoir laisser entrer ganon dans le temple du temps. J'ai une super-épée donc je vais pouvoir arranger ça. Y'a une fille (?) bizarre qui me tuyaute avant même que j'aie pu faire un pas dehors "va au village cocorico, sans ça, tu ne pourras même pas entrer dans le premier temple". On y va: 'faut être gentil avec les filles.

Pour trouver quoi ? Des gens qui vivotent, qui se fichent pas mal de ce qui se passe dehors et qui n'ont pas l'air d'avoir la moindre idée de ce qu'on m'a envoyé chercher ici. Je reçois un oeuf-cocote ... je réveille un type qui sombre dans la dépression qui me fait un appel gros comme l'arbre Mojo d'aller voir comment va sa fille dans son ancien ranch. Pas l'ombre d'un autre indice... Enfin, à part le vieux Merlin qui délire à propos d'un gars qui savait voir la Vérité et qu'on a construit le puits là où il y avait sa maison et le type du moulin qui insiste sur le fait que là, maintenant, c'est bon: son moulin a bien asséché le puits. Sauf qu'on fond du puits, il n'y a rien qu'un éboulement de rochers si serrés que même une bombe n'en vient pas à bout.

Bon ...

Allons au ranch, alors. C'est qu'il n'y avait rien d'autre à faire, j'imagine. Sauf qu'au ranch, la fille s'isole dans un monologue répétitif. J'ai même pas pu lui placer que j'ai vu son père et quand je lui joue la mélodie des chevaux qu'elle prétend avoir oublié, elle m'ignore superbement.

On peut monter les chevaux, aussi. Ça c'est nouveau. Par contre, invariablement le mec m'interrompt et me flanque dehors au bout d'une minute.

Et ça ne fait pas d'avantage d'effet au vieux père déprimé d'aller lui parler de sa fille, non plus.

Tant pis, essayons le fameux temple de la forêt. Il est au bout des bois perdus, d'accord. Et il suffit de suivre la musique de Saria pour le trouver. Enfin, ça devrait, mais ça ne marche pas vu que Saria, elle ne joue plus. Je dois y aller à l'aveuglette... j'aurais du prendre un cahier à spirale avec moi pour me faire une carte, tiens: c'est pas Navi qui va m'aider: elle fait une fixette sur le village de cocorico. Même quand j'y suis, elle me dit qu'on doit y aller.

Bref, je peux aller où je veux, j'ai zéro équipement juste mon sac de bombes et mon épée qui ne sert pas à grand chose vu qu'il n'y pas de monstres dans la plaine d'Hyrule ... Mais me filer un tuyau sur ce que voulait cette tarée de Sheika. ça. bernique.

J'ai poussé une tête jusque chez les Gorons pour m'acheter une jolie tunique rouge qu'ils ne voulaient pas me vendre quand j'avais 12 ans sous prétexte que j'étais trop petit, mais il n'y a plus personne là-bas non plus.

I'm a bit disappointed by Zelda: Occarina of Time's shift from childhood to late-teenage at the temple of time. I should feel like I can explore much more, but I actually feel lost in a world where I miss my reference points and where all the friends who could explain me what to do next have been relocated somewhere else on the map, and none of the actions I could think of to progress is possible. 

I'd like to get the feedback of those who remember having played OOT for the first time. How did you figured out what to do when getting out of the Temple of Time as a grown up and realised that noone Kakariko village seemed to know anything about why Sheik of the Sheika sent you there ?

Saturday, September 10, 2016

La guerre des Mascottes

Ça y est : j'ai enfin reçu mon tome 2 de l'Histoire de Mario. Chiffre de ventes à l'appui, William Audureau et Oscar Lemaire passent au tamis les années sabbatiques du plombier, à savoir la période de 1990 (lancement de Super Mario World) à Juin 1996 (fin du développement de Mario 64). Je dis "années sabbatiques" puisqu'entre les deux, les amateurs de fleurs de feu n'auront que Mario Land II à se mettre sous la dent.

C'est pourtant l'époque où tous vont tenter l'aventure de la plate-forme dans le sillage de celui qui tente de faire vaciller l'idole, à savoir Sonic (1991). Bien sûr, il y aura eu d'autres jeux de plate-forme avant et il y en aura d'autre après, mais durant cette période, ils représenteront le gros des ventes de jeu sur console.

Chose peu surprenante, c'est avec la sortie de Sonic que coïncidera l'envie de faire mon propre jeu de plate-forme avec d'abord Calimero de '91 à '93 puis avec Bilou sous Basic entre '94 et '96.

Pendant ce temps, à peu près tous les détenteurs de personnages enfantin forts vont cesser d'"ignorer" le jeu vidéo et attaquer le dangereux Mario sur son terrain : celui du jeu de plate-forme. Ce sera "castle of illusion" avec Mickey, "duck tales" puis les jeux Infogrames qui ratissent autant de personnages de bande-dessinée francophone que possible mais aussi le bestiaire de la bande à Bugs Bunny -- avec plus ou moins de succès. En réaction, les acteurs du jeu vidéo vont aussi miser gros sur les personnages d'animaux antropomorphiques ayant le potentiel de devenir des mascottes, comme le Mr. Nutz de Philippe Dessoly chez Ocean, la chauve-souris acrobatique chez Sun Soft et le controversé Bubsy chez Accolade (que je ne connaissais jusque là que sur PC pour ses simulateurs de course)... et bien d'autres encore qui n'auront atteint ni l'émission Luna Park ni les planches de Midam. Même les robots de combats spatiaux prennent des allures de braves mascottes et tentent de se faire passer pour des abeilles avec des noms comme "twinnbee".

Oh, well. There's been another book by William Audureau, joint by Oscar Lemaire, about years '91-'95 where platformer was the king of video games, and where it looked like everyone could come with a mascot-like hero that would be the next Sonic since Mario was Missing... So I've been reading and reading. And no code has progressed. More luck next week ?

De notre côtés de jeunes ados, on fait la chasse aux magazines, on rève à ce que peut bien être tel ou tel jeu avec un personnage plus ou moins probable. Il semble qu'il y ait un nouveau venu tous les trimestres. Dans quelques rares cas, on aura l'occasion de s'y essayer mais le monde du PC est tristement dépourvu de ce genre d'exotisme. Au mieux, ce sera James Pond II sur Amiga à la maxithèque, ou la surprise de découvrir Moktar reconverti en Titus the Fox. Ils ne sont pas tous des sonic-like tels que Zool, mais ils cherchent clairement à plaire au même public. Et il semble bien que le succès de Sonic décomplexe tous ceux qui hésitaient jusque là à faire des chat-tout-mignons comme personnages de jeu: il suffit de leur coller un élément vestimentaire de jeune, une attitude cool-et-frondeuse, et en avant. Sur micro, on le prendra avec une dose de dérision, et j'ajouterais bien "Super Frog" (PC, Amiga) à Jazz Jackrabbit & James Pond ... mais le plus souvent, on avait droit à un gros raté du genre "Skunny the Wild West".

Le tandem William-Oscar gratte donc derrière les couvertures de magazines et effectue un impressionnant travail pour rassembler les interviews, les mettre en contexte ... Car si l'un va titrer "la nouvelle mascotte de XXX", ce n'est pas nécessairement l'avis de la société qui l'aura publié, ni du studio qui l'aura créé. Et si les personnages humains (Commander Keen ? Duke Nukem ?) sont assez peu présent dans l'analyse, les "héros/mascottes" improbables tels que Plok ou Cool Spot eux, ne sont pas oubliés.

Il met aussi en perspective les travaux de l'équipe de Miyamoto -- qui n'est évidemment pas restée les bras croisés pendant 5 ans -- qui sans parvenir à donner un deuxième jeu où l'on saute vers des blocs-questions à la SuperNES va se frotter à toutes les technologies de pré-3D afin d'avoir le meilleur Mario 64 possible quand sera enfin prête la console 3D de nintendo.

Il y aura finalement peu de suites parmi les "héros fabriqués spécialement pour l'occasion" ... et aucun ne parviendra à survivre à l'environnement des 16-bits où il a vu le jour, que ce soit pour des raisons de fusion/acquisition/license, par incompatibilité technique entre la vue 3D et les mouvements du jeu de plate-forme, ou simplement parce que les artistes d'animations qui donnaient vie aux personnages se retrouvent privés de tout repère devant les logiciels de modélisations polygonales.

Vous l'aurez compris, même s'il y avait beaucoup moins de matière pour le game-designer-amateur que je suis, le livre m'a malgré tout tenu en haleine. Bon, évidemment, avec tout ça, le travail sur l'amélioration de SEDS et LEDS, mes éditeurs de jeu sous DS, n'ont pas beaucoup avancé ^^".

Wednesday, August 31, 2016

Plummet (2)

Et si le fait d'avoir une plume changeait fondamentalement l'humeur des encriers de la School Zone ? Au point qu'il ne leur vienne même plus à l'esprit de lancer des gouttes d'encre.
Et si ces plumes, Bilou pouvait les transporter d'un encrier à l'autre profitant d'un vol plané d'encrier à encrier.

Techniquement, ce ne sera pas pour School Rush, mais j'aime bien l'idée...

The recent chat about techniques that could extend the number of sprites the GEDS engine could support on the DS opened some new paths and led me to funny ideas such as "what if Bilou could use quills to move from one inkjet to the next one ?" and then "how would an inkjet feel (and look) when he's got a quill in ?".

That might not reshape the SchoolRush game, but I love how it turned out

Monday, August 22, 2016

revising build system

Once upon a commit, was runME, a tool to assist game development on NintendoDS by embedding a game engine, WiFi transfer functions and launch buttons to sprite, level and animation editors. Revising a level should have been as simple as click "LEDS", update the area that wasn't suited to the gameplay, "save and play" to return to runME that would allow you to run the game with its new layout. Editing monster's behaviour should have involved at most a similar trip to SEDS and uploading some revised scripts from a laptop PC.

Nothing like that still occur with SchoolRush. The code layout and the build system makes it extremely tedious to maintain identical feature set for the game's own binary and runME. Slight differences between the two means the game will not play as expected and even will even fail to run on runME because some 'plugin' controllers (the C++ toolkit to build game state machines) expect different arguments. RunME is almost exclusively used to beam .spr and .map files out of the DS to be tested in emulator on the integrated game binary and them beam back the .nds into the DS after some preliminary tests were made on emulator. That's likely the slowest development cycle you could think of :(


Un jeu est sorti. Je m'autorise donc à prendre un peu de temps pour faire de la maintenance dans du code qui en a bien besoin. En particulier le système de gestion des compilations. Ce ne sera pas aussi élégant que ce qu'on a construit au boulot avec mes collègues, mais je reprends quand-même quelques idées... J'élimine les VPATH, notamment. Je regroupe ce qui peut l'être dans un 'common.mk' inclus depuis le makefile de chaque projet, etc.

J'espère que ça me permettra de recommencer à faire de l'exécution dans runME quelque-chose de plus fiable, de façon à pouvoir tester un niveau gribouillé sur DS sans devoir le re-passer par le PC.

I'm on a quest to make it better, drawing experience from the buildroot-derivative project we're dealing with at work. I have hope it will also ease the task of writing unit-tests for LEDS and SEDS that will make them more reliable tools: I've got way too many instances of "data recovery" in the last edits of School Rush.

Maybe I'll have to push myself to avoid re-inventing a "dlod" systems for the plugins and accept that a static library and proper re-compiling statements is all I need: a first intermediate build of "plugins.a" allows me to look at all the things that the bunch of controllers need from the environment to do their job. If I was able to offer that via in-runME patching, I could just upload a new "ppplatformer.bin" to the NDS and have runme work with the update functions. Admittedly, beaming a new runme is simpler and does the job.



[edit] J'aurais pu suivre une alternative intéressante: celle des modules Linux. Dans ce cas-là, c'est l'équivalent de mon "common.mk" qui est fourni à make, et l'emplacement du module à compiler est passé en ligne de commande avec un M=. Du coup, les "raccourcis usuels" qui donnent presque l'impression qu'on a affaire à un dialecte de makefile sont encore plus transparents. Un inconvénient pour un projet dont la base d'utilisateur est plus réduite, peut-être ?

Tuesday, August 09, 2016

make -p et LevelEditor.elf

Bon, moins drôle. En voulant tester une variante de LevelEditor qui ne conserverait que les personnages effectivement sur la map, je me rends compte que LEDS ne compile plus. En fait, SEDS et AnimEDS non plus: j'ai oublié de vérifier que mes modifications du game engine ne "cassait" pas les éditeurs ^^". Heureusement qu'au boulot, j'ai des "buildbots" pour m'éviter ce genre de mésaventures.

Allow me to be much more technical, please. I have some build system issues with the editors. Somehow, I forgot to maintain them as I was upgrading the core library for the game engine library, and some parts of the engine are shared with the editors. Although I don't have build bots setup for this project, I can use some makefile-debugging techniques I developed working on buildroot-based project. The #1 trick being the existence of '-p' flag for GNU make, that let you review every single variable and rule instantiation and understand what goes wrong much faster than by adding echo commands here and there.

Heureusement aussi, j'ai découvert l'année dernière l'existence du flag "-p" pour GNU make, qui nous fait un dump de l'ensemble des variables internes du makefile, avec en prime la ligne de makefile qui a défini cette variable. De quoi retrouver sans trop de difficulté que les options pour générer la "map" au moment du link sont erronées, et de rajouter un "--cref" histoire d'en apprendre un peu plus.

The core issue I'm facing is that LEDS is now trying to include the core part of the game engine, that parses scripts and does game object updates frame by frame. Clearly, it's not required for the editors. And the editors are not ready to include it, because they don't provide details on the kind of game they are. As soon as 'make -p' allowed me to locate where to define additional flags for the linker and what the current flags are, I can enable the creation of a linking map, that will indicate which symbol triggered inclusion of GameScript.o and in which source file of the level editor it was invoked.

Oui, parce que le problème que je rencontre ici, c'est que tout d'un coup l'éditeur de niveau s'est mis à avoir besoin de la quasi-totalité du moteur de jeu. Qui en retour a besoin qu'on lui indique comment marche le jeu.



Reste à découvrir pourquoi "level.o" s'est mis à faire référence à ce AllocContext::active qui a "attiré" le parseur de GameScript à l'intérieur de l'éditeur de niveau ... ça, c'est un job pour GCC avec son flag -E (pour "fais juste le pre-processing et arrête-toi"). Pour ça, j'ai ré-injecter dans ds_rules du "devkitarm" une technique découverte ce matin dans buildroot: plutôt que d'utiliser directement '@' (oui, oui, comme dans les autoexec.bat ;) pour masquer l'appel d'une commande pour ne pas surcharger la console du développeur, on utilise '$Q ' avec 'Q ?= @'. Il suffit alors d'appeler 'make Q= ' pour avoir l'information complète, voire de ne définir la valeur par défaut de Q que si V n'a pas encore de valeur, ce qui permet un 'make V=1' pour '--verbose' bien plus facile à mémoriser. Je peux alors voir la commande exacte de compilation du fichier "level.cpp" et en introduire une variante avec mon fameux flag -E.

The last step is to understand why this "AllocContext" variable (it turned out not to be a function) is used. My best move for that is to capture the exact command that compile level.cpp and replay it with the '-E' flag that only goes through pre-processing and dump the result. I can then see the same thing as the compiler sees, search through it in a single pass. Once it's done and understood, it's merely a matter of moving those static variables into their own compilation unit, so that the linker can pick AllocContextDefault.o to satisfy level.o's needs without pulling the whole game engine along.

Et voici le chaînon manquant: un script est devenu un contexte d'allocation, et la définition du contexte d'allocation se trouve dans GameScript. Un petit déplacement de la variable "active", et ce sera réglé.

Sunday, August 07, 2016

LivingStone, I presume

Les ennemis de Rayman, sur PSX étaient assez évolués dans leur comportement. Les "livingstone" par exemple -- existant en deux tailles -- ne se contentent pas de patrouiller sur leur plate-forme: le grand livingstone peut faire des pauses pour ajuster son casque, fuir effrayé ou se faire assommer d'un coup de prune.

Le petit "teigneux" lui, peut se mettre à pourchasser rayman, mains en avant, tenter de l'aggriper à distance et s'abaisser pour se mettre hors de portée de nos coups de poings. Pas encore exactement un personnage de Street Fighter, mais nettement plus sophistiqué qu'un goomba.

Ennemies in Rayman PSX were fairly sophisticated in their behaviour. The Livingstones -- one of the first monster you encouter -- not only patrol on their platform. They pause here and there, they can be frightened or stunned with bouncing fruits. Then you have the smaller living stone, detecting Rayman's presence, chasing him, or attacking with its hands. It is not yet as complex as a Street Fighter encounter, but not quite your average goomba either. 

J'étais donc assez surpris de constater que les "lividstone" de Rayman Origins sont fondamentalement statiques, occupant sans avancer (ni même se retourner ?) une plate-forme unique. Certains ont un bâton en main, d'autre une balle. Mais d'un point de vue "gameplay", ça ne change rien: ils se contentent d'attendre Rayman. Ils sont assez comparable à des blocs à pics sur lesquels ont peut sauter et qu'on peut casser. Enfin presque: une fois touchés, on peut se servir de leur "bulle" pour aller plus haut, encore que je n'ai pas encore vu beaucoup d'endroit dans les niveaux où cet élément est développé.

Comparatively, I was shocked to see Lividstones of Rayman: Origins almost static, standing on their platform wiht no additional move, not trying to hit rayman with their stick when they have one... just waiting to get smacked. They're functionally equivalent to spiky blocks that you could break with a punch. The "why" is pretty clear: make the game easier. What puzzles me is "how does it come it works? Why haven't I got any feeling of core gameplay being lost ?"

Que s'est-il passé, donc ? Pourquoi cette simplification à l'extrême et surtout où est la "compensation" dans le reste du gameplay qui fait que cette simplification n'a pas d'impact négatif sur l'intérêt du jeu ?

Dans "l'histoire de Rayman", on nous présente la méthode Hascoët qui répartit les challenge contenus dans les niveaux en quatre catégories:

  • Rapidité: aller plus vite que la lave, grimper plus vite que l'eau, suivre un scrolling imposé, être parti d'un nuage avant qu'il ne disparaisse ... d'une fleur avant qu'elle ne se fanne... Bref, tout ce qui incite le joueur à rester en mouvement. Dans Rayman Origin, ce rôle est essentiellement joué par le "roi des lums" (score doublé temporairement) et par les bonus-en-bulle dont on ne saura profiter que si on arrive assez vite dessus. Mais il y aura aussi des pans entiers de montagne qui s'abaissent et mettent le joueur trop lambin en danger.
  • Astuce: tout ce qui demande au joueur de réfléchir un peu pour résoudre un problème, comme le coup de la prune sur la tête du livingstone, ou parvenir à lui mettre un coup malgré ses stratégies d'évasion. Dans "Origins", l'astuce est souvent secondaire, mais les développeurs ont prévu de nombreuses situations où les plantes-interrupteur font apparaître ou disparaître des plate-formes ou des yeux-à-pointe. On peut ainsi à distance précipiter les lividstone vers leur défaite, les prenant à leur propre jeu. Bien rigolo à faire, en tout cas. Faute d'une récompense intégrée au jeu, on est récompensé par un sentiment de supériorité sur ces mécréants pathétiques.
  • Précision: sauter/frapper pour atteindre un endroit en hauteur, ce sera l'élément principal dans Rayman PSX. Rayman Origins monte fortement les exigences ici, en particulière avec les défis des "pièces de la mort" qui demande des sauts et des rebonds impeccables. Je suis aussi tenté de penser que les nuances possibles que dans Rayman PSX, ne serait-ce parce qu'il y a plus d'inertie dans la course du personnage. En plus, ça n'aura échappé à personne, Rayman peut maintenant rebondir sur les têtes des ennemis, et on a droit à plusieurs constructions dans les niveaux ou on joue au parakoopa en rebondissant d'ennemi en ennemi pour les éliminer tous.
  • Synchronisation: passer au bon moment ou frapper au bon moment. C'est peut-être un des éléments qui est en retrait, en tout cas dans les premiers mondes, encore qu'il reste quelques plate-formes mobiles pour aller récupérer des pièces de la mort, justement.

Saturday, August 06, 2016

Tout vient d'la cache

Quand Eric parlait de faire des mises à jour à la volée de la mémoire au fil de l'animation des sprites, je pensais spontanément à un système semblable à celui de Donkey Kong Country: chaque personnage se voit attribué un emplacement en VRAM et les mises à jours pour ce personnage-là viennent systématiquement à l'emplacement alloué à l'apparition du personnage. Du coup, s'il y a deux "kritters" en même temps à l'écran, il n'y aura aucun partage entre eux: le nombre d'objets à l'écran devient fortement contraint, même s'il y a peu d'images indépendantes, comme dans le cas d'Apple Assault.

In my first attempt to understand Eric Zmiro's animation engine I thought the video memory would be managed somehow similarly to what happens in DKC on SNES: every new object on screen would receive a chunk of video memory large enough for the most complex frame it has to render and it would update its content during the vertical synchronization timeslice (or at some other time slice when the GPU isn't busy looking up those pixels). To some extent, the DKC engine would be an auwfully bad choice to implement a game such as Apple Assault, where there are a large number of similar ennemies on screen and high probability that a single block of VRAM is in use by multiple ennemies at the same time. That was failing to include the key ingredient in Zmiro's engine.

J'avais oublié un élément essentiel des moteurs de jeu à la sauce Zmiro:

Chez moi, tout est en cache : Fichier, sprites, palettes, bloc... tu n'allais tout de même pas dupliquer les blocs autant de fois qu'il y a d'instance ? si ? [...] avec ce systeme (développé sur GBA en 2000), on fait actuellement l'affichage de fonte (du texte!) avec caractères proportionnel sur XBOX one et PS4, codé en utf-8 et disposant de toutes les langues y compris chinoix, japonais et coréen ! Tu vois, c'est souple.
Like for tileset used by a gigantic and varied map, Eric introduced cache management algorithm deep into the animation rendering. Animation data refer to logical blocks and the mapping to VRAM location happens dynamically, reusing blocks when possible, importing new ones only when they are not yet in VRAM somewhere else and dropping unused one only when room is needed, keeping them available for the next animation cycle when you have few sprites on screen.

With this approach, no need for pre-defined locations, no need to do spritesheet optimizations such as "let's keep only one VRAM slot for the stunned dumblador and update it from main RAM to get the desired animation on screen". For every block in the SpriteSet, all we need is an additional short integer indicating whether the block is currently missing in VRAM or stored at some location between 0 and 1023. Everytime an OAM need to be patched to reference one logical sprite block (like "page 4, block 21), you can check the corresponding VRAM slot in the spriteset and copy to a free VRAM slot if none is currently assigned.


Fini donc les emplacements pré-établis. Finies les acrobaties du genre "je vais garder une seule image pour 'dumblador assomé' sur la spritesheet et j'aurai un SprAnim qui change son contenu depuis la banque d'image restée en RAM (je fais pareil avec les vagues d'encre actuellement): pour chaque bloc de données contenues dans le spriteset, il nous faut un nombre supplémentaire, entre -1 (absent) et 1023 qui indique l'endroit en VRAM où on peut trouver cette image-là.

A chaque fois que l'on veut reprogrammer un OAM pour qu'il fasse référence au bloc "page 4, image 21", on regarde l'emplacement VRAM associé, et on en alloue un en réutilisant un emplacement libre si le bloc correspondant n'est pas encore en VRAM. Avec 1024 blocs de 16x16, on peut avoir assez de pixels différents dans les sprites pour couvrir 5 fois l'écran de la DS. Le risque d'un objet invisible par faute de mémoire vidéo est virtuellement nul. Dans mon organisation actuelle, j'ai 128Ko pour les sprites, soit moitié moins, mais ça reste tout à fait viable.

Le côté génial du truc, c'est que tant qu'on alloue sur des blocs qui ne sont pas actuellement présents à l'écran (marqués comme libres), on peut faire la mise à jour de la mémoire vidéo pendant la phase longue où le GPU retrace les pixels à l'écran. Seules les substitutions où on est obligé d'éjecter un bloc utilisé lors de l'image actuellement dessinée devront se faire pendant la phase courte émulant un "retour de balayage".

Now, how would that work with Bilou's spritesheet ? I'm currently using about 1/4th of the video memory for Bilou's heads while only one is shown at every single frame. Streaming Bilou's head into a double-buffer as the animation needs it was one of my top improvements for AnimEDS. With a Zmiro-cache, I no longer need to allocate VRAM slots to GOBs. I no longer need AnimEDS updates. And potentially, I could have the whole set of heads used by the current animation in video memory, having only gradual updates of the VRAM as I switch between actions.

Alors, est-ce que ça marcherait avec Bilou ? Un bon quart de la VRAM est utilisé actuellement pour toutes ses "têtes" et une seule est affichée à la fois. J'avais bien l'intention de faire une sorte de "streaming par double-buffer de la RAM vers la VRAM" dans une révision de AnimEDS. Le Zmiro-cache permet de passer souplement d'un double-buffer à "seules les têtes utilisées dans l'action en cours restent en mémoire vidéo". Je gagne de la place et je peux (enfin) me permettre d'autres petites animations avec des grimaces, etc.

Les mains et pieds partagés par les crayons, les taille-crayons et Bilou ? Ils n'occupent pas beaucoup de place et ont de bonnes chances de rester présents en permanence.

Shared hands and feet (used by Bilou, pendats and dumbladors) only use a small area of the whole spritesheet. It's likely a 'least-recently-used' policy would keep them permanently in video memory. Bonuses, ink drops, dust clouds would likely come and go as needed, giving more room for ennemies frames.

How many ennemies could we host ? Well the critical point is more "how much VRAM slots will be off-screen at every frame?". If you have a free (off-screen) slot for every block you need to bring in for the next frame, then you don't need time-critical copies during the blanking interval. You have 128KB of sprites memory, which means 512 different 16x16 blocks. enough to cover 2.5 times the 256x192 screen of the NDS. The gameplay will become cluttered well before you hit the cache limits. 


Les bonus, gouttes d'encre et autres nuages-de-poussière-encore-à-dessiner ferait probablement des apparitions éphémères, forçant des objets dont l'animation tient plus déjà du "streaming" (p.ex. inkjet) à faire revenir une image de la mémoire centrale vers la VRAM.

Bref, vu le nombre de fois où je me suis "cogné la tête au plafond" de la quantité de VRAM disponible juste sur le projet "School Rush", introduire cette technique de cache pour gérer la mémoire vidéo serait sans doute la bienvenue avant d'envisager un jeu plus ambitieux ... disons de la taille d'un Commander Keen ?

Thursday, August 04, 2016

Si j'étais graphiste ...

Si j'étais graphiste, mes sprites auraient plutôt cette trogne-là. Je saurais qu'une bonne animation, c'est une animation où on a pas peur de casser les cadres et j'arriverais à l'appliquer. Du coup, le meilleur environnement pour faire du bon travail, ce serait quelque-chose qui soit le plus souple possible. avoir suffisamment d'images disponibles simultanément pour les copier-coller et les comparaison. Bref, un outil comme SEDS ne me semblerait probablement jamais franchement pratique.

Let's be honest: I'm far from getting any close to what a real pixel artist produces. If I was, my spritesheets would look like those featured in Titus's Prehistorik II: I would not let canvas restrict myself and I would apply squash/stretch so that animations work fine. There would be significant pixels variation between frames, too. In a word, the SEDS+AnimEDS would be very unlikely to suit me. I'd need something more flexible, and in return, my game engine would need something to easily convert such flat sheets into usable assets.

Mais pour mettre des graphismes dans un jeu, faire des graphismes ne suffit pas: il faut aussi qu'ils puissent être intégré au jeu. Il faut que l'artiste puisse le plus librement possible retoucher son animation, y compris faire grandir ou rétrécir certaines images.

L'idéal pour ça, comme l'expliquait hier Eric Zmiro -- concepteur avec plus de 20 ans de métier -- c'est d'avoir le système le plus automatisé possible. Voici donc ce que j'ai compris du système qu'il décrit.

 I had the opportunity to compare the tools used in my own "School Rush" with the kind of tools and techniques that Eric Zmiro (now at Magic Pocket, and formerly developer of Prehistorik II at Titus). The core idea is to make the spritesheet-to-game data conversion as automated as possible. There cannot be any "great hotspot positioning tool" because there shouldn't be any human doing such task in first place.

From his explanations, I started to think about such automated framing tool, which is mostly a matter of separating lines that contain pixels from lines that contain none -- and having some conventions such as "an animation is bottom-aligned horizontally". Of course, there is still need to identify a reference position for each frame, so that e.g. the character's nose stays at the same position on screen while scrolling at constant speed, but a mere line of lone pixels could do the trick.


Sur base de la première planche de sprites, le premier algorithme à faire tourner est un système qui identifie les zones dans lesquelles il y a des images des zones vides. Une ou plusieurs lignes horizontale ne contenant aucun pixel (gris foncé): c'est une nouvelle animation. Une ou plusieurs lignes verticales ne contenant aucun pixels (gris clair) à l'intérieur d'une tranche d'animation: c'est une séparation entre deux étapes d'animation. On peut ensuite raffiner pour rétrécir verticalement la zone active d'un sprite.

1) on découpe les animations par planche (1 planche = 1 animation)
2) on a un outil qui capture les sprites, les convertie en bloc

3) quand un bloc existe déjà dans la banque des bloc, il ne le rajoute pas.
4) pour chaque sprite indique : [x, y, flipXY, color_index, bloc_number, size] (j'espère n'avoir rien oublié)


Si deux sprites sont identiques, ils seront partagés. Mieux, certains blocs peuvent être partagé même si ils appartiennent a des sprites différents
Encore mieux, des blocs peuvent être identique apres flip, ou être identique a une transposition de palette prêt..
Si elle me semble contre-productive, la décision "une animation par fichier" trouve tout son sens dans une équipe soumise à une date de sortie: sur une planche "prehistorik-man.png", on peut effectivement laisser le logiciel découper les bandes d'animations et faire référence à prun = pman[0][*]; pcrawl = pman[1][*]; pswim = pman[2][*]; pjump=pman[3][*]; etc. Mais imaginons qu'au terme de la production on décide finalement de laisser tomber le niveau aquatique. L'animation de nage tombe aussi et pjump devient maintenant pman[2][*]. Tous les autres animations doivent également être re-numérotée. On s'en passerait bien vu qu'il faut livrer la ROM fin de semaine pour que le jeu soit prêt début décembre...

But my understanding was yet one productivity-step below the Zmiro approach: by enforcing only one animation per sprites file, we now have a strong filename-to-game asset relationship. If the file is named pcrawl.png, then we can gather all the corresponding sprites as pcrawl[*]. When instead the 'crawl' animation is simply refered as the 5th one on pman.png, then we become vulnerable to the removal of e.g. 4th or 3rd animation, for instance because "well, the water level doesn't work, we drop the swim animation".

Yet, having the art split into multiple bitmaps doesn't mean that the tool importing them all cannot identify shared frames (or blocks) across the whole dataset. The final touch, for every frame the auto-cropper found, will be to isolate solid pixels into a minimum set of hardware-compatible blocks and pack the pixels of those blocks into tiles. The DS video chip, for instance, will only work with 8*W x 8*H blocks with W/H ratios of 0.5, 1 or 2 and a maximum size of 64*64 pixels. Even with a simple greedy algorithm, we can easily shrunk the amount of video memory required for a sprite to 1/3rd of the brute-force 64x64 sprite approach. Each batch of tiles has a companion set of OAM data that can configure hardware sprites' size, ratio position and indexes so that your 7 sprites actually look like a single, seamless cro-magnon protagonist to the player.


Reste à faire manger ça par le hardware d'une console comme la DS, qui ne fonctionne qu'avec des sprites hardware de 8x8, 16x8, 8x16, 16x16, 16x32, 32x16, 32x32, etc. jusqu'à 64x64. Sa mémoire est limitée, aussi donc avec un seul bloc de 64x64, le nombre de sprites affichables simultanément est sérieusement réduit. Ici, p.ex., on a un cro-magnon de 37x49 pixels qui prendrait 64x64. Avec un simpe algorithme de découpe "glouton", on peut le couvrir avec 4 blocs de 16x16 et 3 blocs de 8x16. Soit 6/16 de la mémoire nécessaire pour l'afficher d'un seul bloc.

AnimEDS travaille par petites éditions successives. Mais AnimEDS suppose que le contenu de la mémoire vidéo est constant. Ici, il n'y a aucun intérêt à garder un morceau de cro-magnon en mémoire si cette image-là n'est pas à l'écran. Du coup, tout ce qu'il faut c'est allouer un bloc de N tiles de sprites -- avec N assez grand pour la plus grosse étape d'animation -- et assez de blocs 'OAM' pour les contrôler. Pendant la synchronisation vidéo, c'est un nouvel ensemble "VRAM+OAM" qui est transféré simultanément pour changer les pixels que la console peut afficher et l'information sur quoi afficher où (les OAMs).

Then you need to have a game engine that can make the best use of these list of OAM datas. A real animator like those who work with Eric will easily saturate the 128K of sprite memory the DS has, so every new frame is likely to see new sprites tiles updated in VRAM together with the OAM updates. More on that in a future post.

Mais je ne suis pas graphiste. Il y aura encore pas mal d'eau coulant sous des ponts avant que je n'accouche d'un personnage pareil ... donc je vais garder SEDS et AnimEDS encore un petit moment. Par contre, si mon moteur de jeu évolue dans le bon sens, on pourrait envisager un outil d'importation des .png en .spr qui ferait ce genre de travail pour faciliter l'importation de graphismes non-SEDS dans un jeu tournant grâce à libgeds.

Monday, August 01, 2016

Climbing level and end-of-game

  • [don't] don't insist on players grabbing "GO" to start playing. Pressing START anytime on the menu screen should work as well.
  • [done] update LEDS so that it crops out-of-boundary monsters when saving -- that should be easier than at loading.
  • [done] unit-test SEDS components and figure out what corrupts .spr files when editting
  • [need] show number of lives and grant an extra life every 100 letters.
  • [need] update build system so that the same controllers and 'guns' code can be shared by runme and games.
  • [wish] Tease players with CJ's "hurry up" theme
  • [done] implement pictures when the last level is beaten to support some story - or show it through some other mean.
  • [done] update libgeds so that GOBs freeze/restore also react to the vertical axis
ps: oops that shouldn't have evaded to the Web so early :-P Well. You may remember I wrote once that I'd like School Rush to conclude in an ascend-the-tower like level. There are a couple of technical barriers before I can integrate that, but none should be a major issue.

Eh! Un post échappé. Mais rattrappez-le! Rattrappez-le! Rhaa! mais ils sont tous en train de courir après des pokemons ... Bon bin c'est pas grave. Voilà: je mettrais bien un niveau grimpe-jusqu'en-haut pour conclure School Rush. Il y avait quelques bricolages à terminer avant de l'ajouter pour de vrai au jeu (bon, puis il faudra que je le construise, évidemment). J'avais commencé une petite "toudouliss" pépère, et j'ai dû cliquer sur "Publish" au lieu de "Save" malgré la différence de couleur.

edit: petite idée qui m'est venu comme ça pour la séquence de fin: Bilou retourne gentiment vers la gauche d'où il vient pendant que l'encre redescend assis sur une éponge qui flotte. En chemin, on voit des "recto/verso" calmés qui font la sieste, des dumbladors rassurés qui peuvent enfin rejoindre les leurs, etc.

Friday, July 29, 2016

School Rush Ready

Here comes a new challenge(r). Bilou: School Rush is at last ready for "VIP" players. There are no more things I need to add/fix for those 4 levels of platforming challenge. It may not be significant change compared to the last release, and these are clearly minor fixes compared to the last build, but it means the player should now no longer need some briefing: all the aspect should be readable and clean.

 Nous y sommes enfin! une version de School Rush qui tient plus du jeu que d'un béta-test. Ce n'est pas encore aussi parfait que je le voudrais, et ça manque sans doute de nouveauté pour mes fidèles testeurs, mais cette fois, j'estime avoir atteint le niveau de finition sur les quatres niveaux disponibles pour qu'il ne soit pas irrespectueux d'en parler aux dévelopeurs professionnels avec lesquels je suis en contact.

Si vous vous demandez "mais comment on y joue", n'hésitez pas à jeter un oeil au let's play de Pirez. (Enfin, assurez-vous quand-même d'avoir un émulateur NDS. DeSmuME, par exemple.

gameplay

You're controlling Bilou, a blue, ball-shaped explorer. You make him JUMP with the (A) button and grab things (or throw them) with (B). Your goal is to reach the right of each level before you're caught by the ever-raising ink.
You'll need to be quick, too. Use (R) or double-tap in left/right directions as if you were a pink, living vacuum cleaner.

You can stomp some monsters, you can throw sharpeners at others. Remember: the pencil soldats are the only real threat here, and they must be stopped from pouring even more ink for their autoritarist plans. Everything else that looks dangerous is mostly acting on fear and may prove very useful if you keep your head cold. Think about how useful a bobbing sponge could be if you could ride it (B). or how high an inkwell could shoot you ...

There are rumours of magical artifacts that could help you. The Fist of Justice, that noone can stand against (double-B) and the Floating Twister (hold A), that let you reach far away places. It's unlikely the pendats will let you recover them without a fight, though.

Story

At the far east of this school-like country, there is a gauge that will stop the ink. Rush for it! The books city is close to be destroyed once for all, and the elders' knowledge will be lost. This must be another plot from Square Root, who decided that mathematics are the only thing worth of being written down.
Everyone here seems to believe that Bilou is a sort of legendary hero...

How to play

Get the NDS image and play it on your homebrew-ready console or in an emulator, such as DeSmuME. See this page if you need extra explanation/instructions for running homebrews.

WARNING : difficulty selection on this release is partly broken : you have to touch the desired difficulty to get it selected. UP and DOWN directions, although changing the cursor's position, have no effect.

Monday, July 25, 2016

Blits!

https://sourceforge.net/projects/dsgametools/files/demo%20games/SchoolRush-fox.nds/downloadedit: all the other things are now fixed. If you're here for a download link, head to the real release post.

Si vous me suivez sur Twitter, vous avez peut-être déjà vu cette petite animation avec un flash quand on ramasse un power-up, suivi de petites étoiles sur Bilou. De quoi mettre en évidence (j'espère :P) le fait que Bilou a maintenant un pouvoir spécial. Dans ce cas, il ne vous reste plus qu'à télécharger cette petite version intermédiaire pour vous rendre compte de l'effet en vrai, à 60 fps avec le son.

I can at last release a running .NDS with that blits-and-sparkle effect when Bilou grabs a power-up. I got another instance of a corrupted .spr file which took longer to fix (automatic fixer just dropped the unique content and replicated some Bilou heads instead :(. With some more manual control over sprck, I finally managed to repair the file. Oh, and I got the additional hint for riding Spongebops, too.

Ça reste modeste par rapport à ce que mon frère espérait, mais j'approche tellement des limites de la mémoire vidéo et de mon éditeur de sprites qu'il va falloir vous en contenter: j'ai du carrément modifier mon outil de réparation de spriteset pour pouvoir faire des retouches à la main sur "quel tile est utilisé par quel bloc sur quelle page" pour éviter d'avoir des têtes de Bilou qui apparaissent dans les encriers ^^"

Thanks to Smealum, this is one of the most visited download page. You played the game ? You think something is missing ? Let me know with a comment ;)