Sunday, August 30, 2009
première photo du niveau 2 ...
J'essayais donc ce matin d'avancer un peu sur le comportement de l'appleman, et en particulier le faire "stresser" lorsqu'il aperçoit Bilou (une sorte de première phase d'attaque). J'ai donc ajouté une petite zone "déclencheuse de pièges" (cf. système de gestion des collisions) à Bilou (que je pourrais éventuellement désactiver lorsque Bilou a obtenu un bonus 'mode furtif'), et j'ajoutais une zone sensible à l'appleman. Bin pas de chance : ça n'a pas marché. J'avais oublié que si la zone active dans un test peut être plus grande que le personnage, il n'y aura vérification des zones passives que si l'objet lui-même est en contact. En d'autres termes, les zones passives sont toujours plus petites que les objets qu'elles recouvrent.
While I'm working on the improved behaviour of the Appleman, i have been tricked by the asymmetric nature of collisions in my own engine. While the *active* collision area can be larger than its own sprite, the *passive* area (that 'recieves' the collision, somehow) is inherently restricted by the bounding box of its sprite, meaning that the Appleman has to be active into detecting Bilou around (not the other way round). It requires a little more code to attach actions there that I'll write down as soon as we have sleep == (*deline && !me). I could also introduce a new kind of controller that simply fires an event when the player enters a given area, but for rectangular checks, it would just be useless work.
Alors on pourrait se dire "bah, il n'y a qu'à inverser" ... Le code n'était pas prêt pour ça, mais vous avez parfaitement raison. Alors cliquez sur un lien quelque-part pour continuer à lire, parce que moi ... bin Yaka.
Friday, August 28, 2009
Thursday, August 27, 2009
contretemps
J'ai ramené ma petite clé USB, celle-là même que j'avais utilisé en Suisse comme point d'accès autonome ... aujourd'hui. Evidemment, dans l'intervalle, j'ai cherché des solutions pour éditer rapidement les scripts déjà présents sur la DS.
Et je dois admettre que je suis assez étonné du peu de programmes proposant un éditeur texte -- même tout simple -- sur nintendo DS. J'ai testé un Blargh en mode pre-alpha (sans sauvegarde :P), le moonshell "en lecture seule" et la combox de Lilou n'est pas fiable sur ce coup-là : j'ai régulièrement des lignes qui disparaissent, qui fusionnent, etc.
Meanwhile, i've been tempted to edit my files directly on the DS. All i have to do is change a few things here and there, not to write down complete source scripts. Moonshell already allowed me to view files, but not to edit them. I gave BLARGH a try, an editor using a "keyboard" specially designed for efficient stylus input, but it's still a beta release that cannot save edited files. Pretty useless. I have thus used the text editor present in Lilou's combox, but it proved to be unreliable, randomly dropping or merging lines on edits. Maybe i'll work on a TEDS text editor to accompany runme and friends later on, and it might be based on "tag clouds" derivated from the text's content.
Anyway, i'm not fully back, but the "maquis" weeks toying with SD card readers are hopefully over, and i've succesfully tested controller chaining feature. I can go on with appleman's behaviour.Bref, quand j'aurai le temps, je me ferai mon propre petit "TEDS", probablement basé sur un "tag cloud" des mots les plus fréquents dans le texte existant, histoire de faciliter l'écriture dans des langages de programmations (au détriment du micro-blogging). Enfin, tout ça pour dire que j'ai enfin pu faire un test de l'enchaînement des contrôleurs: ça demande encore un brin de mise au point, mais ça prend bien forme.
Uh ? It looks like nothing about controllers have been translated in English this far. I'll need to fix that.Wednesday, August 26, 2009
Toujours pas codé de clone de Chuzzle.
edit '2009: Je n'ai toujours pas attaqué un clone de Chuzzle, et sincèrement, il y a peu de chances que je m'y attaque avant mes 32 ans. Mais ZeBlackOs nous a concocté un très sympathique Plop Invaders dont le gameplay se rapproche assez bien de chuzzle. Régulièrement, j'imagine un nouveau contexte dans lequel faire un clône de Chuzzle... un écran avec des pixels morts qu'un employé de PixTeX doit réparer ... des bestioles emprisonnées dans des bulles de couleur qu'un petit garçon doit faire sortir d'une vilaine machine du vilain Pr BubleGum... etc.
Au même titre que Seafox DS, ça restera sans doute encore un moment une idée en l'air, comme j'en ai pondu tant ... mais je dois tenir bon: l'objectif c'est Bilou, sinon je vais encore passer un temps indéfini à imaginer des tas de trucs possibles sans jamais avancer sur rien.
Sunday, August 23, 2009
Dans le Pied++
D'un autre côté, pour pouvoir définir le comportement de mon appleman, il me faut beaucoup plus de contrôleurs, qui sont appelés en séquence pour définir le comportement réel pour un état. Au moment de la lecture du script qui définit le niveau, je vais donc traiter une série de lignes "using tracker(Bilou)" "using Momentum(5,-1)" "using walker()", chacune de ces lignes donnant le nom d'une classe de contrôleur à instancier. J'ai donc pour chaque classe dérivée de iGobController une classe dérivée de iGobFactory capable de construire le bon objet à partir de la chaîne de caractères entre parenthèses.
So i've started decomposing the former "big chunk" controller such as 'walk' and 'gravity' into 'micro-gob-controllers' and make sure they are published in the std::map used by GameScript to prepare the GobState objects according to the rules found in the script, such as "using tracker(Bilou) ; using Momentum(5,1)", "using walker". The corresponding output is a chain of controllers that each do a specific job, easing code reuse. The BerryBat and the Appleman can for instance share the same "tracker" controller that tell them where Bilou stands, while Bilou and the appleman share "Momentum" and "walker" controllers, but Bilou receives its input from "dpad" rather than from "tracker".
Bon. Mais il faut que ces factories -- qui sont du coup des singletons -- soient enregistrées dans une map pour que le script les retrouve (c'est pas du Java: exit le 'Class.forname("tracker")'). Et je voulais pouvoir ajouter encore et encore des contrôleurs à mon code sans devoir maintenir une grosse fonction du genre "register_all_controllers". Cyril proposait donc évidemment des objets globaux (qu'on appelle parfois aussi "objets statiques"), mais je n'étais pas chaud: avec eux, il y a toujours anguille sous roche ...
Comme je n'avais pas d'argument vraiment convaincant, j'ai essayé quand-même. Première surprise : les "printf" ne marchent plus de manière fiable! J'ai encore quelques messages imprimés quand j'utilise "printf" sans aucun argument, mais c'est tout... un problème que j'avais déjà rencontré.
Un peu de désassemblage, et je constate que les messages qui sont effectivement imprimés n'utilisent pas véritablement printf: ils ont été convertis en interne en puts. Conclusion: en appelant printf dans l'initialisation des objets globaux, qui a lieu avant ConsoleInit(), j'ai empêché l'initialisation correcte de la console et rien ne va plus.
I stumbled upon two issues while implementing those factories -- which i initially chose to build with static objects. The first problem is a "known issue" of my libnds version: if i ever invoke a printf() function before consoleInit(), i screw up the stdlib's internal state and all subsequent prints using this function won't output a single pixel >_<.
Je change d'approche: initialisation "en aveugle", et une petite méthode "test" indépendante, histoire de vérifier que mes contrôleurs sont bien présents, appelée juste avant la boucle principale du programme. Deuxième surprise: il y a bien des contrôleurs enregistrés mais pas tous. Pourtant, mon code est bien compilé, tel que je l'ai écrit. Et il avait été appelé, puisqu'il était capable de foutre en l'air l'affichage...
La map est une variable de classe, statique, initialement vide. "As plain as can be" ...
... statique ? ...
Eh là, une minute ... Et comment le compilateur sait-il que parmi ces objets statiques, la bonne initialisation des GobFactories dépend du fait que la map ait déjà été initialisée ? Bin il ne le sait pas, évidemment. Le code d'initialisation appelle tous les constructeurs dans un ordre qui lui convient, et si ça ne me plaît pas, c'est tant pis pour ma faute.
Once this was fixed, i realised that i was f00lish to use static objects to register things in a static map. When i say "static", here, i actually mean "some object defined at the top level that should be instanciated before main() is ever called". The problem with such object is that their initialization order is undefined. In other words, my factory F could very well inserts itself in the map and then the map itself initializes (and thus clears what F modified).
Retour temporaire à "register_all_controllers" pendant que j'évalue les options... Voilà qui donne un nouvel éclairage au dicton "In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." (Stroustrup himself ;)
Wednesday, August 19, 2009
La gazette de Bilou
With all the GoodStuff(tm) i've located and shared through Google Reader this summer, you could setup a real (and interesting) codezine. Here comes the front page. For the content, just head to my googlecast.
Tant de mercredi après-midi passés à dévorer des "prograzines" comme Dream ou Pc-Team ... Au point que quand j'écris quelque-chose d'autre qu'un "progress report" sur Bilou, je m'imagine toujours qu'il s'agit d'un petit article dans un de ces magazines dédiés à la pensée informatique créative. J'aurais évidemment aimé avoir plein de collaborateur géniaux pour faire de ce blog une version numérique de ce "magazine de rêve"... Plus besoin: les collaborateurs ont déjà chacun leur Blog. Retrouvez donc leurs articles grâce à la toute-puissance de Gout-Gueule (les bons tuyaux) ...
(ps: oui, je me suis laissé influencé par Stravingo: voilà que je fais des "fake", moi aussi.
This to give a little more visibility to those "Been Reading", "Blogs I Watch" and similar boxes in the right side of this blog.
Saturday, August 15, 2009
Tobe's Vertical Adventure
Thursday, August 13, 2009
bilou.cmd
Ca fait plus propre ... je suis prêt à rajouter des niveaux dans tous les sens.
Mais j'ai aussi pas mal de fonctionnalités à béta-tester:
- [done] composition de contrôleurs
- [now][done] gobs dynamiques (tirs, étoiles-bobo, etc) et état "nil" pour les détruire, qui utiliseraient de nouveau un mécanisme de liste auto-itérée pour leur gestion
- [done] utilisation d'actions externes dans les expressions de la machine d'état
Am i going to do a release right now ?
Or am i going to toy a bit with chained controllers (useful for the appleman), dynamic Game OBjects (useful for shots and the like) and external actions invoked from the state machines (useful for sound effects) ?
Monday, August 10, 2009
loading ... please wait
I'm in need for an "include" statement in those gamescripts, but once again, nothing had foreseen that your level would need pre-processing (or that you'd change the source of data while parsing the script). Some more design effort will be needed.
Bien. Je peux charger et jouer le niveau 2 quand Bilou atteind la fin du niveau 1. On se rapproche de l'objectif "petit jeu tout simple où on ramasse les pommes pour atteindre la sortie". Il reste un couac avant une release: la définition de Bilou, des monstres, etc. doit être répétée dans chaque script ".cmd". Il me faudrait une petite commande "include" que je n'avais pas anticipée . . .
(PS: l'illustration vient d'un t-shirt ThinkGeek, bien sûr. Il n'y a qu'eux pour en faire des comme ça ;)
Friday, August 07, 2009
Aggressive Appleman
Je garde la primeur des pixels pour la prochaine mini-démo, mais l'idée est de démontrer les possibilités du moteur de jeu en rendant l'appleman plus agressif en le faisant réagir à la présence de Bilou. L'animation donnait donc:
un pas ... attente ... deux pas ... attente ... stupeur! Bilou en vue. Deux pas courus.
Comme l'animation est jouée en boucle, ça a donné l'impression que l'appleman "ralentissait" après avoir un peu couru. J'ai joué le jeu et l'ai fait vraiment ralentir avec un résultat qui me plaît beaucoup: on dirait qu'il est hargneux, mais trop lourd pour pourchasser Bilou bien longtemps. Juste ce qu'il faut pour un premier monde. Restera à coder tout ça et à le faire sauter bas des plate-formes dans l'état "hargneux".
I was toying with Appleman animation, yesterday night. One step, wait, two steps, surprised to see Bilou and chase Bilou (actually, just faster walking). It felt right. I went further making his speed decrease over time until he returns to plain walk. I loved how it conveys the feeling that despites appleman's hate towards Bilou (see the comic book), he just can't run his overweight body for very long.
I have strong expectations towards the appleman as he's supposed to demonstrate the power of the game engine to build sophisticated behaviours (e.g. jump off a platform to chase Bilou only when Bilou is nearby and downwards) out of "simple" bricks (such as a timing block, a hero-in-approach block, etc.)
And, by the way, there is now an english translation of my last two "history" posts about Calimero and Logic Labyrinth.
Timewrap: retrospectively, this is the very first step (2%) towards the mini-game "Apple Assault".
Tuesday, August 04, 2009
Try Again ...
Il est temps de reprendre le code de mon prototype de manière un peu plus rigoureuse, de passer en revue mes classes en suivant les bons conseils++ d'Axel. Jusqu'à 300K qui partent en fumée à chaque vie, ça coûte vite cher sur une machine qui n'a que 4MB.
Good news first: I can at last reload a level when Bilou has been hit too much. The downside is, that this highlight a memory leak in my game engine. Most likely some machine state isn't properly reclaimed. It's time to print my code and read it back with a mop in hand ...
- double invocation of GameScript ctor on reload : >280 K goes away
- not taking care of transitions when cleaning the state machine : 5K
- not taking care of cleaning "guns" : neglectible right now
- other (under inspection) lost things : 5K
- not taking care of OAMs allocation over iterations : invisible sprites after ~16 attempts
Bien sûr, une telle fonction est une dépense de resources matérielles inutile si l'on connaît suffisamment l'implémentation de malloc dans l'environnement précis où l'on développe. En l'occurence, ludo connaît une méthode bien plus efficace et élégante pour libnds. And ludo's sources come from this gbadev postint checkram() {
int total=0;
iprintf("grabbing ...");
void **chunks=0;
void **chunk=0, **prev=0;
for (int chunksize = 1024*1024; chunksize>32; chunksize=chunksize/2) {
int n=0;
while((chunk=(void**)malloc(chunksize))) {
*chunk=(void*) prev;
chunks=chunk;
n++;
total+=chunksize;
prev=chunk;
}
iprintf("%i,",n);
}
iprintf("releasing ...");
while(chunks) {
void **chunk=chunks;
chunks=(void**) *chunk;
free(chunk);
}
return total;
}