J.l.n a grandi. 5 ans maintenant. Il ne se contente plus de regarder papa raconter des Zelda comme si c'était un livre interactif. Il a envie de prendre la manette. Oh, bien sûr il a déjà un peu chipoté dans Rayman Origins ou New Super Mario Bros Wii, mais surtout en mode "bac à sable" ou en mode "ouhla, ça devient dur, j'me mets en bulle".
Son premier vrai jeu est donc Boing! Docomodake un petit jeu mignon qui m'avait été recommandé par Pierrick, à mi-chemin entre lemmings et Rick Dangerous à la sauce bisounours (comprenez, sans les pics qui sortent du sol, et sans que les lemmings n'avancent sans vous). Tout à fait adapté à son niveau, même si moi, perso, le jeu m'avait lassé très rapidement tellement tout était lent dedans.
Pourtant, niveau interactions, c'est assez riche. On bouge avec la croix, on fait apparaître des petits champignons qu'on déplace pour faire des ponts, des échelles, des contre-poids, etc. on bouge encore. On en ramasse pour les lancer sur les (rares) ennemis. Il avance pas trop mal.
Puis l'autre jour il fait un blocage "papa, il faut que tu tires sur la libellule". Papa gribouillait, il encourage le fiston à essayer lui-même "tu te prépares, tu vois, tu t'avances". Rien n'y fait. "mais j'ai peur"!
Et là, j'ai compris la grande puissance du jeu vidéo pour affronter ses peurs. "Regarde, le jeu il est là. Toi tu es ici. Tu es en sécurité: il ne peut rien arriver. Au pire, il y a des petits pixels qui vont un peu changer de couleur, mais tu ne risque rien. Allez, c'est l'occasion parfaite pour apprendre à être plus fort que ta peur".
Beaucoup plus difficile pour lui, par contre, c'est de faire face à la frustration quand il se rend compte qu'il a loupé un coffre (généralement en fin de niveau) et qu'il est impossible de faire marche arrière parce que le développeur a voulu que seul celui qui réfléchit et planifie puisse l'avoir. Là, au bout d'un quart d'heure de concentration pour passer tous les obstacles et récupérer les pièces d'or, ça peut facilement éclater en crise de pleurs qui confirmeront qu'il est temps de jouer à autre chose...
Monday, April 30, 2018
Même pas peur
Sunday, April 29, 2018
definition files in geds3
Meanwhile, I'm digging what sort of additional definitions a "Behaviour Editor on DS" should read, and how that would be translated into .h files that convert the "level 2" scripts into plain "level 0 scripts" that can be parsed by the runtime engine on the DS. I'd allow e.g. BEDS to do more lookups in symbol tables while all symbols should normally be translated into values or expressions in level 0 when loading levels in a game.
Maybe you wonder "but what is level 1?" ... well, level 1 is what I'm doing right now with Bilou School Rush, with the C pre-processor expanding symbols for us so that I can write "$RUNLEFT->$RUNRIGHT on eDpad [D_RIGHT]" instead of "statl12->statr13 on event0 [v2 $20 &]".
Sunday, April 22, 2018
to $(AR) or not to $(AR)
During the preparation of the "controllers" tutorial, I faced a weird linking problem. I wanted to split the huge "controllers.cxx" file so that every controller would be in a sub-file that could be compiled separately and no longer depend on the code from other controllers unless there is a good reason for that. And all of suddens, I had no more factories registered.
Just before that, I had reviewed the factory registering system so that it was enough to just write MomentumFactory mf("momentum");
as a top-level declaration to get everything up and running. But that meant there was no more reference from the main .o files of the game/demo that would require .o files with the factory code (and instance declaration), so they wouldn't be packed in, and certainly wouldn't be initialized either.
So I started thinking about weird mechanisms invoking bool pointers to dummy variables, or no-code functions, and even why not UsingPlatformer
empty class that would extend UsingMomentum
, UsingDpad
and others... Then I realized that all this happened because the .o files (compilation output, that is. Equivalent of your *.OBJ if you're on MS-DOS) are packed into a static library and only pulled to populate the .NDS file on-demand at link-time. If instead I explicitly say "link Demo/*.o Controllers/*.o", they are put into the binary and no trick is needed anymore.
Wednesday, April 18, 2018
shell functions
For so long, I have been creating aliases for my shell. "dir" would be "ls -la" and things like that. TCSH even had ways to retrieve some attributes to the aliases. building 20 student programs and testing them would have merely required me to type N (for next), B (for build) and T (to launch simple tests). Do I need to fix something to better evaluate their program ? B again, then T again.
But it had its drawbacks, and it was pretty ugly to code. Nowadays, I'd do that with shell function instead. Rather than trying to rewrite the statement, it truly allows me to extract all the arguments (either separately or together) and then calling one or more commands
cl()
{
color.pl $* | less -R
}
One last place here I used aliases is with the "quick cd" tool I use to keep my brain sane and my screen not-excessively-cluttered
#!/usr/bin/bash
export CITY=$(pwd)
echo "You are in the City. $CITY"
echo "You can set 4 locations. North, South, East and West."
alias setN='export NORTH=$(pwd)'
alias setW='export WEST=$(pwd)'
alias setE='export EAST=$(pwd)'
alias setS='export SOUTH=$(pwd)'
alias setC='export CITY=$(pwd)'
alias N='cd $NORTH'
alias S='cd $SOUTH'
alias E='cd $EAST'
alias W='cd $WEST'
alias C='cd $CITY'
And yes, it pretends that you're running an old-fashioned, text-based adventure game instead of crawling directories. Because i found it easier to thing of thinks as "west", "north", etc. rather than trying to remember what letter I used for "gstreamer" and what letter was for "alsa".
Saturday, April 14, 2018
Dear ImGUI,
I hope you enjoyed the week-end. It sure was a pleasure to have you around, and getting some pixels rendered without having to bother with ./configure, plugging events into sockets or any kind of new classes.
Sure, I wish you had time to stay for tea and I would have shown you my SpritePages, but I suppose that can be kept for another encounter. I'm pretty sure you and I are meant to meet each other pretty soon.
Everyone was amazed when you just returned "true" in the line of code that painted a new button. Imagine the face they'll have next time when we'll show them GobState representations live and pop up new windows as one explore the state machine...
Stay Safe,
/PypeBros.
PS: okay, the unit-tester requiring 32-bit (so that DS registers addresses are out of the .text segment) and SDL requiring 64-bit won't simplify early integration tests ... we'll find some workaround.
Monday, April 09, 2018
Tutorial revision goes on.
What is really interesting here is that it forces me to get rid of many odd things. Hopefully, that will lead to a code base that will be easier to extend. Things like "rules.gam", for instance.
Being busy reviewing the expressions system, for instance, make it obvious that some static array could be gone now that I have the gob collision structure. the "game counter al so cry for a refactoring out of the GameScript class. And making the 'guns/controllers' system easier to understand (esp. by automating the registration system) made it obvious that I need to re-think the way classes access the Camera object.
Tags: coding, gobscript, refactoring, tutogit
Wednesday, April 04, 2018
Tutoriel libgeds - day 4
Bon, il est temps de vous montrer ce que libgeds peut faire pour ceux qui n'ont pas le C++ dans le sang. Charger des fichiers, définir des animations, positionner les ennemis dans le niveau, tout ça peut être fait à partir de commandes dans des scripts texte lus et transformés en objets C++ par la bibliothèque.
Je vais commencer par un sous-script qui décrit le comportement d'un personnage. On va commencer très simple, avec une seule animation, et toujours le même comportement: ne pas bouger. Voici donc "xdad.cmd"
# this is xdad.cmd behaviour description anim1 0 { spr0 4 delay 3 spr0 5 delay 3 spr0 6 delay 3 spr0 7 delay 3 spr0 8 delay 3 spr0 9 delay 3 spr0 a delay 3 spr0 b delay 3 loop } state0 :anim1 end
Le bloc 'anim<numéro-d-animation>' donne utilise une page du SpriteSet et construit une animation en indiquant les images à utiliser (dans cette page) et combien de temps attendre entre chaque deux images. On peut ensuite l'attacher à un état, c'est à dire une unité élémentaire de comportement . Bon, évidemment, pour l'instant, avec un seul état, il ne se passera pas grand-chose. C'est un peu notre 'hello world'.
Un fichier comme xdad.cmd, on en créera un par type de personnage (imaginez "goomba.cmd", "koopa.cmd", etc.) Maintenant, il va nous falloir un script qui décrit un niveau. Ce sera demo.cmd, pour nous.
#demo.cmd, resource management print "loading tileset" bg0.load "../bg.spr" print "loading sprites" spr.load "../hero.spr":1
#demo.cmd, use 'character' description input "xdad.cmd" import state 0
Pourtant, seuls un ou deux de ces états sont nécessaires pour décrire le niveau (commencer tourné vers la droite ou vers la gauche, par exemple, ou éventuellement par une glissade). Geds propose donc un jeu d'identifiants pour l'ensemble des états d'un personnage (tous les états d'un goomba, par exemple) qui sera utilisé dans xdad.cmd, et l'ensemble des états utilisables pour créer des nouveaux objets (un goomba, mario, un koopa rouge ou un koopa vert), qui sera utilisé dans demo.cmd.
Une fois le traitement xdad.cmd terminé, la commande 'import state 0' indique de prendre le premier état de l'ensemble de xdad et d'en faire l'état numéro 0 pour demo.cmd.
# creating gobs gob0 :state0 (128, 100) end
Comme on le voit sur github, on laisse tomber la classe Hero: il s'agit maintenant d'un GameObject construit et contrôlé directement par la bibliothèque suite au commandes du script.
La classe 'MetaWindow', point de départ de notre démo, a pas mal changé aussi.
#include <GameWindow.hpp> class MetaWindow : public DownWindow { NOCOPY(MetaWindow); Window *active; InputReader* reader; LoadingWindow loadwin; GameWindow gamewin; public: MetaWindow(): active(0), reader(0), loadwin(&reader), gamewin(this, &reader, &loadwin) { ntxm9 = new NTXM9(); // for the sound, remember ? active = &gamewin; }
void setactive() { FileDataReader fd("efs:/sndtrk.xm"); reader = new FileReader("efs:/demo.cmd"); ntxm9->stop(); u16 err = ntxm9->load(&fd); ge.setWindow(active); restore(); // just to have the tileset shown again. if (err!=0) iprintf("ntxm says %x\n",err); }
Et c'est tout. A la prochaine fois pour rendre ses déplacement à notre petit père Noël.
Tags: tutogit
Tutoriel libgeds - jour 5
Redonner du mouvement au personnage dans geds, ça correspond à spécifier une série de contrôleurs pour l'état choisi. Chaque contrôleur a une mission bien précise, p.ex. ici
state0 :anim1 { using dpad using momentum(x to 512) using momentum(y to 512) }
momentum va utiliser les directions sauvées pour augmenter ou diminuer la vitesse horizontale ou verticale (selon qu'on a utilisé "x" ou "y")
On peut aussi passer des paramètres aux contrôleurs: c'est le cas ici du "512" qu'il faut interpréter comme un nombre de 256emes de pixels par frame (1/60eme de seconde) et qui représente la vitesse maximale autorisée sur un axe.
Le ScriptParser cherchera les classes C++ correspondantes et fait le nécessaire pour que le code qu'elles contiennent soient appelées à chaque image générée par le jeu.
Trois lignes de plus dans le script donc (et quelques modifications dans les Makefiles). C'est tout.
Tags: iGobController, tutogit