Friday, December 28, 2007

Phantom Hourglass

Je l'ai attendu pendant pas mal de temps... J'ai résisté tout le temps de la finalisation de thèse. Maintenant je l'ai: ma fée m'a offert "Phantom Hourglass" pour ma Noël ^_^

Persos en 3D et contrôle au stylet, je dois dire que je n'étais qu'à moitié convaincu que ça allait me plaire (je n'ai jamais été un grand fan des jeux 3D et le côté "low polygons" de "Ocarina of Time" et "Majora's Mask" était très décevant à mon sens).

La première bonne nouvelle, c'est que dans les phases de jeu, la 3D passe plutôt bien (grâce à la vue d'en haut qui conserve le gameplay d'un zelda classique, notamment). Du point de vue des personnages, par contre, je trouve qu'on a perdu de la "magie" par rapport à "Minish Cap" sur GBA. Ils ont un peu tous l'air de porter des masques en toile de jute peinturées à la place du visage, rebondissent en parlant d'une manière assez peu naturelle. Bref, on est loin des minish mimi-tout-plein en pixel art du volet précédent. snif.

Le stylet, par contre, est redoutable, même si j'ai tendance à vouloir utiliser la croix pour déplacer link à certains moments (dans les combats, notamment, c'est difficile d'esquiver un grand nombre d'ennemis). On quitte le mode 'contrôle absolu' des jeux précédents pour quelque-chose qui ressemble d'avantage à un "command&conquer". Si certains mouvements (roulade, épée tournoyante) sont plus difficiles à exécuter que dans les bons-vieux-zelda-en-pixels (je l'ai dit), le boomerang dont on peut tracer la trajectoire compense largement. C'est d'ailleurs une de mes techniques de combat préférée: assomer la plus grande partie des grogneurs à coup de boomerang pour aller me concentrer sur un monstre pendant que les autres comptent les ptits zoizos.

Reste le très controversé "temple du roi des mers", ou "temple du sablier fantôme" ou "temple maudit". Appelez-le comme vous voudrez. Avec ces gardiens-spectres indestructibles, il introduit une dimension "infiltration" assez nouvelle dans le genre. Je le trouve stressant. Très stressant. Mais avec une bonne mémoire et des notes correctes prises sur la carte, on ne s'en sort finalement pas si mal. Oui, on doit le revisiter plusieurs fois, mais à chaque visite, on dispose de nouveaux "outils" (bombes, pelle) qui permettent au joueur attentif de prendre de fameux raccourcis et de grapiller des secondes supplémentaires dans les jarres dorées. Ajoutez à celà des minutes gratuites retrouvées au fond des mers, et je suis arrivé au "blason du soleil" avec 8'42" restantes (contre moins de 2 minutes de temps restant la dernière fois que j'ai du le faire.

Bon, évidemment, ce serait trop beau si ça avait été un rien utile. Bin non. Je me suis précipité jusque là pour rien. La "clé solaire", c'est pour un autre temple, ailleurs ...

Les dongeons sont chouettes (enfin, corsés, quoi, mais on s'en sort sans la soluce à l'exception de deux ou trois énigmes dont les indices sont donnés de manière foireuse). Les boss bien dosés (quoi qu'aucun d'eux ne m'aient encore tué :P) ... Je suis déjà au navire fantôme en seulement 3 jours ... C'est grave, docteur ?

edit: ma fée vient ingénument de tirer la cartouche du jeu que j'avais laissé en veille avant d'essayer de ramener la quatrième soeur au début du bateau fantôme pour faire ses exercices d'entrainement cérébral. Comme vous pouvez le voir, elle ne recule vraiment devant aucun sacrifice pour rallonger la durée de vie de son cadeau ^^"

edit+:
c'est bien, le stylet, mais dans les combats contre les boss, ça a un inconvénient majeur: ça glisse des doigts. Croyez-le si vous le voulez, mais je me suis retrouvé crétin comme un lapin pendant le combat contre le crabe invisible qu'il faut viser entre les yeux à avoir mon stylet qui me "zippe" entre les doigts! Ledit crabe en profite naturellement pour me choper et le jeu dit "frotte l'écran pour te libérer". Ah ouaiche.
Je m'en suis sorti quand-même, mais de justesse. 'Suis pas sûr d'être 100% prêt pour Twilight Princess sur la Wii, moi ^^"

edit++: oh, j'aurais peut-être dû préciser que mon Zelda préféré (toutes catégories) était "Link's Awakening" sur le tout vieux GameBoy. Vous comprendrez sans doute mieux ma difficulté à accrocher à OT et MM, du coup :P

edit+++: vous êtes coincés mais vous n'avez pas envie de consulter la soluce du jeu ? repassez faire un bonjour à la voyante de l'île du feu. C'est gratuit et elle aura peut-être même un petit cadeau pour vous ;)

Friday, December 21, 2007

spr2html ^_^

Il parait que j'ai tendance à utiliser HTML pour tout et n'importe quoi ... j'ai bien peur d'avoir remis ça ... J'avais bien un petit script capable de transformer une image (de préférence un niveau de jeu) en un 'SpriteSet' (que j'utilisais pour les tests de scrolling), mais jusqu'ici je n'avais rien d'équivalent pour le sens "retour".

Et comme j'ai un peu la flemme d'écrire des pixels sur une image .png, je me suis plutôt tourner sur une jolie petite table HTML. Avouez que le résultat est plutôt réussi, non ? bon, évidemment pour l'instant on ne voit encore que les "tiles" un par un, tels qu'ils sont dans la mémoire vidéo, mais encore un peu de chipotage, et je pourrai les voir par "bloc" de 16x16 ...

De quoi simplifier les procédures de conversion de données que je vais devoir faire... Parce que là, sans un éditeur de map, je n'irai pas beaucoup plus loin. Animer les pommes qui n'utilisent pas des tiles consécutives. bof.

So far, the tiles you edited with SEDS could only be opened with SEDS (or shown on your DS screen through the 'runme' companion program). That was true until yesterday. Here comes the "spr2html" converter tool that can turn those "opaque" .spr files into a bunch of HTML tables that show palettes and tilesets contained in the spriteset. So far, it is mostly a debugging tool for the other manipulation scripts (merging sprite sheets, converting colors, etc) that prooved to be more efficient than beaming files to the DS and back, but it should be quite trivial to upgrade into a full-featured "exporter" that would produce .png pictures straight out of my .spr files...

edit: et je me rends compte de la raison des palettes "toutes mélangées" que j'ai obtenues dans mes "livres de sprites" qui rassemblent plusieurs planches séparées: je comptais les couleurs 1,10,11,...,19,2,20,21, ... 29,3 ... à chaque étape, alors forcément, quand on répête ça, on finit par un jeu de couleurs tellement mélangé qu'on est prêt pour une petite belote :P

oh, for those who wonders, i've used the "bgcolor" attribute of "td" tags and and solely filled my table cells with to ensure they'd have the proper size. That doesn't seem to please all browsers around, but as long as one of them (konqueror, but not firefox) renders it fine, i'm happy.

Wednesday, December 19, 2007

Plagiat ?

"C'est quoi, ce plagiat de Worms" demandait Bodman il y a 2 ou 3 posts... Euh, j'avoue, j'ai toujours été un fan du jeu, et quand j'ai du "relifter" mon "yelloworm" pour la forêt de Bilou et qu'une silouhette un peu "wormesque" est sortie sur ma petite grille 16x16 de SEDS, j'ai trouvé qu'elle donnait plutôt bien.

Du coup, les illustrations sont encore un peu plus "worm-inspirées". Mais j'ai un affreux doute. Mon ver jaune pixelisé est il assez "original", ou donne-t-il l'impression d'un repompage honteux du jeu de Team 17 ? C'est un peu le défaut des blogs, à mon avis. Je lis régulièrement les messages de bodman et j'imagine qu'il lit mon blog aussi, mais je n'ai aucun moyen de l'inviter à une petite discussion sur ce qu'il pense réellement de mon ver, au-delà de ce qu'il a déjà dit. Personne ne laisse d'adresse mail nulle-part vu qu'on a tous peur de recevoir (encore plus) de spam ... Bin moi, mon e-mail c'est pype_1999.geo@yahoo.com. Et je ne vois pas comment je pourrais avoir encore plus de spam là que je n'en reçois déjà. Donc, si bodman ou un autre veut prendre contact pour une petite discussion sur ICQ (#98176626) ou msn (je vous enverrai mon adresse par retour de hibou), you're welcome ;)

edit: après une (chouette) petite discussion sur ICQ, j'ai fini par apprendre que bodman avait visiblement fort idéalisé les petits vers de la première version de Worms, qui sont beaucoup plus proche des lemmings, et avec des yeux biens plus proéminents. Non, à la réflection, je pense avoir réussi un bon croisement entre le Worms Armageddon et le "Poison Slug" de Commander Keen. Un double clin d'oeil, donc.

oh, et la démo du Worms original de 1995 est un peu lente dans dosbox, mais tout à fait jouable ^_^

Monday, December 17, 2007

Des pentes et des testpoints ...

Je relisais ce document sur la réalisation du jeu M.C. Kids, et j'ai enfin compris pourquoi ils avaient eu tant de mal à prendre en compte les pentes dans la "gestion des collisions". (J'ai un peu du mal à parler de détection de collision entre sprite et décor, vu que j'ai utilisé ce terme pour les collisions sprite-sprite pendant des années ;)

Bref. L'idée globale des testpoints, c'est s'assurer que le testpoint situé sous le personnage soit toujours à la frontière entre le "ciel" et le "sol". Ultra-simple sur des horizontales, un peu plus subtil sur une pente (mais grosso-modo il suffit d'ajuster le déplacement vertical en fonction du déplacement horizontal). Le hic, c'est de passer d'une surface horizontale à une pente. LE hic, c'est que la pente commence devant notre personnage alors que le point-test que l'on doit garder sur cette pente est sous le personnage (ici, yelloworm). En clair, notre worm va soit s'arrêter avant la pente (s'il la considère comme un mur), soit rentrer dans le premier tile puis s'arrêter au premier bloc de "mur" complet.

Dans M.C. Kids (et selon les dires de l'auteur, dans SMB3 également), ils résolvent le problème en introduisant un nouveau type de tiles: le "bas de colline", qui est placé dans le sol, dans le prolongement de la pente à amorcer. Ca marche, bien sûr, mais personnellement, je trouve ça un peu "bricolage". Un autre point qu'ils mettent en avant, c'est l'importance de garder un nombre de "test de map" fixe et le plus réduit possible -- de préférence un tile par testpoint.

Mais nous avons de toutes façon un testpoint devant notre personnage: celui qui sert à déterminer si oui ou non on arrive dans un mur. Et il est important de s'assurer qu'il soit suffisamment bas pour qu'il stoppe Bilou (et le yelloworm) même si le mur est très bas.

Du coup, on peut en profiter pour détecter le début d'une pente quand on arrive un tile avant. Il nous reste alors à ajuster la vitesse verticale de manière à ce que, un tile plus loin, on soit monté d'un pixel. On sera alors effectivement "sur" la pente. Bingo.

Il faudra évidemment s'arranger pour que l'angle entre les deux testpoints soit suffisant par rapport à l'angle de la pente la plus forte dans le jeu, mais ça, ça ne devrait pas nous poser de problème particulier.

Voilà. C'était ma cogitation du dimanche un peu en retard ... j'espère que c'était suivable ^_^

Tile Racer

une fois n'est pas coutume, c'est d'un jeu PC que je voudrais mettre en avant. "Tile Racer", une reprise du concept de "Stunts 4D Driving" par trois étudiants autrichiens, qui -- à mon avis -- vaudra le coup d'être testé.
Comme dans S4DD, vous pourrez construire vos propres circuits de dingues (mêlant tonneaux, loopings, rampes, tremplins, etc) à l'aide d'un éditeur basé sur le modêle des "tiles" (mosaïques, en gros) avant d'y faire une petite course contre la montre.

Patience: l'adversaire IA est en cours :P

Saturday, December 15, 2007

demi-tour, marche!

Et voilà. Le mécanisme des "testpoints" est ajouté. Avant de recommencer chaque étape d'animation, mon petit ver s'assure qu'il ne rentre pas dans un mur et qu'il ne tombe pas. Je ne suis pas certain que ça conviendra pour tout le monde (Bilou, en particulier).

Il faudra aussi que j'automatise le demi-tour (pour l'instant, le ver s'arrête au bord, et je lui fais faire demi-tour "à la main" en programmant la deuxième animation.

edit: yes! le petit ver est maintenant entièrement autonome et toujours avec un code 100% générique. Une petite machine d'état avec des animations de "pause" entre les allées et venues, et ça y est. Et je peux en mettre autant que je veux! il suffit de rajouter une ligne dans test.cmd ;) Etapes suivantes:
  • animer les pommes
  • désactiver/réactiver les OAM quand ils sortent de l'écran
  • passer *réellement* à deux plans pour l'affichage du décor
  • scrolling parallaxe
  • (post-posé: animation composite pour Bilou).
J'ai aussi commencé un nouveau graphisme pour Bilou: là, je le trouve vraiment trop petit par rapport au "reste du monde".

Got the testpoints support added. Before playing the 'walk' animation again, the woodworm will check it wouldn't enter a wall and wouldn't fall down. It might not work for every entity (clearly not for Bilou), but it does the job here. Adding a turn-back ... there we are. Fully autonomous entity patrolling on a platform with completely generic code. First state machine ever, and I can replicate them here and there by just adding one line in test.cmd file.

Friday, December 14, 2007

iWorld has non-virtual desctructor

Okay. Ca y est. Après avoir donné un destructeur virtuel à la classe iWorld (:P), et surtout une fonction reset() à la classe GameObject pour s'assurer que les nouveaux sprites ne vont pas essayer de "vivre" dans l'ancien monde (détruit) après reconstruction du nouveau monde, je peux recharger mon script de niveau autant de fois que je le souhaite dans runme.

Oh, il y a eu d'autres chipotages, bien sûr. Les sprites et quelques autres éléments sont enregistrés directement auprès du GuiEngine, pour les animations notamment, et il est assez malvenu de supprimer l'un deux sans l'avoir "désenregistré" sous peine de voir le moteur du jeu essayer d'animer les morts (sic).

Oui, je sais, c'est assez macabre. Mais que voulez-vous: la Faucheuse (traduisez: le Garbage Collector) n'est pas de mise en C++ et quand un objet meurt, il est pour ainsi dire obliger de s'enterrer lui-même.

faire et défaire ...

autre bonne nouvelle: les animations marchent! enfin, quand je dis "marchent", je devrais plutôt dire "rampent", puisque pour l'instant, seul le "petit ver jaune" de la forêt a été animé.
Je suis pas mal fier de mon coup, je dois dire. J'ai gardé un code tout à fait générique, qui est paramétrisé par un petit script de commandes. Petite astuce, les déplacements du ver sont intégrés dans la séquence d'animation elle-même, ce qui permet d'avoir un contrôle plus fin du déplacement (pour vraiment donner l'impression que le ver rampe, et pas qu'il glisse sur le sol pendant qu'il se tortille, comme on le voit si souvent dans les jeux amateurs).

Good news: animations are working: we can now see the yellow woodworm crawling through the level. I love how it keeps the code generic script commands. Another nice element: worm motion is integrated into the animation sequence, allowing for tighter control on how motion and frames fit together. It really feels like the worm is crawling, not sliding+giggling as I see too often in other works.

The down side is that I face too many red-death-screens while developing that. I guess this is my understanding of C++ virtual destructors that is still too far from sufficient. Since the whole environment in which "scripts" are evaluated must be cleaned up and rebuilt at every new attempt, I'm calling them a lot. And while I can enjoy some guru meditation, too much gets boring.

En revanche, si je commence à être assez rôdé sur les std::vector<GameObject*>::iterator, je suis encore un peu perplexe sur les destructeurs virtuels. L'environnement d'exécution du "petit script" en question doit être "renettoyé" chaque fois que l'on veut relancer le script, et pour l'instant, ça se traduit encore trop souvent par un écran rouge de la mort. J'aime bien la méditation, mais toutes les 5 minutes, ça devient lassant. (quicklink: l'assembleur ARM par TONC: http://www.coranac.com/tonc/text/asm.htm)

D'un autre côté, j'ai un peu relooké mon script qui traduit une image (comme celle ci-dessus) en un tas de tiles et les données pour la map, de sorte qu'on puisse lui indiquer quelle couleur doit être considérée comme "transparente", et il s'arrange tout seul pour que les tiles entièrement de cette couleur soient considérés par la toute nouvelle routine de "testpoints" comme étant "EMPTY", tout le reste étant de type "BLOCK"...

I'm still doing this with a picture-to-map script, with the 'level' being built with the Gimp, but now my tool producing tiles and map data out of the picture can be told what color is to be seen through and tiles completely made of that color will be considered empty by testpoints routine, while the rest of the map is said to be of type "BLOCK". Basis of sprites-to-world collision. A milestone is reached. (first Level Editor build - with no saving - will only come next April. NdlR)

edit-PS: la première version du level editor (sans sauvegarde) n'arrivera qu'en avril de l'année à venir. Là, on est donc toujours dans une "composition" de niveaux à coup de Gimp suivi d'une conversion avec détection des tiles redondants par un script fait-maison.

Tuesday, December 11, 2007

Et les sprites ?

Je suis confronté au même problème que Syra. Scroller, c'est bien, mais les sprites (Bilou et compagnie) ignorent royalement ce qui se passe sur la couche de fond, et qu'on se retrouve donc avec les monstres qui restent "scotchés" sur l'écran alors que le niveau du jeu défile par derrière.

Rien de bien méchant à arranger, mais ça demande quand-même un peu de (ré)organisation du code, ce qui me prend systématiquement une plombe. Enfin, dans l'immédiat, ça ne marche pas trop mal, excepté un petit "glitch" désagréable (le fond est déplacé trop tôt par rapport aux sprites, ce qui leur donne de s'enfoncer dans le sol quand on scrolle vers le haut, par exemple).

Ce midi, j'attaque les animations !

Tuesday, December 04, 2007

Yes! Ca scrolle!



C'a été un drôle de combat, reprennant les bonnes vieilles habitudes du cours Algo I (invariants, etc) pour parvenir à faire scroller le niveau de Sonic sur ma DS. Faire un scrolling vertical, c'est simple. Le scrolling horizontal m'a déjà donné plus de fil à retordre, mais pour s'assurer qu'ils n'essaient pas de s'assassiner dans les coins, j'aime autant vous dire que ça ne va pas sans mal.

J'ai laissé tomber les transfers DMA pour la plus grande partie du code. L'idée maîtresse ici était une "fenêtre de validité" qui indique quelle portion de la map est effectivement présente dans la mémoire vidéo, et à partir de quelle position. L'ennui, c'est que pendant tout un temps, le scrolling "vertical" modifiait des zones que le scrolling horizontal tenait pour acquises. Bref, on se retrouvait avec de gros blocs de terre au milieu du ciel, de l'eau dans le sol, des hybrides guèpes-singes, etc.

mais ça y est. Ca marche. Pour les curieux, le code est sur le CVS. Et au passage, j'en ai profité pour commencer un petit interpréteur de scripts pour ce genre de tests (histoire de pouvoir réutiliser un fichier .spr transféré préalablement). L'ennui, avec ce genre de méthode, c'est qu'il vous faudrait 5 minutes pour mettre en place le test à partir de runme.nds ... D'où la vidéo ;)

Pas de musique sur la vidéo, donc si vous voulez vous mettre dans l'ambiance, jetez une oreille à "Oil Ocean (WT-40 mix)" qui m'a accompagné lors de tous ces tests ^_^

Friday, November 30, 2007

dev-fr.org ... le paradis du homebrew

Bon, j'ai bien aimé "Bloops", adoré "Tetris Attack DS" et "Setsuzoku no Puzzle" ... Mia est passé sur PSP. J'ai bien ri avec Kaboom et versé une larme de nostalgie sur XRickDS et GianaSister DS ... Quoi d'autre. Quid quand les blogs restent quois ? Tournons nous vers les forums !

Après quelques semaines peu convaincantes sur playeradvance (trop noob) et gbadev (trop prise de tête), j'ai essayé dev-fr, et jusqu'ici, je suis séduit ^_^. C'est tout à fait le genre "gazette" que je cherchais. Si vous avez déjà acheté un magazine un peu "touche à tout" sur l'informatique (je pense par exemple au PC team, création graphique, musicale, jeux, OS alternatifs et programmation), vous aurez peut-être remarqué que j'ai tendance à animer ce blog un peu comme quelques rubriques dans ce style de journal.

Okay, i liked Bloops, loved Tetris Attack DS and Setsuzoku no Puzzle. I quite liked Mia's homebrew too, but he's now dev'ing on the PSP. Kaboom made me laugh and both XrickDS and GianaDS have wet my eyes with tears of nostalgia. Then what ? What when blogs are silent ? Let's check out the forums.

My experience on player advance (too n00b) and gbadev (people are just too complicated) didn't convince me until i found dev-fr.org. That's exactly the kind of homebrew gazette i was looking for (i once hoped Drunken Coders news would offer this, but it turn out they merely advertise new movies available on the moonbook project >_<).

Here's a small sample on what you can found there (okay, it's a french-speaking forum. Noone's perfect). An interesting event on that board is the Saturday's demo. A homebrew guru details with videos and code a common special effect or programming technique. It can be about particle systems or the use of horizontal blank interrupts to achieve wobbling and parallax scrolling. Very pleasant.

 Petit tour d'horizon, donc, de ce que j'ai vu d'intéressant. Je laisserai à mon frère le soin de faire les tests et les scores ^_^

FAT Mod Player, par cid2mizard. Comme le nom l'indique, ça sert à écouter .mod ... Tous les mods que vous auriez mis sur votre carte flash.

Autre évènement sympaLa démo du samedi soir: scrolling list. Un principe assez original: illustrer des techniques de programmation (généralement sur la DS) avec le code à la clé. Des articles généralement très bien ficelés, et dignes de ce que l'on trouvait dans les magazine (même si les démos, elles, ne sont pas nécessairement très impressionnantes comparées à ce que l'on voyait sur la Scène Amiga il y a 10 ans d'ici. Le mot d'ordre, c'est BabySteps ...

Plop invaders ... un petit jeu bien sympa qui rappelle le principe de Chuzzle (mais pas tout à fait) avec un scénario digne des invasions blorks de Kid Paddle.

C'est mignon, ça fait cogiter les neurones et c'est bien ficelé, même si les graphismes dans les phases de jeu sont parfois un peu légers à mon goût (et les plops sont probablement un chouya trop petits).

Then come the Plops. Kind of blobs from unexpected nuclear experiment that you have to erradicate by exhausting their air. A chuzzle-like (though the gameplay differ) with a Kid Paddle-like scenario. Cute, mind-twisting and well tied together, despite some effort could be done to improve in-game gfx.  

Par Mollusk , Pitt et Zeblackos. Une collection de mini-jeux un peu curieux, réalisés dans un langage dont personne ne voudrait, mais pour un résultat qui vous dévorera des heures de transport en commun.   

Another blog-worthy stuff is Mental Games by Mollusk & friends. The kind of minigames pack that many suggest on the DS, but with a retro-look that gave me the urge to try it (compared to Puzzle Maniak which still leaves me cold). Ideal if you want 5-minutes fun in the bus. Check out my blogmarks if you want to keep up to date of my other findings. 

Le tout, évidemment, uploadé sur ma DS Phat avec mon propre petit "runme", que j'ai boosté à 1Mbps, et ses scripts perl ... Parce que je le veux bien.

edit: je suis loin d'avoir fait le tour, bien sûr, et comme je ne suis pas mon frère, je ne vais pas essayer d'animer une rubrique "le jeu homebrew de la semaine". Mais si je repère un jeu qui a l'air de valoir le coup sur ces forums, je l'ajoute dans mes blogmarks.

Saturday, November 24, 2007

BG_WRAP_ON ?

I read somewhere that "Background Wrap only applies to rotation backgrounds (Rotation Backgrounds.) Setting the bit to 1 enables wrapping of the background while specifying a value of 0 disables wrapping of the background. Specified by BG_WRAP_ON or BG_WRAP_OFF". -- this suggest we need MODE_5 if we want two planes for the level data. I did the test this afternoon and it turned out that mode 0 is very well capable of wrap-scrolling. And actually it seems to be supported by all the BG layers, too.

class UnderProgress : public Animator {
unsigned offset;
public:
UnderProgress():Animator(1,"-cx-") {offset=0;}
virtual Animator::donecode play() {
if(!running) return Animator::DISMISS;
offset++;
BG2_X0=offset;
SUB_BG0_X0=-(offset>>1);
return Animator::QUEUE;
}
};


Difficile de trouver des informations précises sur le scrolling de la DS, en fait. Si bien que les infos trouvées sur GBAtek et autres wiki laissaient à penser que seul le mode 5 (avec des plans carrés capables de rotations et zooms) pouvait fonctionner avec le "scrolling infini". C'est effectivement le rôle de BG_WRAP_ON pour les plans dits "extended rotation", mais je vous assure pour l'avoir fait fonctionner pas plus tard qu'il y a 2 minutes que le mode 0 et ses plans "texte classique" supporte parfaitement le scrolling infini, et sur tous les background.

En fait, c'est le comportement par défaut de la console et notre bit "BG_WRAP_ON" n'est là que pour désactiver cette fonctionnalité (qui pourrait être gênante si on essayait de se servir des plans déformés pour faire de la 3D (cf. le "mode 7" de la SNES).

Je souffle un coup, donc: je pourrai sans soucis choisir la taille 512x256 qui m'est si chère pour l'instant (les mode 5 n'offrant que 128x128, 256x256, 512x512 et 1024x1024).

(PS: j'en profite pour signaler à ceux que l'anglais rebiffent que le premier des posts "tutoriel" sur le scrolling est (enfin) complètement traduit).

Thursday, November 22, 2007

Scrollons encore

On discutait scrolling avec Cyril hier midi, et il m'a fait remarqué assez justement que je m'inquiétais inutilement pour les scrolling à grande vitesse. Bin oui, tant qu'on ne scrolle que d'un pixel à la fois on peut s'en sortir très bien avec seulement 512 pixels de large dans la mémoire vidéo. Au cours du décalage, on finira bien alors à se retrouver avec un morceau de 256 pixels appartenant à un seul bloc de VRAM à l'écran et on a les mains libres pour changer le contenu du deuxième.

example of what concerns me
Mais si la vitesse devient trop élevée, on risque de se retrouver à passer d'un 'bloc' à l'autre mais en gardant toujours plus d'un bloc de VRAM à l'écran, ce qui nous empèche de mettre l'image à jour sans prendre le risque d'un affichage inconsistant. Mais c'est là que Cyril est intervenu: rien n'empèche d'arrêter le scrolling plus tôt que prévu juste pour ce 1/60eme de seconde... On a alors de nouveau les mains libres pour copier le bloc suivant en VRAM, et au coup suivant, on scrollera un peu plus. L'un dans l'autre, ça devrait être invisible (edit 26.11) J'ai testé sur le temps de midi: c'est indécelable.

types de blocs pressentis pour Bilou, et leur encodage sur 4 bitsReste un autre problème: l'encodage des "types" de blocs. Si je faisais une copie élément par élément à la main (jouable si on remet un bloc de 8x8 pavés à jour d'un coup), je pouvais chiper les bits "miroir" pour encoder les types dans la carte "offscreen", et les remettre à zéro avant la copie dans la surface "onscreen".
Mais pour remettre tout un bloc à jour (2K), il serait franchement préférable de passer par le DMA.
Mais bonne nouvelle, on peut s'en sortir avec un encodage un peu plus subtil. Imaginez: on a besoin d'encoder si chaque tile est solide, traversable, incliné, etc. mais aussi s'il s'agit d'un bonus, de pics, de lave, etc. Trop pour 4 bits ... sauf si on encode que 12 types de tiles et que l'on se sert des numéros 12 à 15 pour des blocs plus "spéciaux", par exemple ceux dont seul le personnage du joueur doit s'occuper.

Alors, quel est le truc ? Eh bien voilà. Notre niveau n'est pas construit à partir de tiles 8x8 mais à partir de blocs 16x16. On peut donc supposer que la lave prendra bien 16x16, et ce n'est pas juste 2 bits (de 12 à 15) que l'on a pour faire la différence entre les picots, la lave ou les bonus, mais bien 4x2 bits (2 dans chaque tile faisant partir du bloc 16x16). Soit 256 types de blocs spéciaux possibles. De quoi voir venir...

Monday, November 19, 2007

Ideas for smooth scrolling on the DS...

Bien sûr, la DS est capable de faire un scrolling fluide à travers un grand niveau, mais ce n'est pas nécessairement une mince affaire. Je cogitais sur les méthodes possibles l'autre jour et j'ai pris mes notes dans mon blog.

Je rafinerai et traduirai plus tard ...

maps & tiles sharing VRAMThe hardware (from Liranura's 2D tutorial)

Map bases always have 32×32 entries. To create bigger BGs (Like 64×64) you need to use several map bases. As for tile bases - If you want to make use of the full tileset (1024 tiles), you will have to use several tile bases - 4 Tile bases for 256col full tileset, and 2 Tile bases for full tileset of 16col mode. Since the Map bases and the Tile bases are located on the same region in VRAM, they can overlap. Since a map base is 2Kbytes and a Tile base is 16Kbytes, each Tile base contains 8 Map bases.
Une surface affichable sur la DS est constituée de 32x32 tiles (l'écran en fait 32x24) et occupe 2KB dans la mémoire vidéo. Pour construire des plans de décor plus larges (p.ex 64x64 tiles), il nous faudra plusieurs 'morceaux' de 32x32 mis côte à côte pour former une surface plus grande. On retrouve le même phénomène avec les tiles (pour utiliser l'entièreté d'un jeu de tiles (1024 tiles), il nous faut 4 sections de 16K en mode 256 couleurs). Notez que c'est au programmeur de choisir s'il va stocker 16K de tiles ou 8 maps dans une région donnée de la mémoire vidéo.

La console nous permet de positionner l'écran librement dans la surface définie (pour chaque plan séparément, hein, ) et -- contrairement aux carte VGA -- par défaut la surface 'boucle' sur elle-même (si la zone affichée déborde par la droite, c'est la gauche de la surface qui sera réutilisée).

We can have hybrid technique ...
At some point we have to alter parts of the map to keep scrolling smoothly. Nothing forces us, however, to have a unified technique that accomodates both horizontal and vertical moves. The fact that the screen isn't a square, that memory stores lines continuously and columns discontinuously and similar consideration -- not omitting the fact that our game may have a side-scrolling or vertical-scrolling action (shmups ;) -- may suggest that we have two distinct mechanisms for updating the map after a vertical and a horizontal movement of the "camera".

Le système de scrolling va forcément mélanger software et hardware. Le côté hardware, c'est le choix de la portion visible de la surface en VRAM (on l'appelle "onscreen surface" -- litéralement 'à l'écran' en anglais). Le côté software consistera à modifier des portions de cette surface (de préférence qui sont actuellement invisible pour le joueur) afin de donner l'illusion d'un décalage continu alors qu'en réalité, nous somme piégés dans un carré de 512x512 pixels.
Avant de ce lancer dans le code, il serait bon de se rappeler que rien ne nous oblige à avoir une technique unique pour les scrolling horizontaux et verticaux. Les uns pourrait parfaitement s'opérer à grands coups de DMA sur des tranches entières alors que les autres se feraient "bloc par bloc" gérés entièrement depuis le CPU.
  1. we can't have smooth scrolling in a 64x64 area if we reprogram 32x32 entries (dma copy) at once (<-- cyril contests this, see next post).
  2. we could do the "John Carmack" trick, using hardware scroll in the 64x64 area and then "jump" to a second 64x64 area when we're about to move out, but that would kind of be silly on hardware that allows to "wrap around" the area with our viewport (which the PC hardware couldn't do properly).
  3. doing "double-buffer" of the map will involve a burst of up to 8K memory transfer (through DMA), potentially leading to gameplay lags
  4. we have better things to do with the other maps (e.g. additional planes)
  5. DMA copy for the map might be interesting to save CPU (well, it is actually frozen during the move), but it requires that the offscreen map is a verbatim copy of what's used on screen. manual copy of the map parts instead allow us to use more bits for tiles meta-data and wipe them as the tiles are moved on screen. That would give us 64 types of block, more than we need to encode "slipperiness", identify bonus, etc.
thinking again ...
Nothing forces us to use 64x64 ... since the height of the screen is smaller than 32 tiles, we can very well work with e.g. 64x32 instead. This is not only nice because it halves the amount of work without loss of functionnality (maybe a bit less effective "caching" of vertical scrolling), but also because it means we now can do the "carmack jump" thing effectively: Suppose we are working with maps 0 and 1 initially (side-by-side 32x32 areas of the level map) and that the viewport is getting close to the edge of the currently displayed area ... rush! we dump another 32x32 chunk of the level map (and now we can just ask for a DmaCopy of the whole data if it is properly stored offscreen) into map #2. When it then appears that we are about to scroll out of the current 32x32 area, we then cheat the video hardware, reprogramming the map base to be map#1 (instead of map #0) and the X scrolling register to show us in the new area (most likely x=x-256 or x=x+256 depending on the movement).

Autre petite constatation: rien ne nous oblige à utiliser du 512x512 pixels! en fait, ce serait même l'inverse (en cas de scrolling horizontal, ce mode nous oblige à faire plus de mises à jour et ne nous offre pas grand-chose en contrepartie). Au passage, ça nous permettrait de faire un "scrolling à la John Carmack" plus efficacement (enfin, au moins une fois de temps en temps...).

Mais entretemps, je suis nettement plus sceptique sur l'interêt de la technique Carmack (rendue célèbre par la série des Commander Keen) sur le hardware de la DS.

I'm not sure we could keep it smooth forever with that technique, unfortunately: there would be no way for us to tell the hardware that map #N-1 and map #0 should be shown as a continuous 64x32 area...

see also captain Apathy's tutorial
voir aussi le tutoriel de Edorul (GBA)
Sonic the Hedgehog 2 (Emerald Hill) from soniccenter.org

Friday, November 16, 2007

Un autre arbre pour Bilou

Je me suis fait une petite scéance de "speed-pixels" ce midi. On ouvre the Gimp, on récupère les couleurs de la forêt de Donkey Kong: King of Swing et c'est parti.

L'idée, c'est de faire vite et de mettre les éléments en place: ils seront retravaillés plus tard dans mon sprite editor, mais ce dernier n'est pas encore très pratique quand on veut rapidement entasser quelques gros ronds pour faire une forme de feuillage (à noter pour plus tard, en blanc sur bleu, ça aurait pu faire de beaux nuages) ou les formes étirées du tronc d'arbre.

J'en dirai plus plus tard, mais je crois que c'est un bon début...

Thursday, November 15, 2007

2D sur la DS : quelques chiffres ...

Plus de 640K de mémoire vidéo sur la DS -- c'est presqu'autant que la mémoire vive dont on disposait sous DOS sans les extensions. Mais comme je vous le montrait dans un de mes posts précédents, il faut répartir cette mémoire entre les deux écrans, les fonds, les cartes, les sprites et éventuellement, les palettes et les textures. Bref, pas mal de monde.

Pour un jeu de plateforme comme Bilou et Badman, le plus raisonable serait de partir sur 256K pour les décors, 128 à 256K pour les sprites (tout ça sur l'écran principal) et de garder les 128K restant pour gérer l'écran secondaire (map, inventaire ... peu importe). 256K de décors ... avec mes blocs qui font 16x16 pixel, ça veut dire que j'ai droit à un bon millier de blocs différents conservés simultanément en mémoire. Soit près de 5 écran de DS. C'est déjà honnête ...

Bien sûr, rien n'empèche de changer le contenu de la VRAM au fil du jeu. C'est notamment ce que j'ai l'intention de faire pour les blocs animés (pensez à la pièce d'or de SuperMario ou au bloc-question). On leur attribue quelques tiles sur lesquels on ira recopier systématiquement l'étape d'animation suivante au bon moment (depuis nos 4Mo de mémoire de travail, donc). Ainsi on gagne du temps et de la place. On pourrait aussi essayer d'éliminer certains blocs non-affichés pour les remplacer par d'autre en fonction de la progression du joueur dans le niveau, par exemple si l'on voulait faire un traveling continu sur les écrans d'Another World... mais il y a peu de chances que je me serve de quelque-chose de ce genre.

Dans un niveau ou le scrolling est libre dans toutes les directions, on choisira de préférence une map 512x512, de manière à pouvoir toujours modifier les "bords" de la map pour avancer dans le niveau sans que le joueur ne remarque quoi que ce soit. Il y a aussi des map 512x256 et 256x256 que l'on utilisera dans des jeux ou le scrolling suit un seul axe (les shoot'm'up, par exemple, ou des niveaux spéciaux dans un jeu de plate-forme).


Evidemment, on pourrait se dire que c'est du gâchis de prendre une carte de 512x512 alors que 256+16 aurait suffi à un scrolling fluide (réfléchissez un peu: pourquoi le GBA a-t-il un écran de 240 pixels de large, selon vous?). Mais ce serait compter sans le fait que la "carte" des tiles peut aussi nous servir directement pour savoir si notre personnage (et tous ses adversaires) ont affaire à un mur ou à un trou. Chaque "tile" est encodé sur 16 bit dans la carte (cf cet autre post précédent) et on peut choisir parmis 1024 "tiles" différents, les autres bits permettant de "retourner" les blocs horizontalement et verticalement.


single tile encoding, from LiraNuna's tutorial


Restent 4 bits inutilisés qui pourraient se révéler bien pratiques pour encoder directement le type de bloc: creux, plein, "montée" à 45°, "descente" à 45°, "montée" à 22.5% ...

Dans Rayman Designer, il y a 24 types de blocs différents, y compris le bloc semi-solide (on peut passer à travers en sautant, mais pas en tombant), les blocs glissants (de nouveau 7 inclinaisons différentes), des blocs qui blessent, qui tuent, qui noient, qui font rebondir, escaladable, etc.

<obsolete why= "si les bits "palette" sont actuellement effectivement utilisés, c'est en les combinant par blocs de 4 tiles que l'on étendra le nombre de propriétés disponibles.">

Bien sûr, avec 4 bits de libre, c'est un peu juste pour proposer les 24 types de Rayman, et pourtant, dans Bilou, il nous faudra bien tout ça. Mais dans notre cas, il y a peu de chance que l'on se serve du "retournement" de tiles. Le plus souvent, ça fouterait en l'air tous nos efforts d'éclairage sur les blocs. Résultat, on pourrait s'arranger, par exemple, pour stocker certains blocs "à l'envers" et pour pouvoir se servir du bit "miroir horizontal" pour faire la différence entre les montées et les descentes ... L'alternative, ce serait d'avoir une des combinaisons pour indiquer que le bloc est "spécial", et de se servir à ce moment de son numéro pour choisir le comportement approprié, sachant que ce sera un peu plus compliqué à traiter... L'idéal, ce serait de garder ça pour les interactions que seul le personnage fera (grimper, se blesser, etc.) et d'avoir les effets sensibles égalements pour les monstres directement encodés sur la map...

</obsolete>

Enfin. 'faudra tester tout ça. J'espère que ça ne vous a pas paru trop imbuvable: j'avais besoin de mettre les idées au clair avant de me lancer dans le code de gestion des niveaux ...

Wednesday, November 14, 2007

LBM & Linux

Je suis un vieux de la vieille qui a commencé ses pixels sous MS-DOS. Et de temps en temps, j'aime pouvoir récupérer mes vieux dessins tout pixelisés. Mais voilà, bien peu de programmes supportent les fichiers .LBM de mon ancien Deluxe Paint II enhanced :(

Sous ubuntu, pourtant, le package netpbm fournit un outil ilbmtopbm qui servira à ImageMagick (les programmes 'display' et 'convert', entre-autres) pour passer du format LBM au format PBM (Portable Bit Map) -- inconnu de tous, sauf de la bibliothèque ImageMagick qui peut pratiquement tout faire à partir de là.

Reste que imagemagick persiste dans l'idée que mes fichiers Deluxe Paint devraient s'appeler ".ilbm" et pas ".lbm". Comme c'est pénible et que je suis geek, j'édite le fichier /usr/lib/ImageMagick-6.2.4/config/delegates.xml et là ou on voyait une ligne "decode 'ilbm', je passe à

  <delegate decode="lbm" command='"ilbmtoppm" "%i" &gt; "%o"' />
<delegate decode="ilbm" command='"ilbmtoppm" "%i" &gt; "%o"' />


Bref, voilà comment mon frère a maintenant mes petits sprites de Kid Paddle pour les envoyer sur le forum de Midam ^_^

(packages à installer: libimlib2, imagemagick et netpbm/libnetpbm10)

Monday, November 12, 2007

Java pas m'énerver ...

Quand il s'agit de manipuler un document XML, moi, mon interface préférée, c'est XPath. Pas besoin de code bien compliqué: on fait comme si tous les éléments étaient des petits fichiers dans une arborescence, et on donne un chemin pour trouver les éléments qui nous intéressent. J'avais déjà pu m'en servir avec succès en PERL, je m'attendais à quelque-chose d'ultra-simple en Java, langage de l'XML par excellence.

J'y vais donc de mon petit test débile:

import java.lang.*;
import java.util.*;
import javax.xml.xpath.*;
import org.xml.sax.InputSource;

public class XpathTest {
public static void main(String[] args) {
try {
System.err.println("creating xpath...");
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = args[0];
InputSource src =
new InputSource(new java.io.FileInputStream(new java.io.File(args[1])));
System.err.println("search for "+args[0]);
String content = xpath.evaluate(expression, src);
System.out.println("here: "+content);

xpath.reset();
src = new InputSource(new java.io.FileInputStream(new java.io.File(args[1])));
Object node = xpath.evaluate(expression, src, XPathConstants.NODESET);
System.out.println("here: ("+node+")");
} catch (javax.xml.xpath.XPathExpressionException ex) {
System.err.println("oops: "+ex);
} catch (java.io.FileNotFoundException ex) {
System.err.println("no file : "+ex);
} catch (java.io.IOException ex) {
System.err.println("doh: "+ex);
}
}
}

Tout ça à l'aide de la première référence que je trouve: la doc de sun bien claire, sauf sur un point "c'est quoi cette 'nodelist' que je suis supposé recevoir mais qui m'est transmise sous la simple forme d'un 'Object' ?". Au bout de quelques minutes de tests, je me rends compte que la seule chose qui marche, c'est le chemin "/" qui reprend tout le texte du document. le reste ("/feed/entry[1]/title" ou "//author", ce genre de choses chouettes et utiles), ne donne aucun résultat. Pas une exception ou un message d'erreur. non. rien, tout simplement. que le chemin corresponde à un noeud existant dans le document ou pas, d'ailleurs.

grmbl.

Puis à force d'essayer, je finis par constater que le fameux objet que je récupère est de la classe com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList.

Et là, je dis: ça pue. pourquoi m'ont-ils renvoyé un objet interne non-documenté et (de plus) qu'est-ce que c'est que ce "sun...apache..." ou bien c'est dans le standard, ou bien ça n'y est pas, non ?


allons bon ...
Xerces does not provide an XPath implementation (it implements only support for the limited expressions allowed by XML Schema constraints). Xalan provides an XPath 1.0 implementation and from the com.sun.org.apache... package name it seems there is the Sun (derived from Xalan) implementation that is included with the JVM.ref

Tout de suite, ça m'étonne moins. Reprenons calmement avec la doc d'apache, donc.
  1. on installe le package "xalan", un traducteur XSLT qui est sensé fournir XPath pour de vrai
  2. on redéfini sa variable d'environnement CLASSPATH pour pointer sur /usr/share/java/xalan2.jar
  3. on google sur "org.apache.xpath example" et pas "xpath java example"
Voyons voir. Ouais. des tonnes de Factory et docBuilder.parse() ... 'fallait s'y attendre. Et naturellement, rien n'aide dans le code java ou dans JavaDoc à retrouver comment il serait bien possible de construire un objet de telle ou telle classe à partir d'un nom de fichier, ce qui rend toujours les tutoriels Java pénibles (très 'magie noire', si vous voyons c'que j'voulions dire).

Bref, le code le plus simple auquel j'arrive ressemble à ceci:
import org.apache.xpath.*;   // for XPathAPI, obviously!
import org.apache.xpath.objects.*; // for items, nodelists, etc. (XObject)
import org.w3c.dom.*; // for Document and friends
import java.lang.*; // for String and the like.

/** see also:
http://xml.apache.org/xalan-j/apidocs/javax/xml/parsers/DocumentBuilder.html
*/
class xpath2 {
public static void main(String args[]) {
Document doc=FileToDoc(args[0]);
String xpath = args[1];
System.out.println("\nQuerying DOM using xpath string:" + xpath);
try {
XObject o = XPathAPI.eval(doc, xpath);
System.out.println(o.getTypeString()+"> "+o);
} catch (Exception e) {
System.err.println("doh:" +e);
}
}
}
mais pour ça, il me faut écrire une horrible fonction capable de passer d'un nom de fichier à un Document, parce que visiblement, les gens qui ont écrit XPathAPI n'ont pas pensé à rendre ce cas-là simple :(
    static Document FileToDoc(String fname) {
/* well, Document is an interface and cannot be built simply */
/* -- grmbl -- */
try {
javax.xml.parsers.DocumentBuilderFactory docBuilderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder docBuilder =
docBuilderFactory.newDocumentBuilder();

// Parse the XML file and build the Document object in RAM
return docBuilder.parse(new java.io.File(fname));
} catch (Exception e) {
System.err.println("parse error: "+e);
return null;
}
}
Notez que si vous avez déjà un InputStream prêt sur le contenu (p.ex. une connexion réseau), inutile de passer par un fichier: docBuilder.parse(InputStream) existe également. Il y a même docBuilder.parse(URL) pour ceux qui ne sont pas occupés à faire un exercice sur l'écriture d'un client HTTP :P
(soupir)

Et pour être sûr, ils ont *aussi* rendu la réécriture de documents XML vers un fichier tordue:
 import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);


Pour la postérité, la javadoc de l'API XPath sur le projet Apache.

Jouons avec netcat ...

Les blogs sont nos amis, mais pour la plupart d'entre nous (même les programmeurs), la simple question "y a-t-il du neuf sur mon blog préféré" paraît trop complexe pour qu'on se donne la peine de la programmer. Pourtant, j'aimerais bien lancer mes étudiants sur un TP basé sur les flux RSS. Alors ?

Alors, bin souvenez-vous du post sur netcat, cet outil unix capable d'ouvrir et de manipuler des sockets en ligne de commande (je simplifie, mais bion). Avec quelques connaissances de HTTP 1.1 on va pouvoir s'amuser un peu. Tout d'abord, il nous faut l'URI d'un flux RSS, en l'occurence, le mien: http://sylvainhb.blogspot.com/feeds/posts/default

Nous avons déjà l'outil wget qui nous permet de récupérer une ressource sans passer par un navigateur, mais netcat va nous permettre de bidouiller un peu notre requête HTTP et de récupérer "en live" la réponse du serveur.

Voyons donc. La manière la plus simple pour récupérer la page avec notre flux RSS en HTTP correspond à

GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1
Host: sylvainhb.blogspot.com


Auquel le serveur répondra quelque-chose comme
HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8
Last-Modified: Mon, 12 Nov 2007 11:00:00 GMT
Cache-Control: max-age=0 private
ETag: "8ec946e4-7f26-4280-8dad-30c1e7f20e51"
Transfer-Encoding: chunked
Date: Mon, 12 Nov 2007 11:15:53 GMT
Server: GFE/1.3
Connection: Close

c04
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
<id>tag:blogger.com,1999:blog-34057821</id>
<updated>2007-11-12T12:07:24.724+01:00</updated>
<title type='text'>Bilou HomeBrew's Blog</title>
...


La réponse est divisée en deux parties: des en-têtes, qui nous indiquent ce que l'on va recevoir, de quand celà date et comment gérer la suite du transfer et le contenu qui nous intéresse (le flux RSS proprement dit). Ceux qui ont fait un peu de programmation WEB auront tout de suite reconnu le "look HTML" de notre contenu. Il s'agit en fait d'un document XML, qui adopte les conventions d'HTML pour présenter n'importe quel type d'information (ici, un "flux" () qui possède ses paramètres propres (titre, dernière mise à jour ...) et une série d'entrées (), qui correspondent aux articles du blog.

Grâce à la balise , il serait possible de suivre l'évolution du blog en redemandant régulièrement le flux par HTTP et en comparant avec la dernière version reçue. Mais bon, là, mon flux pèse dans les 128K et ce serait ridicule de tout retransférer à chaque fois. Il y a évidemment moyen de faire mieux -- et à mon avis, c'est un des principaux avantages de HTTP/1.1 par rapport à sa version 1.0.

Vous avez remarqué la ligne "Last-Modified" dans les en-tête de la réponse ? Il s'agit de la dernière date de mise à jour (enfin, ce qu'en pense le serveur). Et nous pouvons demander au serveur de ne nous retransmettre le document que s'il a changé depuis cette date avec une petite variante de notre requête:

GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1
Host: sylvainhb.blogspot.com
If-Modified-Since: Mon, 12 Nov 2007 11:00:00 GMT


Le serveur ne répondra maintenant par un "200 OK" que si la page a changé. Dans le cas contraire, on aura droit à un petit "304", sans contenu. Nettement plus léger, non ^_^ et plus simple que d'extraire à nouveau la balise <updated> pour comparer avec la précédente. Et tout ça avec une seule ligne de commande (à mon avis, bien plus sympa pour les tests que de lancer un "telnet" et d'essayer de taper toute sa requète avant que le serveur WEB n'estime que vous êtes trop lent):

echo "GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1\nHost: sylvainhb.blogspot.com\nIf-Modified-Since: Mon, 12 Nov 2007 09:51:53 GMT\nConnection: close\n\n" | nc sylvainhb.blogspot.com 80


Petit raffinement: sous Unix, on dispose aussi d'un outil "watch" qui appelle la même commande, encore et encore. On pourra donc se faire un "surveilleur de blog ultra-geek" avec
watch 'echo "GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1\nHost: sylvainhb.blogspot.com\nIf-Modified-Since: Mon, 12 Nov 2007 09:51:53 GMT\nConnection: close\n\n" | nc sylvainhb.blogspot.com 80'


Bon, okay, la date de référence pour laquelle on teste les mises à jour est toujours la même ici, ce qui rend l'exercice assez inutile. C'est que le début, d'accord, d'accord ?

(edit: amusant: non seulement cette méthode m'indique quand il y a un nouveau post, mais aussi si un post a été remanié ou s'il y a un commentaire en attente de modération ;)

Thursday, November 08, 2007

Encore Titus

De temps en temps, je passe faire un tour sur vgmaps.com, un chouette site qui répertorie les niveaux de jeux vidéos comme un "atlas". C'est du boulot, évidemment. Ayant récupéré "the Blues Brothers" sur abandonia, je me suis amusé à photographier le jeu au fur et à mesure.

the Blues Brothers, c'est le jeu où Titus Interactive prépare les ingrédients de ses futurs jeux. Des munitions (caisses à lancer sur les ennemis), pas encore tant de passages secrets, mais une série de "salles secrètes", comme les cavernes de Prehistorik (premier du nom) qu'il faudra explorer pour rassembler les objets nécessaires au concert de Jack et Elwood, mais qui peuvent aussi bien contenir des "bêtes" bonus ou un loubard.

Many games feature a way to carry items between different places, but Titus Interactive, in their nineties, brought that as the number-one mechanic of the game. The amno, for instance, are things you carry along, like crates. You can only carry one at a time, and if you get hit, you lose what you're carrying. The result is a platformer where careful progress is required, but where you also face a puzzle dimension, in the sense that you will need to pick your route to save amnos.

The whole is spiced up with some exploration, as you will need to find a special item in each level to get the "good ending" of the game. By then, I found that mix much more interesting than the usual straightforward, infinite amno, gun-oriented platformer.


Autre détail qui a son importance, si vous êtes touchés alors que vous transportez une caisse, vous la perdez, ce qui veut dire que plus loin dans le jeu, vous serez désarmé face à un autre danger. Bref, le moindre faux-pas est lourd en conséquence. Autre exemple, les designers se sont amusés à s'assurer qu'à deux ou trois endroits, vous risquiez de retomber plus en arrière dans le jeu (de préférence là où vous n'aviez pas la possibilité d'éliminer tous les ennemis).

  • niveau 1 : le magasin (guitare dans une des échoppes). On affronte des loubards, des mémés en caddie, des policiers, des serveuses furieuses et des jardiniers toqués. Une fois dans les nuage, c'est le piaf pond-vite qui nous mêne la vie dure
  • niveau 2: en construction (lunettes et chapeau que je ne parviens pas à atteindre. Peut-être faut-il un parapluie ...) Sale gosses armés de pulvérisateur d'acide et gros bras maniaques de la clé à molettes, mais gare aux mares d'acides et aux broyeurs.

Autre petit élément sympathique, des objets tels que les parapluies ou les balons du premier niveau, offrent un gameplay plus varié.

Blues Brothers II -- jukebox adventure: un flopBref, du bon jeu de plateau comme on aimerait en voir à nouveau. Dommage que l'opus "II" (juke box adventure) n'ait pas été une réussite... Bien sûr, les graphismes sont nettement plus beaux, mais ils ont complètement perdu le fil de l'histoire. Tout d'abord, le principe même du jeu n'a plus rien avoir. On le catégorise sur abandonia de "no-brain fun", et en effet, plus la moindre recherche. La progression dans le niveau est devenue ultra-linéaire. Finies les caisses, ici on lance des disques, et il faudra souvent en balancer plusieurs pour venir à bout d'un monstre apparemment inoffensif.

Là aussi, le bât blesse: alors que Blues 1 nous avait fait affronter des personnages parfois déjantés, mais toujours réalistes, on se retrouve ici face à des pièges à loup vivants et géants, et .. euh une sorte de tondeuse à gazon croisée avec une pelleteuse mécanique qui à visiblement des instincts de pit-bull.

Bref, les deux premiers niveaux sont beaux, mais franchement insipide une fois leur côté démo/tutoriel passé, et dès le niveau 2, les monstres sont tout simplement pénibles (mouvements trop rapides, impossibilité de les dégommer quand ils sont "au repos", bref, pas impassables, mais pénibles)

Et pour le coup de grâce, je vous laisse contempler, hébétés, nos fameux blueseurs transformés en sur-hommes après avoir mangé une part de gâteau, ce qui semblerait leur permettre de faire des sauts plus longs, et peut-être renforcerait la puissance de leur lancer de disque.

Ridicule et pas convaincant pour un sous. Bref, autant Titus Interactive nous a fait de bons jeux dans ses jeunes années, autant il semblerait qu'ils aient été contaminés par la transformation du monde du jeu vidéo en un "marché" et progressivement perdu toute notion du gameplay et de la conception des bons niveaux. Je n'oserais même pas dire qu'ils ont transformé BB en un clône de Megaman: la seule ressemblance viendrait du fait que l'on tire sur des ennemis dans un sidescroller.

Bref, concentrez-vous sur le premier volet à moins d'être un graphiste en manque d'inspiration.

Monday, November 05, 2007

Pas bien (2)

je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.

Wednesday, October 24, 2007

SEDS 32x32 needs you

Les béta-testeurs sur les forums sont assez unanimes sur un point: 16x16, pour l'édition, c'est un peu juste.

Je m'attaque donc au support de blocs plus grand (32x32 pour commencer, mais de manière à pouvoir supporter les résolutions classiques des sprites GBA/DS, à savoir 32x16/16x32 ou 16x8/8x16 également).
Ca fait pas mal de chose à réviser dans le code (d'autant que je ne peux pas garder le même type d'affichage de grille à un autre niveau de zoom: on ne verrait plus rien), mais j'ai déjà pu faire quelques essais de tracé dans la grille 32x32 ce midi.

L'ennui, c'est que le touchscreen de la DS ne permet pas un tracé suffisament précis à cette résolution. En clair, ça ira pour donner les "grandes lignes" d'un dessin, mais pas pour une édition au pixel près :(

SEDS has been now officially advertised on some NDS forums, and i got plenty of feedback from beta-testers. Among other things, for many guys, 16x16 canvas is just too small, so i'm now trying to have 32x32 edition to work. That makes many things in the code to be adjusted, including reviving the alternate grid display -- and those are getting in place.
The one thing that is more annoying is that 'pixels' are then only 4x4 wide if i want the full 32x32 sprite displayed -- and imho, 4x4 areas are too small to be accurately enough plotted directly with the stylus. It sounds thus that i'll keep this experiment for "rough sketches", but that we will still have to work with a higher zoom level of a sprite sub-region.

A re-réfléchir, donc...

Dans le même ordre d'idées, la palette n'est pas toujours évidente à utiliser. Dans ma manière d'utiliser l'éditeur, ce n'est pas bien grave parce que je travaille essentiellement avec les flèches (couleur suivante/couleur précédente) ou la pipette, mais je dois reconnaître que cobain a mis le doigt sur un point noir. Et déplacer la palette plus loin du bord n'a pas arrangé grand-chose: cliquer dans une case 4x4 sans en sortir, ce n'est pas une mince affaire sur le touchscreen de la DS.
Le mieux, ce serait sans doute de "doubler" la palette d'une zone agrandie des 16 couleurs autour de la dernière couleur choisie ...

Similarly, the palette isn't that easy to use accurately for people who haven't fine-calibrated their stylus input. I don't care too much myself since i'm not that much using the palette directly -- i make wide use of "next/previous color" with the Dpad and the "color picking" on the grid... The best alternative i can think of would be to offer both the full palette with 4x4 per color, and a "quick pick" area where you have access to the 16 colors around the one you just clicked, but with e.g. 8x8 region per color.

pre-release 0.1 beta-test for download here

Monday, October 22, 2007

tiles extraction ...

Un autre petit outil en Perl (basé sur la bibliothèque de manipulation d'images Imlib) qui décortique une image et identifie les tiles uniques (8x8) et le nombre de couleurs utilisées...
Il ne fallait pas grand chose pour en faire un convertisseur .gif->.spr un peu plus automatisé. Je m'y suis attelé ^_^. L'outil en question s'appelle "imlib2spr.pl" et est disponible dans le CVS du projet 'runme'.

I've been working on a new small (PERL) tool for SEDS/runme. "imlib2spr.pl" is using the "imlib" package to open your .gif, .png ... pictures and identify uniques tiles and colors so that it can then convert them into .spr files.
It also builds a map of how to reuse those tiles to get the initial image back.

Mais pourquoi chercher à transformer une image .gif en un tas de tuiles, me demanderez-vous. Okay, certaines images contiennent des zones un peu répétitives et pourront donc prendre moins de place en VRAM... et c'est tout ?

Ooh non! Notre DS est effectivement capable d'afficher directement des images 'bitmap' (c'est ce que je fais quand vous envoyez à runme un fichier .pcx), mais avec une taille maximale de 256x256 ou de 512x512, selon la configuration d'écran choisie. Impeccable tant que vous voulez une image fixe, mais imaginons que je veux faire scroller horizontalement une image de 320 pixels de large, je fais quoi ?

Je passe à 512x512 ? le bitmap fera alors 256K, presque la totalité de la mémoire vidéo!
Je tronque à 256x256 et je redessine une colonne chaque fois que je me décale d'un pixel ? Bonjour le code!

Maybe you wonder why i'm trying so hard to split a picture into small tiles while i've shown with runme that it was fully possible to display a .pcx (and thus .gif and .bmp aswell) image straight on the screen. Well, the reason is scrolling. You very well can show a 256x256 image on the DS screen (which is 256x192) and side-scroll it again and again (using the 'scrolling wrap' hardware option). That will take you 64K worth of VRAM. Now if you want instead to side-scroll a 320x200 image, you'll get into trouble unless you're agree to devote 512K of VRAM just for your background image.

On the other side, once you have 'tiled' your background, you can easily repeat it as many times as you want: it's merely a matter of a few KB, and you can easily rewrite offscreen parts of the map as the scrolling goes so that you keep showing the right stuff at the right time, with a 64:1 reduction of the stress on VRAM.
Since we are running on gaming hardware, i think we should make the best possible use of it, shouldn't we?

Well, demo and code for that will follow once the 7.11.7 day is over.

Sous GBA, pas tout ces soucis: l'écran faisait 240 pixels de large et le mode bitmap 256x256 aussi, donc on avait tout loisir de redessiner des blocs dans la partie complètement masquée de l'écran, puis de scroller un peu, puis de redessiner, etc.

Eh bien, si l'on prend la peine de convertir notre bitmap en "tiles", on peut continuer ce petit jeu: une fois les tiles en mémoire, une "carte" peut très bien contenir deux fois l'image initiale sans nécessiter d'avantage de mémoire vidéo (allez, quand-même 1 ou 2K de plus, mais c'est quand même mieux que de passer de 64 à 256K, non?)

Bref, c'est Cyril qui sera content. Lui qui me proposait y'a pas 48 heures d'ajouter un mode "construisons notre map" dans SEDS ... On en est plus très loin ;)



à la base, c'était ça:

#!/usr/bin/perl
use Image::Imlib2;

$image = Image::Imlib2->load($ARGV[0]);
print STDERR "$ARGV[0]: ".$image->width."x".$image->height."\n";
while ($ty<$image->height) {
$tx=0;
while ($tx<$image->width) {
foreach $y (0..7) {
foreach $x(0..7) {
($r,$g,$b,$a) = $image->query_pixel($tx+$x,$ty+$y);
$r=pack("C1",$r);
$g=pack("C1",$g);
$b=pack("C1",$b);
$colors{"$r$g$b"}=$ncolors++ if !exists $colors{"$r$g$b"};
$tile.=$colors{"$r$g$b"};
}
}
$tiles{$tile}.="($tx,$ty)";
$tx+=8;
$tile="";
$ntiles++;
}
$ty+=8;
print STDERR ".";
}

print scalar(keys(%tiles)) . "unique tiles (/$ntiles) detected\n";
print scalar(keys(%colors)) . "unique colors detected\n";

exit 0;

note: il nous faudra installer le package libimage-imlib2-perl pour faire fonctionner le tout.


rem: pendant ce temps-là, Globoeil nous faisait une release de son "virtual game maker DS" ...
à découvrir sur globoeil.fr/vgdms ...

Tuesday, October 16, 2007

SEDS Multipage

ah, y'a pas à dire: c'est agréable d'avoir un environnement de développement capable de mises à jour rapides ... En quelques coups de cuiller à pot, j'ai pu, hier soir, goupiller la première version de SEDS capable de gérer des fichiers .spr multipage. Enfin la possibilité de dépasser 48 sprites en un fichier (ça devenait vraiment problématique) et de réorganiser mes petits dessins par thèmes (un seul fichier pour toute la forêt, avec une page contenant les blocs de terre, une pour les arbres, une troisième pour les pommes, etc.)

Wow, needless to say, it's really a good thing to have software update to speed up application development. Just a couple of edit-compile-update loops were enough to brew the first version of SEDS that can manage multi-page .spr files (which had been tested in runme a couple of weeks ago). That means i can at last break the "48 sprites per file" limit and reorganize my own tiles theme-wise, e.g. grouping all the forest-related tiles with one page for dirt blocks, one for the tree trunk & roots, anoter one for in-progress tree tops, one for the apples, and so on.

C'est aussi un premier pas vers la possibilité de mélanger des blocs 16x16, 8x8 (pour les pieds et les mains de bilou, entre autre) et 32x32 (l'encrier).

Bon, ceci dit, pour l'instant, les réorganisations sont pénibles au possible, mais c'est juste parce qu'il me manque une interface pratique pour ce genre de tâche :P

Et il a fallu faire tout celà sans que les aventuriers qui avaient téléchargé la release d'hier ne se retrouve temporairement avec un programme inutilisable suite à un update malencontreux... ce qui n'a pas été sans mal :P

This is also the first step towards the ability of mixing 16x16, 8x8, 32x32 (and other sizes coming) resolutions in a single editor/spriteset, which will be crucial to go on working with Bilou's world. Well, right atm. "reorganization" is as tedious as moving files using MS word, but that's still better than no reorganization at all :P


Allez, ça mérite bien une "0.2"

Sunday, October 14, 2007

SEDS revived.

un bouton "quit" pour revenir de SEDS à runme, la fonction "auto-update" sur SEDS (donc, si je corrige, je recompile, je pousse 'start/select' et je redémarre le programme remis à jour), un bouton "edit" dans runme qui me permet de basculer vers l'éditeur avec la planche de sprites qui vient d'être téléchargée ...

Hit on "edit" in runme, and you are forwarded to SEDS that will start editing the tiles you have previously downloaded. Hit START-SELECT, and you upgrade your copy of SEDS via the WiFi. Click on "quit" and you'll return from SEDS to runme, ready for beaming out...
In other words, all the pieces of the jigsaw are starting to fit together. I shooted a video to show off on youtube the whole process, but i couldn't wait for the 111 MB to get uploaded :P so you instead get that picture of "spector" i sketched during the first tests of WiFi-enabled SEDS (which wasn't able to save anything by that time). If you need help, feel free to describe what you're trying to do and where you're stuck in a comment, so that i can start a sort of FAQ for the soft.

bref, tout ce petit monde s'organise et commence à interagir. J'ai même pris une vidéo pour essayer de vous montrer tout ça... ouais. on ne sait rien lire des boutons sur lesquels je clique, et on voit surtout ma grosse tête en miroir, le pull de ma fée et ma cuisine méticuleusement rangée. Le tout prenant 111Mo ... j'ai interrompu l'upload pour vous resservir un 'spector' gribouillé du temps où rien de tout celà ne voulait marcher.

edit: petite release reprenant tous (j'espère) les fichiers utiles: seds-n-run.zip.

Vos commentaires sont les bienvenus pour construire une petite FAQ.

/dev/tcp ou netcat ?

En réaction au blog de bodman, qui nous présentait une manière élégante (tirée d'un autre blog: unixjunkie) capable de lancer des requêtes HTTP armé du seul shell "BASH":

exec 3<> /dev/tcp/www.google.com/80
printf "GET / HTTP/1.0\n\n" >&5
cat <&5
exec 5>&-


qui se soldait sur mon ubuntu invariablement par un "bash: /dev/tcp/www.google.com/80: No such file or directory". Intrigué, j'ai un peu cherché sur les forums, puis j'ai téléchargé les sources, et dans le README, je trouve ceci:

9. Why is bash configured with --disable-net-redirections?

It can produce completely unexpected results. This kind of
feature should not be part of a shell but a special. tool. And
that tool has existed for years already, it's called netcat.



aha. man netcat, alors ...


netcat is a simple unix utility which reads and writes data across net-
work connections, using TCP or UDP protocol. It is designed to be a
reliable "back-end" tool that can be used directly or easily driven by
other programs and scripts.
In the simplest usage, "nc host port" creates a TCP connection to the
given port on the given target host. Your standard input is then sent
to the host, and anything that comes back across the connection is sent
to your standard output.


ma réponse de TCSHeur sera donc:
debian> echo "get / http/1.0\n\n" | nc www.google.com 80


Je vous laisse juge ^_^

Wednesday, October 10, 2007

SEDS: user guide 0.1a

Puisque le développement de mon sprite editor peut reprendre (ça y est, il a sa fonction "wifi update" lui aussi), autant que j'en profite pour documenter son interface qui peut sembler a priori un peu rébarbative (oh, le doux euphémisme).

Je généralise l'utilisation du bouton "L" pour faire les "clics droits", permettant notamment de transformer le crayon en pipette, etc, et bientôt de faire un "flip" ou un "rotate" plutôt qu'un classique "scroll".

My sprite editor's development has been resumed thanks to the "wifi update" feature. So it is a good day to give a first userguide draft (the picture above). Note that the whole GUI uses the concept of "aLt-click", which is touching the screen while holding the L shoulder button. that's how you can pick a color in the grid rather than painting a pixel, or save your work in the spritetable. later on, it will als be used to flip the tile rather than scrolling it... Very soon, you will be able to switch between runme (the file transfer utility) and SEDS without power-cycling the console. stay tuned.

Si vous aviez déjà installé runme, vous pourrez bientôt basculer entre l'éditeur et le programme de transfer. Notez que la version SEDS-dkp20 est déjà en ligne (wifi update oblige) et que vous pourrez trouver un package complet sur sourceforge.


Utilisation simple:
copiez le fichier seds.nds sur votre carte mémoire, bootez-le, cliquez dans la grille pour dessiner vos pixels et référez-vous à la fausse-photo ci-dessus pour les autres actions. sauvez vos pixels dans le fichier A,B,X ou Y en tapant START-R-(ABXY), récupérez-les avec START-L-(ABXY). Tapez START-R-R pour sauver rapidement le fichier en cours d'édition.

Mise à jour par wifi

Note: Pour utiliser ces fonctions, il est nécessaire d'avoir installé exec_stub.arm7 et exec_stub.arm9 à la racine de votre carte flash.

Dans SEDS: Appuyez sur START puis SELECT pour lancer la sélection du point d'accès (automatique si vous avez déjà utilisé MarioKart ou un autre programme du genre avec ce routeur, manuelle sinon. Je ne pense pas que les clés WEP soient supportées pour l'instant).

Le programme se connecte alors à mon site pour récupérer la dernière version stable et l'enregistre sous "sedsw.nds" à la racine. note: c'est ce fichier que 'runme' tentera de lancer lors de l'utilisation du bouton 'edit' après un import de fichier .spr

Dans runme: Assurez-vous que vous avez bien copié dslurper.cfg à la racine de votre carte flash. Une fois connecté au réseau WiFi, appuyez simplement sur SELECT pour télécharger la dernière version runMEw.nds (également stocké à la racine). C'est aussi la version mise à jour que SEDS utilisera quand vous cliquez sur 'QUIT'.

Transfers par Wifi

Copiez les deux scripts server.pl et sink.pl
sur un PC qui est sur le même réseau WiFi que la DS, "server.pl" pour envoyer un fichier vers la DS et "sink.pl" pour recevoir un fichier. Comme ce sont tous les deux des scripts perl, il vous faudra d'abord installer perl sur votre machine (il est déjà là si vous avez Linux, facile à ajouter à cygwin, sinon, le projet ActivePerl devrait faire l'affaire).

Mettons que je veux envoyer xdad.spr, livré avec le software, que ma DS a reçu l'adresse IP 192.168.3.4 et que le PC, lui, a l'adresse 192.168.3.2, la commande à entrer (dans un shell) sera:

Code:
perl server.pl xdad.spr 192.168.3.4 192.168.3.2
Lançons maintenant runme.nds, on choisit son point d'accès (automatique s'il a été réglé avec mariokart ou un autre) et on voit apparaitre le fichier dans une liste. En cliquant dessus, on commence le téléchargement. C'est tout. En appuyant sur le bouton "A", on peut voir le fichier, écouter le .mod/.s3m/.xm/.it etc.

Supposons maintenant que je veux le récupérer sur le PC (oui, c'est idiot, mais c'est pour l'exemple), il me suffit de lancer
Code:
perl sink.pl other.spr 192.168.3.4 192.168.3.2
Ensuite, cliquons sur "beam out" ou l'on voit que le PC est prêt à recevoir un fichier et l'enregistrer sous "other.spr". Reste à cliquer sur "Tileset in Memory" puis sur 'other.spr' et c'est parti à nouveau.

note: cette technique ne marche qu'avec des fichiers de moins de 512Ko, ce qui n'est pas un problème pour vos sprites.