Wednesday, July 30, 2014

Ink Swamp Worm


The ink swamp worm
Now *this* is looking better. It tooks two "masters" (one to the left, the other to the right) to ensure that I have a chain of wavelets GOB looking still, and looking to occupy the whole level. I will definitely need a wider GOB for the wavelet so that the spawn rate is enough to cover the screen even when the camera accelerates, and I'll need to investigate the camera offsets (currently, some values curiously refuse to work). But at least I get spawning and termination of wavelets as expected.

Hmm. J'aime mieux ça ^_^ Un "maître" de chaque côté, qui s'assure qu'il n'y ait plus de vagues à une extrémité et qui en génère une nouvelle s'il n'y en a pas au-dessus de lui. Il me restera des règlages avant que ça n'ait une belle tête de mer d'encre, mais on s'approche de l'objectif.
Il faudra aussi que je trouve un moyen d'arrêter la montée implacable de cette encre, au fait ^^"

Tuesday, July 29, 2014

Une histoire d'encre...

La première implémentation de l'encre qui monte n'est pas franchement un succès. J'avais oublié que les zones sensibles d'un GOB (hitbox) ne peuvent pas se trouver en-dehors de son rectangle vital (bounding box). J'avais aussi oublié qu'un nouvel objet généré par un GOB apparaît systématiquement à l'emplacement de son "père". Les alignements de coordonnées partiels et impliquant la caméra, par contre, donnent pleinement satisfaction.

Pour ce qui est de l'affichage de la "grosse zone noire" par-dessous les vagues (l'encre proprement dite), j'ai décidé de laisser ça sous la responsabilité du code spécifique au jeu qui gère aussi l'affichage du score

Monday, July 21, 2014

Sonic 2 for free ?_?

J'avais eu l'occasion de télécharger Sonic 2 pour Androïd, temporairement gratuit, sur la recommandation de mon frère. Une valeur sûre, de 1992. Emerald Hill et ses ponts spiralés ... La Chemical Zone et ses blocs lambinants qu'il faut escalader après avoir dévalé des pipe-line de liquide bleu-louche.
J'essaierais bien d'aller jusqu'à la Mystic Cave voire Oil Ocean, mais pour tout dire, les contrôles sur tablettes sont une catastrophe! Le bouton de saut ne réagit pas systématiquement, ce qui est un comble pour un jeu de plate-forme où les réflexes sont si importants. Ça fonctionne un peu mieux quand on appuie vers la mi-hauteur, mais ça veut dire que presque tout ce qui se trouve devant Sonic devient masqué par ma main >_<

What good is a free copy of Sonic 2 if you can't play it ? And how could play a reflex-based platformer when your hands are hiding half of the play screen ? How could you have proper timing when you can't have your hero reliably jumping on "button" press ? And if trying to move backwards may be ignored because you suddenly move out of the active detection region ?

does it really deserve the 'sonic' tag ?

Sunday, July 20, 2014

DLODs for runme.

Scribbled notes on how to extend runme tool with a way to import plug-ins (or Dynamically-Loadable Object Directories -- DLODs) that would contain a set of controller, guns and effects required for a given game. So far, changing some of Bilou's behaviour require that you recompile controllers.cxx, which in turns mean that you also need to re-compile runme if you want it to work with your new code. I'd like instead that the map file indicating where the support code entry points are so that we can have DLODs that are statically-linked to work with one instance of runme, and loaded at a specific location in the DS's 4MB of RAM.

That's on my secret todo-list for about 7 years, but that won't be for this summer.

In a similar approach, I'd like a gobscript-to-c++ compiler that would replace run-time parsing of the script with build-time generation of a series of constructor/setters or static data.

Dinner Time. See ya.

Friday, July 18, 2014

rbegin(), deadend.

I know that C++ has pitfalls and numerous weapons for you to shoot at your own feet, and the behaviour of iterator has already puzzled me a couple of time, but I wasn't expecting *this*. I wasn't expecting the position returned by a single there = list.rbegin() to be different depending on when you de-reference it. Like, pushing 3 items, invoking there = list.rbegin(), pushing 3 more items and figuring that *there now let me access the 6th item 0_o. I had to check the source code of stl_list.h to understand how reverse_iterator is just a façade calling operators of a companion bidirectional-iterator as expected to be appropriate, and how the 'end' of a list is materialized by a 'guard' node hosted by the list itself (an academic workaround), meaning that when you ask for rbegin(), you're actually positioned exactly on the same node as with begin(), but now operator* finds it smart to move one position backward just before returning the target.

Eh bien, on dirait que le C++ me réserve encore quelques surprises. Il m'avait semblé judicieux de réécrire une partie de la gestion des monstres de LEDS en utilisant une std::list et des itérateurs, mais je me suis rendu compte hier que du coup, éditer un niveau détruisait systématiquement toutes les informations sur les monstres. Un effet qui est resté caché lors des tests en émulateur, vu que desmume ne modifie jamais de façon durable les fichiers. Je vais donc laisser tomber le "rbegin" ('donne moi le premier élément de la liste lue à l'envers') au profit d'un --list.end() ('donne moi l'élément juste avant y-en-a-plus') parce que ce dernier, au moins, est évalué au moment où on le demande et pas à la volée au moment où l'on s'en sert.

Je sens de plus en plus le besoin de tests systématiques de mon code, mais en environnement émulé, j'ai du mal à percevoir comment les mettre en place.

Monday, July 14, 2014

pinky LEDS

I've spent too much of my hobby time trying to figure out why one object of my levels didn't work as expected, partly because properties were only encoded as obscure quadnary codes in the level editor. Now, I can give a nickname and a cpc-like SYMBOL statement to illustrate the block behaviour. Whenever a 0-3 special tile is found, the editor will investigate the surrounding tiles for a 16x16 full-block with all special properties, decode the quadnary value and retrieve the corresponding symbol. I thus have pink-ish 'plus' for bonuses that will work in-game, waves for ink, triangles for spikes, etc. At the moment, I still have to encode them with 0-3 tiles and will get the confirmation that they're properly encoded only when moving the screen around. I have plans for better than this, but the first step-stone is in place.

Voilà donc le premier pas vers un nouveau mode d'encodage des blocs spéciaux: chaque bloc peut se voir assigner un "symbole" (façon CPC basic) qui apparaîtra dans une jolie (?) couleur rosée lorsque l'éditeur fait le rendu du niveau. Il faut toujours faire l'encodage "à la main" (c'est même un peu plus délicat que précédemment, puisqu'on ne peut plus loucher sur les codes existants :P) mais dès qu'on déplace la vue, l'éditeur nous confirme que les règles du moteur de jeu ont bien été respectée (numéro de bloc spécial connu, un bloc tout entier a été utilisé, etc.) ... et le petit symbole pointu ne laissera plus de doute sur le fait qu'on a encodé un picot et non pas une fin de niveau ou un bonus.

Ce n'est qu'un premier pas, mais comme ça, je peux enfin trouver et corriger le problème d'interaction avec les taille-crayons dans le "niveau de *deline". J'espère pouvoir du coup aligner 2 ou 3 autres niveaux-courses d'ici la deadline de la neocompo (s'il y en a une cette année).

Friday, July 11, 2014

Un nouveau mode d'action pour LEDS

Ajuster les propriétés des blocs d'un niveau, ça devient fréquent et c'est loin d'être une partie de plaisir dans LEDS. L'encodage par tiles spéciaux numérotés de 0 à 3 est techniquement suffisant, mais c'est une vraie plaie pour l'édition de niveau et encore pire pour la maintenance du genre "faire en sorte que l'encre réagisse aussi avec les monstres" ce qui suppose de passer tous les blocs d'encre de 2002 à 3002 >_<.

Tout celà serait plus efficace avec un mode "inversé" où l'utilisateur peut préparer un bloc de 2x2 tiles avec les propriétés souhaitées puis toucher un des blocs proposé comme graphisme pour que l'ensemble des blocs similaires à l'écran voient leurs propriétés mises à jour. L'idée est simple en apparence, mais on est dans du C++ et donc ce genre de modification est à peu près aussi confortable que de déplacer une porte dans une maison: mieux vaut d'abord faire un bon relevé des murs porteurs ...

Hey there. I hope I will find time to introduce a handy feature in LEDS this summer: the ability to quick-update the properties of blocs appearing on-screen. I spent some time identifying constraints and spotting the locations in the code where I'll be able to insert hooks for this. Wait and see. I have to apologize for the poor picture quality this time. I want to focus my available time on actually *coding* the modifications ^^"

J'avais fait, au moment d'ajouter "l'appel transient du tileset" une cartographie des "fenêtres" de LEDS qui n'est pas loin d'être le plus complexe de mes 3 éditeurs pour DS. Cette semaine "offline" fut l'occasion de me re-familiariser avec tout ça, retrouver les bouts de code correspondants (imprimés sur 25 feuilles de brouillon, vu l'état de mon cybook), de compléter avec les dépendances entre classes et d'essayer de trouver le meilleur emplacement pour la véranda ... pardon ... pour la nouvelle "fenêtre d'édition rapide des propriétés du niveau".

Les contraintes sont donc les suivantes:

  • SpecialsWindow doit s'enchaîner sur MapeditWindow, qui s'enchaîne elle-même sur TilesetWindow pour avoir l'affichage souhaité. Faire des sous-listes de widgets au sein de TilesetWindow aurait pour effet de rendre la map invisible pendant l'utilisation du nouvel écran.
  • SpecialsWindow doit être créé par TilesetWindow qui lui donnera l'accès à deux de ses SpriteTables (sprwidgets)
  • L'activation de SpecialsWindow ne peut être décidée que par MapeditWindow, seul composant capable de dire si on se trouve ou non en mode "édition des propriétés du niveau". On peut déléguer l'exécution de cette décision au TilesetWindow ou à la fenêtre-racine de l'application.
  • MetaLayer (widget) est le mieux placé pour effectuer le remplacement des données une fois que la SpriteTable aura lancé l'évènement indiquant quel est le bloc-cible.
  • [done] J'ai 96 caractères disponibles pour des affichages adaptés (p.ex. un bloc fendillé plutôt que 0202). Le nom apparaissant en (2) sur le mockup et les caractère spécial affiché sur la map sera défini via le fichier .cmd et ses structures 'bloc $no { @commands } '
Je crois qu'on peut dire "heureusement qu'on aura pas besoin du mécanisme "transient windows" cette fois-ci" :P (qui permet d'avoir le GuiEngine qui produit un évènement 'GUI_ANYKEY' aussi lorsqu'on relâche les boutons).