lundi, mai 26, 2008

Lost in Colorspace

Pour travailler en pixel art, il faut bien admettre que les couleurs choisies sont extrêmement importantes. Et avec ma "palette deluxe paint", moi, je suis plutôt mal parti.

Je m'explique: la palette DP est uniquement basée sur le modèle "RVB" des couleurs. Un dégradé de rouges, par exemple, partira du blanc (#ffffff) au rouge pur (#ff0000) pour ensuite aller vers le noir (#000000). entre le rouge et le noir, on aura (en plus de Julien Sorel) des teintes de rouges de plus en plus sombres en abaissant progressivement la composante rouge (seule restante). J'ai toujours utilisé ce modèle-là, mais il a ses limites.

Picking the right colors is of highest importance for pixel art. So far, SEDS is shipped with the "Deluxe Paint II" palette as default and i'm mostly using the palette from the game Tyrian for Bilou ... Which turns to be not a so good idea as it mostly uses "straight" ramps of colors. All my blue rasters, for instance, start with a nearly-white color, then gradually drop greens and reds to get to full-blue and then drop blue too to get to almost-black color.

Unfortunately, it's not very appealing for most situations, and it's clearly unappropriated for "natural" objects such as trees, rocks, etc. A new technique i've learned recently is to build your raster in HSV space, where hue, saturation and value are progressively altered to move from one color to the other. Sticking to a single hue will produce a quite uninteresting trunk for a tree, for instance, while having yellowish-highlight and red-ish shadows will turn out into a more "live" tree -- theoretically, i mean : i still have to test that live.

En particulier, pour des objets "naturels", un moins bon éclairage rend l'objet plus sombre, d'accord (c'est la base du rendu de profondeur), mais aussi d'une couleur moins franche (parce que nous ne voyons bien les couleurs que s'il y a assez d'intensité lumineuse ... repensez à votre dernière balade nocturne :) On aura donc tendance à désaturer les couleurs sombres en plus de réduire leur composante de luminosité, et inversément, à re-saturer les parties plus claires (même si on a jamais vu de zone jaune-orangée sur un tronc d'arbre), pour renforcer le côté "chatoyant" de cet endroit bien éclairé par le soleil ...

Tout ça me donne de nouveaux objectifs et une nouvelle manière de penser le "gestionnaire de palettes" de mon Sprite Editor.

  1. pour pouvoir plus facilement jouer avec les couleurs d'autres artistes, je me fais un petit script qui reprend la palette de n'importe qu'elle image et la propose à la DS par wifi.
  2. le meilleur moyen que j'ai jusqu'ici de trouver une couleur qui m'intéresse est de partir de deux teintes "extrèmes" et de demander un dégradé HSV entre elles. Ce qui m'intéresse particulièrement, ce sont les dégradés qui changent également la teinte et qui me permettent des bruns-roux pour mes troncs d'arbres avec des verts-jaunes pour les feuilles et la végétation.
Les formules de conversion RGB<->HSV sont faciles à trouver (wikipédia-power), mais plutôt moche à convertir en code. Enfin, ça ira, vous bilez pas : j'en ai vu d'autres ;)

all together, that gives me new objectives for the Sprite Editor (and mainly palette edition mode). I'm already working on a way to import colors (via Wifi) from a file laying on your PC during the edition, and using the "quick color selection" widget to manage and sort palette colors (as converters tends to mess them all).
Once this works, i'll try to build a "hsv-raster" feature so that we can feed two colors and pick any intermediaries between them. RGB2HSV functions are easily found on wikipedia, but they're quite ugly to code ...
edit: ça y est: mon SEDS est à nouveau fonctionnel. Il a fallu réorganiser presque toute la gestion de la mémoire vidéo pour pouvoir afficher les rasters importés par wifi. Pfiou.

jeudi, mai 22, 2008

Quelques vieux Pixels de Bilou

Une chose est sûre: Bilou n'est plus tout jeune. Et je ne vous parle même pas du petit personnage "Bubble" de Pierrick, programmé à grand coup de symbol 240, 60, 126, 201, 201, 255, 126,60,231, reprogrammant quelques caractères du CPC64 -- une machine dont l'architecture graphique n'a pas fini de me surprendre... Non.

Bilou n'a commencé à s'appeler 'Bilou' que lors de son portage sur PC, et a acquis plus ou moins définitivement ses couleurs à l'occasion d'un concours "expliquez-nous votre jeu et on le code" qui devait être contemporain de Super Mario 3 ... Auxquels on a finalement jamais participé pour cause de NDA et dont on a d'ailleurs plus entendu parler depuis.

Bilou is certainly not so young anymore. It all started with the "Bubble" character that Pierrick used in his programs on the CPC64 with the "symbol" statement, but it really became "Bilou" (say it "bee-loo") during a video game design contest back in the SMB3 days. While my brother and i finally decided not to run the contest because of the implied intellectual property mess, Most of the Green Zone and its monsters date back from that era. The Appleman, the yellow wood worm, the bumping mushroom, etc.


C'est d'ailleurs de cette époque aussi que date une bonne partie du "bestiaire" (au moins pour la forêt) et les super-pouvoirs de Bilou. A gauche, le désormais célèbre "appleman", le "feuillu" sournois et le "caterpillar" (version normale, pas le Boss, qui n'a jamais été programmé nulle part), le petit ver, le champignon sauteur et le "bubble bat".

A cette époque, évidemment, pas de Sprite Editor convenable, et je n'avais l'accès au PC que 1 heure par jour, et uniquement les mercredis et week-end. Donc le plus gros du boulot se faisait à l'aide de maqueurs micro-fins sur des feuilles millimétrées et de traceuses de cercles. Voilà donc les premiers pixels de Bilou, qui ont été vaguement utilisés pour quelques tests peu concluants en BASIC/VGA -- le temps que je décide que Bilou serait animé "à la rayman" pour fluidifier l'animation ... environ 3 mois avant l'apparition des premières démos de Rayman :P

This was a time where i hadn't any good Sprite Editor at hand, and could only use a computer one hour a day on wednesdays and week-ends. So most of the art was first "rendered" on a millimeter-grid sheet of paper with color markers before it was manually run-length-encoded in a dedicated BASIC program ... maybe. The contest also see the first definition of Bilou's superpowers (he got one extra power everytime he recovers a magic stone) : flying, swimming, laser fire (and protecting glasses), etc.

On voit déjà ici quelques-un des pouvoirs spéciaux de Bilou d'alors: voler (en tourbillonnant comme un hélicoptère), nager, tirs au laser (et les lunettes qui vont avec), et je n'ai pas repris sur le scan la transformation en petit nuage, ni le lancé de Game-Boy qui immobilisait temporairement les ennemis...

Allez, pour la cloture, une image d'anthologie, recodée sur l'émulateur CPC par Pierrick entièrement de mémoire. Ce n'est pas le code source du tout premier Bubble, mais bien de son tout premier adversaire. Ce qu'il y avait de bien, avec le CPC, c'est qu'on pouvait réécrire par dessus certains caractères, sans effacer le fond. Donc il faisait un caractère "balle" en bleu et un second avec le blanc des yeux, deux print et deux locate, et vous aviez déjà un petit perso multicolore.

Dangerous Temple ...

XRick, c'est un des seul jeu auquel j'ait vraiment joué (mis à part Solitaire et Démineur) sur mon Zaurus.

Du point de vue "pixel art" (si on peut dire), j'ai envie d'attirer l'attention sur la "richesse" qu'il y a dans le décor, avec seulement 30 caractères sur cet écran (je ne compte pas le fond, hein, juste les rocs et les briques). Et ce qui est amusant, par exemple, c'est que puisque les briques ont exactement une taille multiple d'un caractère, on peut les combiner comme on le veut.

Mélanger terre/rocs et briques, c'est le secret d'un temple maudit bien réussi. Les graphiste de "Lost Vickings II" l'ont bien compris, mais à mon avis pas parfaitement interprété. Dans Rick, pour des raisons d'économie, l'ensemble des bords du temple est fait avec des briques, et uniquement avec des briques (jamais des rochers). Ici, les graphistes ont pu s'en donner à coeur joie avec ces zones de terre qui débordent un peu, sauf que si vous voulez mon avis, c'est raté : on le dirait "collé" par-dessus le mur :P

Autre détail un peu loupé, à mon avis, c'est d'avoir utilisé un bloc carré (en l'occurence 16x16) comme élément de base plutôt qu'une vraie brique (16x8 dans Rick, et ç'aurait pu être 32x16 ici sans soucis. Oh, il y a bien des briques de ce genre, mais trop détaillées pour pouvoir servir de "passe-partout". le "simple pavé 8x8" sert presqu'exclusivement de bouche-trou dans Rick Dangerous, et c'est très bien comme ça.

Bon, à côté de ça, ils ont de superbes lianes dans LV2, hein. et quelques colonnes bien sympa aussi, et l'habituel "gros bloc-icône" représentant la divinité vénérée dans ce temple. Un must.

Enfin, un dernier élément sympa de ce temple, c'est les pavés décalés. Ils devaient avoir un moteur de collisions un peu plus sophistiqué qu'à l'habitude dans ce jeu, parce que non contents d'avoir plusieurs inclinaisons de pentes, ils se sont permis d'avoir plusieurs hauteurs de sol plat ces cocos. Evidemment, c'est beaucoup plus crédible pour une ruine d'avoir des pavés de travers, et c'est beaucoup plus crédible que les pavés soient dessinés de travers si notre personnage doit s'adapter à ces variations de terrain. Et là, je vous avoue que dans l'état actuel des choses, on ne saurait pas encore faire ça dans Bilou ... Donc, retour à la planche à design ce soir et je refait un essai sur cette histoire de bordures :-)

Et bien sûr, je ne peut pas conclure sans remettre un petit bout de cet excellent temple par Tomf sur pixelation, tout en pixel art désaturé, bien sûr. Tomf a parfaitement géré le coup des briques et son temple est visiblement en bien meilleur état que d'autre. Et si ses lianes sont moins luxuriantes, elles ont leur petit charme quand-même. On pourra peut-être regretter l'absence de parties "roc" pour changer un peu, et le décor de fond un rien répétitif, et on aurait ajouté des statues d'idole, que ça n'aurait pas fait de tort, imho.

Oups. Je suis impardonnable. J'ai oublié de mentionner le "labyrinthe" du premier Sonic dans la série. Bon, vu comme ça, ce n'est pas vraiment convaincant, je l'admet ... mais quand j'ai imprimé ce niveau pour faire un peu d'analyse au niveau "level design", je vous assure que ça sautait aux yeux ...

d'ailleurs, ça se voit tout de suite sur une vue un peu "dézoomée" de cette version master system : les concepteurs ont essentiellement travaillé sur les bords, sur lesquels l'attention du joueur se portera principalement ...

lundi, mai 19, 2008

le côté obscur ...

Petite page web (prétentieuse?) que j'avais créée il y a quelques temps avec des sujets de programmation que je jugeais "trop perturbant pour mes pauvres étudiants". Entre-autres, des hacks autour de ce que Cyril (et les gens du standard C99) appelle les compound literals, qui permettent des choses bien amusantes comme
   struct llist *lst=cons(a1, cons(a2, co...ns(aN,NULL) ... ));
pour construire une liste liée de constantes.

Ca a marché dans gcc 2.95.3 puis plus trop dans gcc 3.3.x, etc. au point que j'ai fini par laisser tomber. En fait, c'est maintenant une partie intégrante du standard C99 (tout comme for (int i=0;i<10;i++), par exemple), donc je le dé-pioche. Bonne lecture aux Codeurs foos

dimanche, mai 18, 2008

"even less interesting than kirby"

Enfin quelques réponses à mon petit mockup (probablement trop "capture d'écran d'un test" et pas assez "mockup" au goût des habitués) sur le forum pixelation. J'ai du boulot pour retravailler mes pixels. Voyez plutôt :

  • Zeid: "Kill like half a dozen colours. You are using way to many and to little effect, organise a decent palette and apply highlights and shading according to the material"
  • "Use a grey background as the placeholder background, the green you have set on right now is way to saturated and will affect how your sprites seem to look."
  • KittenMaster : You could hue shift the shades gradually from the reddish brown into more yellowish browns in order to have a better connection to the green in the picture. And the worms have bad selout.
  • MrMister : The mushroom in the tree is really arbitrary and you should try adding some more of em to make the scene more interesting.
Oh, juste à côté, c'est la révision de Bilou en 'vrai pixel Art' par Zeid. Ca donne bien, mais j'ai vraiment du mal à m'écarter de mon bon vieux bilou ...

En clair,
  • [done] il faut que j'ajoute un "organiseur de couleurs" dans SEDS pour pouvoir manipuler plus facilement mes rasters, etc.
  • [done] il faut aussi que j'ajoute un "créateur de couleurs" (parce que encoder des #rrggbb au D-pad, c'est pas top)
  • [done] exporter plus facilement les images de SEDS vers le monde PC (spritetable en png, animations en .gif)
  • [wish] il faut que je teste l'animation de Bilou "à la rayman" avec les mains et les pieds
  • [done] mes arbres ne donne pas mal comme buissons, mais ils sont trop saturés pour ça.

vendredi, mai 16, 2008

Faut que je repense les test-points

Bon, Bilou saute, il tombe, il rebondit ... tout ça c'est bien joli, mais il a tendance à se retrouver un peu trop souvent dans les murs à mon goût. Et en plus, son comportement devient un peu trop complexe à exprimer dans mon modèle de machines d'état. Pensez un peu. Rien que pour le saut, il me faudrait pas moins de 10 états si je veux que Bilou se "souvienne" de la dernière direction dans laquelle il est allé :P

Great. Bilou jumps, Bilou falls and bounce. It's all nice and funny, but he ends up into walls a bit too often to my tastes. Moreover, it's getting too complicated to express his behaviour only through that state machine approach: only jumping takes up to 10 states if we want to remember the last direction Bilou has been leading to ^^"

One of the reason why it's getting so complicated is that when jumping forward, there are additional testpoints to be checked, while these testpoints are disabled when jumping simply "upwards". The solution would be relatively straightforward: i need a new class of testpoints that would be conditionnal on horizontal speed.
Une des raisons de toutes ces complications, c'est que lorsqu'il saute vers l'avant, Bilou doit vérifier deux testpoints de plus (pour éviter de rentrer dans un mur) mais que ces testpoints ne sont pas souhaités lorsque le saut est simplement vertical (sinon, on ne peut pas sauter le long d'un mur ^^"). La solution est relativement simple, heureusement, il suffit de créer une nouvelle "classe" de points-test qui ne serait active que lors d'un déplacement horizontal. Cyril avait bien proposé le passage à un moteur physique plus complet (avec gestion de la friction, de l'élasticité des chocs et tout -- vous savez comment est Cyril ;) mais je préfère garder ça au niveau du script pour l'instant.

Autre petite modif' en cours: varier les types de blocs possibles. C'est joli, un éditeur de niveau qui vous propose toutes sortes de pentes, de blocs réactifs et ce genre de choses, mais si le moteur de jeu voit juste "ciel" et "roc", on est pas avancé. Enfin, ça, ça peut prendre encore un moment.

samedi, mai 10, 2008

Way of the Pixel ...

Quelques tiles sur le thème "forêt" et "temple déchu dans la jungle" chipé sur Pixelation que je voudrais bien étudier ...

a couple of tiles from various artists that i have grouped together for study and tests using SEDS. Note the relatively low number of colours per tile : pixel artists tends to work with 16 (sometimes 32) - colour palettes.

Sources: vierbit's jungle, opacus' floating(?) rocks and jericho's rpg tree

vendredi, mai 09, 2008

pour reprendre mes vieux jeux sous DS ...

Bon, je vous ai déjà parlé de Badman, un de nos personnages phares sur le GameMaker, et de "comment le fait que les graphismes utilisent des blocs de 20x20 pose problème pour un portage sous DS". Bin hier, je suis retombé sur le plan de mon premier donjon pour "Bilou's Quest", ma petite tentative de RPG en BASIC (avec l'introduction de la souris dans mes programmes QB) qui n'était peut-être pas extraordinaire au niveau du scénario (tout un donjon pour trouver son bouclier alors que l'épée ne sera là qu'au niveau 2, bon ...)

Soit. De nouveau, dans Bilou's Quest, les graphismes étaient en 30x30 avec des salles de 9x6 "dalles" ... moyen pour le portage pour DS, mais j'ai peut-être bien une piste pour le faire tourner malgré tout. L'idée étant de construire des graphismes de 32x32 qui, une fois "dézoomés" pour faire 30x30, redonnent les images originales. Pas de chance, par contre, je parviens à faire 32->31 (zoom factor 273) ou 32->29 (zoom factor 274), mais pas 32->30 :P Au mieux j'ai un mapping 32->15 ... un peu gourmand en VRAM (4K par dalle), mais comme vous pouvez le voir, je n'avais pas tant de variété dans les blocs (36 à tout casser) et la plupart étaient en 16 couleurs (indispensable pour arriver à afficher Bilou par-dessus à l'époque), donc ça devrait passer.


Restait à découvrir quels pixels d'une ligne de 32 sont affichés quand on 'dézoome' (indispensable pour avoir de bons graphiques). Je vous le donne en mille: 1357911131416182022242628. Je devrai pouvoir faire pareil pour 32->20, mais là il me faut encore un brin de chipotage pour dire qui va où.

Bon, d'un autre côté, il n'y avait rien dans Bilou's Quest qui nécessite vraiment un affichage par tiles, donc je pourrais fort bien prendre un écran bitmap et faire le rendu comme dans le mode 13h du VGA, en fait.

lundi, mai 05, 2008

gedsdemo : get it!

Avec un petit desmume intégré à ubuntu, plus "byzanz" pour la capture vidéo (en .gif ... y'a mieux, mais c'est plus cher), et voilà un petit aperçu du rendu de la greenzone ...

vous pouvez télécharger la démo ici.

Okay, time for a demo. Here's what my Game Engine for DS (geds) looks like with a greenzone tileset and some sprites for the Bilou game ... captured out of desmume rendering using "byzanz".

Sorry for lacking time to translate former posts that describe my work. Hope i'll be able to do that soon.


PS: le moteur de jeu est et restera Open Source, mais en revanche, les droits d'auteurs habituel s'appliquent aux graphismes intégrés dans la démo.
Please keep in mind i spent hours on the art, and that unlike code, it is not open for reuse.

vu sur wayofthepixel et dev-fr.

vendredi, mai 02, 2008

*bounce*

Un nouveau pas important pour la réalisation de Bilou a été franchi: j'ai mon évaluateur d'expressions, et son intégration au moteur de jeu est quasi-parfaite. En clair, cela signifie que je peu maintenant indiquer via mon scripteur de niveau que lorsque Bilou arrive sur le sol, il doit:

  • rebondir si sa vitesse est trop élevée
  • s'arrêter si la vitesse n'est pas trop grande.
Avant la DS, j'avais essentiellement testé deux mode de développement de jeux: le BASIC et le GameMaker de Recreational Software.

Côté BASIC, c'était la liberté totale pour les algorithmes et les comportements des monstres, mais les possibilités graphiques restaient restreintes -- même sur Pentium '90. Côté GM, c'était le constat inverse: scrolling dans des niveaux relativement grands, un nombre d'animation et de monstre présent à l'écran quasi illimité (au point que Pascal s'est même servi de monstres pour faire les bonus de notre remake de Pop'n'Twinbee). En revanche, le GameMaker était totalement incapable de gérer un saut un peu potable. Le simple fait d'avoir un sprite différent pour la montée et la descente du saut était impossible. Alors faire faire une cabriolle au perso quand il arrive au sommet de sa parabole (comme dans Bilou sur Basic), vous pensez bien ^_^.

About 10 years ago, i decided that neither QuickBasic nor recreational software's GameMaker could still fullfil my needs for creating games. I wanted parallax scrolling, compound sprites (think of rayman, but i already had it for Bilou in QB), and most importantly, more flexibility in creating monsters attack patterns.
I don't want to have to program them at the lowest level of machine code, i want their behaviour to be part of the game data, not part of the game engine.
When restarting game development on the DS, i decided to opt for something that would be state-machine inspired, but capable of reacting to the level map, the hero's position, etc. How to actually make it working came up later while reading the "making of Another World" .

Bref, à part des fioritures comme le parallaxe ou des sprites composés (à la Rayman), mon projet "Ultimate Game Maker" devait surtout permettre une plus grande souplesse de programmabilité : un scripting des actions : ne pas se limiter à des transitions "d'un état à l'autre" pour la gestion des monstres, etc. mais permettre plusieurs transitions depuis un état en fonction de l'état actuel du monstre, et une modification de certains de ses paramètres. Comme vous pouvez le voir sur l'image, je vous concocte déjà un petit 'appleman' bien particulier grâce à ce nouveau mécanisme.

C'est en lisant un making of du jeu Another World que l'idée est revenue au premier plan pour la DS. Dans Another World, Eric Chahi a choisi de disposer d'un environnement de développement pour son jeu qui ne nécessite pas de recompilation entre deux tests successifs, mais aussi la possibilité d'écrire toute la logique du jeu indépendamment de la machine considérée. Le jeu étant développé sur Amiga500 et constitué exclusivement de polygones rendus 'à plat' (à partir d'image filmées, il n'y a donc aucun calcul 3D), il n'est pas possible de s'en tenir à un "BASIC" traditionnel, trop gourmand en temps de calcul. Eric nous concocte alors son propre petit langage, mélange d'assembleur et de BASIC (oui, quand-même) dans lequel il va exprimer toutes les réactions du jeu (genre "quand le laser entre en contact avec la base du rocher, le rocher se décroche et s'incline en oblique").

Aucun élément compliqué n'intervient (pas de chaînes, pas de structures de données complexes): Eric utilise uniquement 256 variables entières pour représenter l'état du jeu, et le plus souvent, il ne les nomme même pas.

Même le maniement du joystick est géré de cette manière.

Another World was coded by Eric Chahi on an Amiga 500. He wanted cross-platform game logic for a game whose logic is *much* more complex than a shoot'm'up, and he also wanted to avoid recompilations between two tests. He thus naturally opted for some scripting language -- a mix between BASIC and assembly -- through which he controls animations and game variables (just integers).
Well, that's more or less what i'll do for my sidescroller game engine, except that you'll have per-object (monster, hero, switch...) variable in addition to the global (per-level) variables. In my case, i can even make the scripting simpler than Eric's "bassemblic" as it will essentially be used in predicates and actions of a state machine. So no control flow is needed at all.

Eh bien, je me suis dirrigé dans la même direction avec mon Game Engine, mais en donnant plutôt 16 variables par personnage (oh, il y aura aussi des variables globales comme dans Another World, rassurez-vous). Je me suis évidemment inspiré de mon interpréteur WASP qui m'a valu mon doctorat pour le bytecode, mais en simplifiant encore un coup: il me faut des expressions, pas des programmes ici. Donc exit toutes structure if-then-else ou les boucles, qui peuvent se coder par la structure de la machine d'état. Reste à inclure quelques instructions supplémentaires (p.ex. créer un nouveau monstre ou jouer un son), mais la base est là, même si mon 'langage' est encore plus moche que le bassemblic de Eric Chahi.

# gestion de la chute de Bilou.
state4 :anim0 {
using gravity
testpoint off (4,16)
testpoint off (12,16)
}

state5 :anim0 {
using stopper
testpoint on (4,16)
testpoint on (12,16)
}
# si la vitesse est trop élevée, on rebondit en la réduisant de moitié.
state4->state4 on fail [v1 $40 >=] (v1 2 / ~ :1)
state4->state5 on fail [t]


En avant. Essayons de voir si j'arrive à fixer la caméra sur Bilou pour le promener dans le niveau. Et en même temps, je vais tenter de faire un petit .nds de démo pour que vous puissiez tester ça sans devoir comprendre le fonctionnement de mon 'runme'.