Thursday, May 28, 2009

sendall

J'ai toujours été intrigué par cette fonction "sendall" du Beej Network Programming Guide. Selon Beej, un appel à send pour transmettre des données pourrait ne pas nécessairement envoyer autant de données que prévu. J'ai toujours trouvé ça un peu surprenant et je n'avais personnellement jamais été témoins d'une telle chose jusqu'à aujourd'hui.

Corrigeant les TP de programmation de BitTorrent, j'ai un strace ouvert aussi sur le client initial dans un "environnement de test contrôlé" et voilà que j'aperçois la séquence suivante:

send(10, "\0\0\200\t\7\0\0\0(\0\0\0\0\2619\r\222\265\315r\264a\363"..., 32781, 0) = 32781
send(10, "\0\0\200\t\7\0\0\0(\0\1\0\0\340\306\335\246\17\r\377\265"..., 32781, 0) = 32781
send(10, "\0\0\200\t\7\0\0\0(\0\2\0\0\233\257\314\25P\322\2363\316"..., 32781, 0) = 32781
send(10, "\0\0\200\t\7\0\0\0(\0\3\0\0002\235\311\36yyzt\322\363$"..., 32781, 0) = 28790
send(10, "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"..., 3991, 0) = 3991


Le programme tente d'envoyer des données de 32K accompagnées de 13 bytes de contrôle. Le plus souvent, celà signifie qu'un buffer de 32781 bytes est passé à l'appel-système send (cf. le 3eme argument) et que 32781 bytes ont effectivement été envoyés (cf. la valeur de retour, après le '='). Sauf pour les deux derniers, où si on a bien 32K+7 soumis, seuls 28790 bytes ont pu effectivement être "envoyés" ... Je devrais plutôt dire "pris en charge par le protocole TCP". Effectivement, TCP a sa propre mémoire-tampon dans laquelle il conserve les données à envoyer, mais elle n'est pas infinie. Si a un moment donné elle "déborde", TCP prend le plus de données possibles mais signale à l'application qu'une partie n'a pas pu être traitée.

On aurait pu préférer une approche "l'appel va être bloquant jusqu'à ce que tous les bytes soumis soient traités". Bin ce n'est pas forcément le cas, et ce n'est pas plus mal: l'application a peut-être quelque-chose de plus utile à faire avant de ré-envoyer le reste.

Comme j'ai de temps en temps des fichiers qui "passent mal" avec les transfers wifi de runme, je regarderai à l'occasion si je ne ferais pas bien de rajouter un "sendall" ici ou là.

PS: au passage, Beej a finalement fait une version "bouquin" de son superbe tutoriel.

Monday, May 25, 2009

Lâcher prise ...

Zeblackos (concepteur du jeu "Plop" et fan the "Thing on a Spring") m'a ému en écrivant l'autre jour:

D'ailleurs, c'est bien ça qui m'épate le plus : depuis le temps que tu es sur ce projet, je ne sais pas comment tu as fait pour ne pas lâcher prise O_o
C'est très impressionnant.


Je ne me l'explique pas. C'est à la fois chouette et effrayant. Chouette parce que bien que l'idée ait été lancée il y a près de 15 ans, je continue à bosser sur le projet -- toujours changeant, mais toujours présent. Effrayant, parce que c'en est presque une malédiction: tout "déclic créatif" finit par produire une idée pour le projet Bilou. Je me nourris des jeux auquels je joue, des bouquins que je lis, des pubs que je subis, des musiques de mon frère, de petits dessins, etc. Puis à un moment, ça donne ceci:

Non, je ne mettrai pas de plate-formes volantes comme dans Keen. C'est trop simple, éculé. Ni de haricot magique. Pourtant il faut bien que quelque-chose permette au joueur de "revenir sur ses pas" après qu'il soit tombé sans avoir recours à un passage secret par-dessous l'arbre. Puis s'esquisse un drôle de champignon au chapeau tout plat qui se transforme en ascenseur involontaire sur une feuille de papier brouillon. Une sorte de mini-strip qui prend forme, sans grande prétention pour aller rejoindre la série des "on the road". Mais ça va faire un titillement de plus qui ne me lâchera pas tant que je ne l'aurai pas transformé en "cyber-réalité" faite de jolis pixels tout colorés.

Ainsi, chaque fois que je vois la bannière sur mon blog, mon esprit prolonge le mouvement et Bilou atterri sur la souche dans un nuage de fumée qui fait "pouf". Un jour ce sera codé. Idem pour le saut d'encrier en encrier. Je changerai alors ma bannière pour y intégrer une nouvelle "toudouliste".

Saturday, May 23, 2009

parallaxe ... foireux.

Petit test de scrolling parallaxe ce matin (entre vidange du garage et achat de papier peint) qui est encourageant sans vraiment être satisfaisant. C'est ma première tentative de charger plusieurs tilesets différents en mémoire, et je dois maintenant combiner une "infinimap" (dont l'image est modifiée au fil du scroll) avec une "wrapping map" (dont l'image reste fixe mais "tourne en boucle").

Les pommes sur fond blanc témoignent d'une petite réorganisation de la VRAM. J'ai réglé tout ça un peu vite à mon goût et il faudra que je prenne le temps d'ajuster le code pour qu'il fonctionne correctement sans dépendre d'effets curieux du genre "if bg==2 ...".

I wanted to bring the real (parallax) background in my woods this morning, but it didn't came as 'fluently' as i hoped in the code. Things were not quite ready for mixing wrapping maps and large maps, not quite ready either to host several tilesets in vRAM or to load an odd number of colors. I had to put ugly patches here and there to show the feature. A proper way to "split" SpriteRam in several banks is required in the future, as well as a real "WrappingMap" class and an update of the map-related script parsing functions. Well, anyway, even though my camera isn't as neat as Kram's, it's more "sexy" this way than with the dark-red background.

PS: since the demo is now released, now, it's time for a new "todo list", reusing wishes from the former one.

  • [done] have the "level exit" activated when enough apples have been picked.
  • [done] increase homogeneity of collision detections
  • [done] pre-define values when initializing GOBs in script (e.g. set Funghi's counter)
  • [done] blocking ennemies: e.g. you can't pass through Funky
  • [done] bilou can tell whether he has been "hit" by an ennemy or an apple
  • [done] code cleanup : upgradable "block info"
  • [done] register "action on counter back to zero"
  • [think..., done] substrate for "shooting" (dust clouds, stars, etc.)
  • [wish] code cleanup: more states, more anims (array -> maps in GameScript)
  • [wish] support multi-palette environment (by now, i'm just lucky it works fine !) or 16 color backgrounds
  • [wish] provide a cleaner way to have parallax scrolling (and more maps)
  • [done] make sure we can change/end level!
  • [done] add sound fx support
  • [wish] add music selection in the GameScript!
  • [done] loading SpriteSet with odd number of colors properly
  • [done] execute scripts non-interactively in demos.
Note: le parallaxe figurait dans mes "todo list" depuis décembre 2007 quand même ...

Friday, May 22, 2009

Moon walk ?

As seen in former post: Scripting Sunday:

TODO: moving Bilou through the animation isn't the right way to go. Maybe "delay x" in the animation sequence to have the next frame triggered only when we move to the next pixel would be better
Faire marcher un personnage est loin d'être une tâche facile et en particulier, ça demande une synchronisation parfaite entre le déplacement du sprite et son animation. Le moindre décalage et le joueur aura l'impression que le personnage "glisse" sur le sol au lieu de marcher. En clair, le pied en contact avec le sol doit rester au même endroit par rapport au sol jusqu'à ce qu'il se lève. Ce genre de défaut était assez fréquent dans les jeux de mon enfance (hein, Eric ;). Une manière assez simple d'y remédier est évidemment de faire courir le personnage, de préférence "à la supermario"

La solution que je pensais y apporter était relativement simple: intégrer les déplacements dans l'animation à coup de "move x y" entre deux images. C'est comme ça que je déplace le wooworm et ça réussit plutôt bien. Le hic, c'est de combiner ça avec une vitesse éventuellement variable et le test des collisions qui a été ramené dans le contrôleur (qui ignore tout de l'animation en cours).

I've never been satisfied by typical game-making animation tool that just let you define a constant moving speed (e.g. one pixel per frame) and an walking animation that you try to match that. It always gave me the feeling that the hero is "sliperring" on the ground or walks with rollers. I initially planned to fix this by integrating moves to the animation itself (i.e. 'show frame A, then wait for 2 frames, move by 2 pixels horizontally and show frame B'). That's how woodworm works, but i couldn't simply extended to Bilou's walk... Not until a friend of mine suggested that i could also delay the animation _until sufficient movement has been accumulated to 'hop' two pixels away_. Here comes the specific code that does that (only when the animation is "self-moving", which would be typical from ladder climbing, walking and other "friction-based" moves.

C'est Pierrick qui m'a donné la solution a mon problème en racontant comment du temps du CPC il faisait faire des sauts "réalistes" à son petit bilou en modifiant la durée d'affichage à chaque emplacement vu qu'il lui était impossible de placer le bilou (eh oui, c'était lui) entre deux tiles (pas de sprites en CPC basic ?). Plutôt que de chercher midi à 14 heures (du genre "modifier la vitesse d'écoulement du temps pour que Bilou coure plus vite"), j'ai juste changé l'interprétation de "move x y" en "ne passe à l'étape d'animation suivante qu'une fois que le contrôleur aura 'accumulé' le décalage suffisant. Traduit en code, ça donne :

inline bool trymove(int dx, int dy) {
    forcechecks=false;
    if (selfmove) {
        int cflags  = cast==HERO?F_PLAYERTHRU:F_MONSTERTHRU;
        bool notyet = (dx>0 && cdata[4]<dx) || (dx<0 && cdata[4]>dx)
                   || (dy>0 && cdata[5]<dy) || (dy<0 && cdata[5]>dy);
        if (notyet) return false;
        if (cando(dx,dy, cflags)==cflags)  {
            x+=dx; cdata[4]-=dx;
            y+=dy; cdata[5]-=dy;
            return true;
        } else {
            cdata[4]=0; cdata[5]=0;
            return setstate(state->dochecks(x>>8,y>>8,world, cdata));
        }
    } else {
        x+=dx;
        y+=dy;
        return true;
    }
}
  • selfmove est défini par état : true pour monter à l'échelle, false pour tomber, etc.
  • cdata[STEPX] et [STEPY] accumule les valeurs de cdata[XSPEED] et cdata[YSPEED] (vitesses définies par le contrôleur) en mode "selfmove" (normalement, on a directement x+=cdata[0])
  • trymove(dx,dy) est appelé lorsqu'une étape d'animation utilse la commande "MOVE"
  • condloop et check permettent de vérifier les testpoints sur des frames données (p.ex. quand le personnage a de nouveau les pieds au sol).
Voilà. J'avais envie de démystifier ça. J'espère que ça sera utile à l'un ou l'autre.

A pair of per-object variables (cdata[])will thus be used to accumulate some intended move until that "step" size becomes large enough for the move x y instruction found in the animation list. The trymove(dx, dy) tells whether such a move is possible right now or must wait until more motion has been accumulated.

edit: De manière étonnante, Miyamoto avait lui fait le choix délibéré, dès Donkey Kong, de casser le lien entre animation et déplacement parce qu'il jugeait qu'une animation de marche réaliste "ne collait pas à l'action frénétique d'un jeu vidéo" (l'Histoire de Mario, p.240)

2024 #choice reality check: It is still there, and I like how it makes many character feel like they're in contact with the ground. But let's be honest, it makes the code a bit more complicated every year. It makes it possible to have characters whose motion accelerates and decelerates over one step with a constant average speed, but offseting the graphics for a truly-constant-speed could achieve something similar, and that wouldn't even be complicated for a compound sprite. So there I am. Maybe this was not a good choice, but I haven't replaced it yet.

Tuesday, May 19, 2009

Le Bilou Nouveau est arrivé...

Comme promis, voilà la nouvelle démo de mon moteur de jeu. Ce n'est pas encore parfait, bien sûr, tant au niveau technique qu'au niveau graphique ou gameplay, mais ça vous permettra de voir faire une meilleure idée de ce sur quoi je travaille.

L'objectif est de récolter toutes les pommes du niveau, et un petit "GREAT" vous félicitera si vous en trouvez 16. Vous pourrez vous faire "blesser" (aussi souvent que vous le voudrez) au sol, mais pour l'instant, vous êtes invincibles en saut. Et il me manque toujours un fond convainquant.

Bref ... Work in progress.

Here you finally get it: a new demonstration of my game engine with my most up-to-date pixel art. It's not perfect, of course. Neither graphically, technically or in regards to gameplay. But at least it gives a better view of what i'm working on.

So far, your mission is to collect as much apples as you get (and you can get all of them in one row), a message "**GREAT**" will show you you've got 16 of them. Note, too, that you'll never get hurt while jumping. And yeah, it'd be much better with a background of some sort.

download gedsdemo.nds



PS: dans cette version, il vous faut toujours appuyer quelques fois sur "Y" au démarrage de la démo pour lui forcer à "lire" le script du niveau. C'est une de mes priorités de retirer ça pour la prochaine démo, bien sûr.

PPS: last update: 2009/05/20: Kram reported a bug on real hardware. Fixed.

Greetings fly to: NODA (efs lib), OxTob (ntxm), the devkitpro team, Kram (DS2DS), CJ (R4), Pierrick & Tbob (music), lackey, victorX, pixelaroo, arachne, zeid, Helm and many more pixel pushers at Pixelation for artistic advices, sourceforge & blogger for project hosting.

Suivre le développement du projet ...
Read progress reports

Monday, May 18, 2009

Demo coming soon

Encore un peu de patience. Le plus gros du boulot est fait, j'ai juste à "packager" les éléments de ma plate-forme de développement SEDS/LEDS/runme en un petit .nds autonome. Et éventuellement rajouter une animation pour que Bilou puisse se faire écraser par les champignons.

Après ça, release d'une petite démo jouable que j'espère plus convaincante que celle de juin 2008. Comptabiliser l'énergie de Bilou ne devrait pas être trop difficile à ajouter, par contre je ne sais pas encore comment m'y prendre pour redémarrer le niveau s'il meurt, etc. Il est possible que je garde ça pour plus tard.

Just a few more days ... Apples works, collisions works, all i need is packaging of code and media files into a single, standalone ".nds" file that you can download and try on your homebrew-ready DS. Hopefully, i'll also add an extra animation so that funghis can stomp Bilou and you'll get a playable demo of what i've been up to since June 2008.

Stay tuned.

Friday, May 08, 2009

Game Engine progress report

Bonne nouvelle: le mécanisme de gestion des collisions entre sprites (re)prend forme. J'avais déjà fait quelques tests dans la version précédente, mais cette fois-ci, la réaction aux collisions peut être programmée: Bilou sursaute lorsqu'un ver le touche mais il peut écraser le ver en question en lui sautant sur la tête, comme dans Mario.

Good news from the Game Engine: sprite-to-sprite collisions management is (re-)enabled. I already had a former release where the screen flashed to red when Bilou hit a monster, but this time i can script the desired response to collisions. For instance, Bilou will be "hit" when touched by a Woodworm, but he can stomp the same woodworm by jumping on its head.

Il y a encore un peu de boulot avant de pouvoir faire une "release" de la nouvelle petite démo:

  • [wish] increase homogeneity of collision detections
  • [done] have apples animated once again
  • [done] have Bilou collecting apples
  • [patched] more states, more anims (array -> maps in GameScript)
  • [wish] have the "level exit" activated when all the apples have been picked.
  • [done] rationalise memory use in libntxm (less mallocs/realloc) and track array overflows
Et au passage, il faudra aussi que je fasse un peu le ménage côté "gestion de la mémoire". La libntxm étant au départ prévue pour un éditeur de modules, elle a tendance à faire des reallocs dans tous les sens (trop souvent source d'erreur à mon goût) et j'ai régulièrement des pointeurs qui sont devenus (?) invalides au moment de la destruction du mod en cours.

(wishes and cleanups kept in the current todo list)