Tuesday, October 13, 2009

Ziggy, il s'appelle Ziggy ...

Unfortunately, I'm not the author of these graphics (2Dhero -- Tom Filhol is), neither am I working on a nintendo DS port of this indie game running on Game Maker for Windows. So why does it appear here ? because I'm studying it as much as I can: character design, graphic style, palette choice, composition. This is truly a platformer gem that we are offered here, reminiscence of Superfrog (with so much better gfx!) 

 Je ne peux pas m'empêcher de comparer Ziggy à Superfrog. C'est un excellent exemple de "jeu d'auteur" où la passion (et le talent, je dois l'admettre) nous apportent un jeu d'une qualité rare en ces temps de crise. Vous l'aurez compris: il ne s'agit pas de graphismes à moi, ni même d'un homebrew pour DS (dommage, d'ailleurs). 2Dhero nous a concocté son jeu "en indépendant", avec le Game Maker pour Windows, comme beaucoup d'artistes du pixel le font ces derniers temps. 

De mon côté, j'étudie tout ça avec beaucoup d'intérêt ... palette de couleur, composition de la scène, style graphique, etc. J'imprime en gros plan, je colle des petits extraits dans mon agenda, etc. Je ne "relookerai" probablement pas complètement Bilou pour suivre le "style ziggy", mais comme je coince sur les lianes et les fleurs ces temps-ci ... A noter au niveau gameplay une "attaque aérienne" qui permet de sauter horizontalement en plus du saut ordinaire, ce qui ouvre presque plus de possibilité que la "glissade", plus classique. Oh, et pour ne rien gâcher, il tourne dans wine...

Edit: it took me a while to do it, but in december, the 'slopes demo' features ziggy-inspired vines. 

Sunday, October 04, 2009

L'île des colons -- that was Bilou RPG

Je m'offre un petit moment de nostalgie... En cherchant "Bilou et son astro-flasheur à perforation en vrille" pour mon frère, j'ai repris une série de captures d'écran (vus sur twitter) d'un de mes plus gros projets en QuickBasic: Bilou's Quest. Un Zelda-like dont j'ai retrouvé une version sur diskette en fouillant chez mes parents il y a quelques semaines de ça. Le montage n'est pas génial: à l'époque de la sauvegarde, j'étais alors occupé à remplacer le joystick par la souris, ce qui fait que la version récupérée a besoin de la souris pour diriger Bilou et d'un gravis 4 boutons pour parler, soulever, etc. Bref, j'ai triché en démarrant les fichiers .BAS directement.

I'm taking you back 15 years ago, with a couple of screenshots i've taken this morning. Here comes the island that Bilou explores in Bilou's Quest -- one of my largest QuickBasic games. I recovered a backup on a floppy a couple of monthes ago and finally managed to make it run again ... well, sort of. I agree there isn't much to be proud about anymore: that's just a nostalgic memory, and the first occurence of Flower Power and Badman in pixels.

Du coup, je goupille comme je peux, je remplace les écrans auxquels je n'ai pas su accéder par des captures de l'intérieur des maisons et des grottes, etc. Bon, je vous le concède, en dehors de l'aspect "nostalgie", il n'y a pas grand-chose à en retirer. La maniabilité était innomable, les graphismes de Mystic Quest sous GameBoy sont bien plus réussis, le scénario manque cruellement d'inspiration, etc. Rien qui ne justifie que je cherche à en tirer une adaptation DS, quoi. Mais en son temps, c'était chouette de bosser dessus ;) Et puis, ne lui retirons pas sa valeur essentielle: c'est un projet qui a été transformé en un jeu. Compte tenu de la quantité impressionnante d'idées de jeu que "la farde PPP" contient, Bilou's Quest a tout de même le grade de "réalisation", même si ça ne couvre que 10% du scénario prévu (à la fin du niveau 1, le joueur n'a pas encore d'épée et ne peut se défendre qu'en lançant des pommes). Merci à mon frère Piet de me le rappeler.

Bilou's Quest (extra screenshots)

 Screen title used software-rendered fonts for better readability, and featured small cutscene with a "soldier bubble".


The "quest status" screen was equally black-background, and drew inspiration from "Zelda: Link's Awakening". You could pick two objects and assign them to the 2 buttons of the mouse ... but at this stage in the quest, you have no object yet. Your pal Bouli is shown in jail just above the load/save and the map icons.

Tuesday, September 29, 2009

IRQ_VCOUNT

Voilà exactement le genre de technique de programmation que j'ai toujours admiré sur les consoles (et les ordinateurs Commodore, qui d'une certaine façon, sont des consoles avec un clavier et un lecteur de disquette). Mettons que je veuille modifier au milieu d'une image les paramètres de l'affichage, comme la palette de couleur, la priorité et la position de tel ou tel plan du jeu, etc.

Pour un jeu vidéo, ça me permettrait par exemple de garder une zone de score fixe dans un jeu à scrolling, ou (*ze* cas d'école) de virer la palette dans les bleus à la hauteur du plan d'eau. Dans mon éditeur de niveau, ça permettrait aux boutons de rester affichés correctement malgré les choix d'afficher ou de masquer les différents "calques".

Bien sûr, ça peut être approché aussi sur les cartes VGA etc. à condition de bien synchroniser le timer avec les débuts et fin de ligne à l'écran. Et c'est là toute l'élégance de la "solution console": il y a une ligne d'interruption dédiée directement à cette synchronisation (donc plus besoin de timers), et dans le cas de la DS, on a carrément le luxe d'un registre supplémentaire qui indique si la ligne courante correspond ou non à une ligne indiquée.

void vcountirq() {

if (REG_VCOUNT<192) {
BG_PALETTE[0]=RGB15(0,0,31);
REG_DISPSTAT = (REG_DISPSTAT&0xff)|(192<<8);
} else {
BG_PALETTE[0]=RGB15(0,0,0);
REG_DISPSTAT = (REG_DISPSTAT&0xff)|(160<<8);
}
The 'vertical count matched' interrupt is a perfect explanation of why I prefer underground console programming against overworld PC games. It is a very simple mechanism that lets code be run when the graphic controller is about to process line Y, and yet it enables a wide panel of special effects in games. The most common "showcase" is for sure implementing water: at a given horizontal position, you swap the palette and provide a "bluer" one so that bottom of the screen looks sunken.
The above code snippet does just that in a "raw" fashion where only backdrop color is changed. Don't let yourself scared by those bit masking, combining and shifting. It is just another facet of computing that is *very* handy when dealing with hardware registers. If you think of your process as an "electronic process" taking place on an array of bits, it just becomes natural.

Une petite fonction toute simple donc, qui sera appelée "sur la bonne ligne" et qui change les couleurs (ici, une seule, et entre deux valeurs pré-calculées, mais c'est juste pour la démo). Astuce, pour pouvoir être invoquée sur plusieurs lignes (plutôt que toujours sur la même) et donc remettre la couleur à sa valeur précédente, je change le numéro de la ligne où l'interruption doit se produire pour lui donner la valeur suivante dans l'interruption elle même (c'est le code avec REG_DISPSTAT).

Bon, okay, le code avec les & et les << fait un peu peur: c'est des manipulations de portions d'entiers pour modifier un byte qui se trouve en réalité dans la moitié d'un registre de 16 bits. La programmation DS est remplie de bidouille de ce genre. C'est de l'informatique d'avant XML, qui exploite pleinement la structure binaire des nombres.

Bien sûr, pour que ça fonctionne, je dois enregistrer la fonction vcountirq via la libnds (il ne suffit pas de lui donner le bon nom pour que ça se fasse tout seul. Vous rêvez, les gars!)
irqSet(IRQ_VCOUNT, vcountirq);

REG_DISPSTAT = REG_DISPSTAT|(160<<8);
irqEnable(IRQ_VCOUNT);
Vous remarquerez qu'on retrouve ici aussi les "manipulations bizarres" sur DISPSTAT, pour l'initialisation. Heureusement, le web est plein de gens qui passent leur temps à expliquer "X&FF = garder les 8 bits de poids faibles de X", etc.

Et pour désactiver l'effet,
irqDisable(IRQ_VCOUNT);
tout simplement.
J'aurais pu vous bricoler tout ça juste pour le fun ou parce que je prépare en secret un nouveau niveau de Bilou avec de l'eau. Malheureusement, je n'en suis pas encore là. Je suis dans une impasse avec mon éditeur de niveau, tout simplement: les boutons qui me permettent de décider si je veux voir ou non le fond, le plan principal, les sprites, etc. disparaissent ou deviennent illisibles par suite des manipulations pour changer la visibilité des plans. Résultat, rien de tel qu'un bon "virq" pour forcer l'affichage à "revenir" dans le bon état le temps de m'afficher la barre d'outils qui doit se trouver en bas de l'écran tactile...

Well, i wish i was posting this message because i'm working on an impressive water level. Not yet. I'm simply stuck with the UI of my level editor, where i need more layers than the console actually provide, so I'm doing a dynamic "horizontal split" when the user press "down" to access layer visibility setup. The hardest part is to integrate this properly in the GuiEngine (as usual with OOP >_<)

... Reste à intégrer ça dans le GuiEngine ...

edit: i managed to integrate and test on real hardware. It works, despite the amount of time taken by the operations confirms just "dma'ing" a new palette wouldn't work. The actual code for my 'vcount' handler is only 8 lines long (50 instructions, involving 8 stores to video registers), but it takes two scanlines to be fully processed. Plus, the first scanline shows a "flickering" area of some 24 pixels wide, suggesting that even the "companion code" that brings us from the interrupt to the "virtual void online" snippet is also too long. Maybe pushing it to ITCM would help ... and having the interrupt taking place one line in advance and forcing a busy loop until we encounter a HBLANK.

update: Pour la petite info, c'est maintenant intégré et testé sur la DS elle-même. Et ça marche, même si je suis surpris de voir 8 modifications de registres (les données sont constantes: ça se voit dans l'assembleur généré par le compilo) prendre quand même deux lignes d'affichage pour s'exécuter ! Je devrais peut-être essayer de mettre les routines concernées en ITCM, histoire de m'assurer qu'elles soient toujours en cache, ou qqch comme ça (sur du C++, ça va être coton, tiens!).

Thursday, September 24, 2009

Sur GBA

On est en janvier 2001. Le GBA commence tout doucement à prendre de l'ampleur et je rencontre dans le bus un gars qui s'est acheté une "cartouche programmable" pour y mettre plus de jeu. Je me renseigne un peu, entre 2 release de Clicker, et je trouve pas mal de documentation technique confuse, mais alléchantes, sur les capacités de la bête.

Ma petite BD de Bilou a le vent en poupe. Je fais 2 à 3 "mini-strips" par semaine, et je commence à envisager la possibilité de réimporter tous ces petits personnages dans un jeu ... sur GBA, justement. L'occasion de donner un coup de jeune aux mouvements possibles. La version BASIC était assez simpliste de ce point de vue-là : un bouton (ENTER) pour passer au pouvoir magique suivant, et un autre (SPACE) pour utiliser le pouvoir sélectionné. [L] et [R] pourrait bien jouer ce rôle ici, mais après quelques heures passées sur Megaman X, je me mets à chercher quelque-chose qui n'interromperait pas l'action à tout bout de champ.

A.D. 2001, I discover the Game Boy Advance and meet in a bus a guy who bought a strange cartridge with some 256MB of flash memory that can host games you upload from a PC. I dig the hardware specs that seems very interesting though still incompletely understood. By the same time, my little Bilou comic project is gaining speed, with 2 to 3 strips a week, and i'm starting to dream of re-importing those characters into a newer version of the video game ... on the GBA.

Finalement, la réponse de Nintendo concernant ma demande d'informations supplémentaire sur le hardware son de la GBA et la perspective de devoir gérer le mode thumb et les copies entre ROM et RAM de quelques Ko auront raison de l'aventure avant même que je n'aie installé une suite GCC pour ARM (que mon frère s'était quand-même empressé de télécharger chez Wan, avec tous les tutos disponibles à l'époque! Il y croyait dur comme fer!)

These drawings are a testimony of an attempt to re-think the controls of the game. After each level, Bilou recovers one of the "magic stones" that increases its abilities. Here, i tried to stick to two buttons and avoid interupting the action, while the BASIC version had a "select power" button (ENTER) and a "use power" button.

Despite my brother's efforts to make me start working on it, Nintendo's reply (we were asking for detailed information about how the sound worked on the device) and some awkward aspects of GBA programming (co-existence of thumb and normal instruction set and the need to manually move data between ROM and a fairly small SRAM area) burried down the project. Only the Nintendo DS that can potentially serve both as the game platform and the development platform revived the dream of a Bilou game on a true gaming console.


Tout ça parce que dans son commentaire sur "Summer Flight", mon frère mentionnait que le mod avait été remixé plus tard pour la version GBA de Bilou (qui, je le rappelle, ... ok, je sors)

Monday, September 21, 2009

curseur de copie pour LEDS


There isn't much to show (yet) about the new modifications of LEDS and its (disappeared) user interface. I'm still under the process of revising the GuiEngine's internals, adding a "transient window" flag here, a GUI_ANYKEY event there, analysing the codeflow so that i can intercept keystroke in the proper widget, etc.
But altogether, it slowly brings a revised level editor with "improved" features. The most interesting one being the (so) long awaited "block copy" mode. Note that it isn't quite the kind of "block copy" you might expect, but rather an adaptation of the "copy cursor" from CPC basic that Pierrick loved so much: you L-click on a tile from an object you want to copy, and then you click and draw from another location to reproduce the object at the source. Pretty useful.


Je progresse sur l'éditeur de niveau, même s'il n'y a pas encore grand-chose à montrer. C'est l'inconvénient de l'approche "interface utilisateur absente" où j'utilise au maximum les boutons de la DS comme contrôles. Pourtant, en interne, ça se transforme pas mal dans le code du GuiEngine, notamment pour introduire les fenêtres "temporaires" capables de disparaître dès qu'on relâche la touche qui les a invoquées, etc.
Mais la nouveauté de ce soir, c'est la copie de blocs sur la map, inspirée largement du "curseur de copie" du CPC qui plaisait tant à Pierrick.

vous voulez essayer ? téléchargez le petit 'pack' combinant la version actuelle de l'éditeur, le niveau 1 de Bilou et ses tiles tous prêts au travail...

  • L+dpad = move around the map
  • "draw mode" : L+click = grab tile, click = paint tile, dpad = select another block from the tileset
  • "copy mode" : L+click = define the source, click & move = copy from the initial click position the source image
  • select = toggle between bg and fg edition
  • B = toggle blocksize (8x8 or 16x16)
  • L = toggle between "draw mode" and "copy mode"
This is a debugging demo, so (unfortunately), you can't save your edits right now and you cannot edit anything else but the embedded map with the embedded tiles. A fully-featured application with external files selection from the map is of course planned as soon as those widgets update are done.

todo: allow tiletable as source for copies.

Tuesday, September 15, 2009

Révision du LevelEditor

C'est reparti, donc, pour un tour sur l'éditeur de niveaux. Et ça risque de prendre un moment, compte tenu du fait que je ne me souvenais même plus de l'architecture que j'avais choisie pour les classes "*Window". Avant de m'attaquer aux gros morceaux comme "copier-coller de blocs" ou "rogner la carte", je vais déjà un peu rationaliser l'espace de travail, histoire d'éviter qu'il soit bêtement saturé.

Pour ça, je compte sur le bouton "R" pour passer du mode "édition précise" au mode "brouillon" et sur un nouveau système de "pull down window", c.a.d. des fenêtres qui deviennent actives (et visible sur l'écran tactile) tant que le Dpad est maintenu dans une direction donnée. Ceux qui ont joué à Zelda: Phantom Hourglass voient de quoi je parle.

I'm resuming work on the level editor. It's been so long that i need to draw UML diagrams again to figure out the relationship between the classes, and so on. As you can see on the figure, there are quite a lot of things i want to alter on the UI, most of them relying on a newly introduced trick to have "pull" windows (that is, windows that only remain active on the touch screen as long as you hold the DPAD in the direction that invoked them.

  • [done] clean-up user-interaction
  • [done] layer visibility, "grid magnetism", etc.
  • [done] block-copy mode
  • [wish] pattern-fill mode
  • [todo] map cropping
  • [todo] tile-swapping tool.
  • [need] fix that dprint() macro !
  • [done] .cmd parsing and monsters edition
  • [wish] radar for moving around
  • [done] status report out of the playground.