Wednesday, March 31, 2010

- * aouch * -

I'm not going to claim that 'it works! I can't believe it". It's a little too early for that, but at least I've got the framework set up and the boring stuff done. I can have little stars shot away from Bilou when he's stomped by Funky Funghi. There are still weird things to be investigated such as "why doesn't they disappear as expected?" or "why do they look like coming out from Funky Funghi rather than from Bilou?"

Il est encore un peu tôt pour crier victoire, mais ça prend forme. Ces petites toi-toiles s'échappent de Bilou lorsqu'il se fait écraser par Funky Funghi ... les éléments permettant de gérer des objets dynamiques s'assemble ... l'objectif "apple assault" se rapproche. Il me reste à comprendre et corriger quelques effets curieux. Ce serait aussi bien qu'elles disparaissent lorsque leur animation est terminée par exemple ... et qu'elles proviennent effectivement de Bilou.

Source-checking and cross-checking doesn't seems sufficient. I'll have to meditate this.

edit: les petites étoiles sont supposées rebondir quelques fois sur le sol puis disparaître grâce au code suivant:

state19->state19 on fail [v1 $20 >] (v1 $40 - ~ :1)
state19->nil on fail [t]
mais curieusement, ça ne marche (presque?) jamais avec [v1 $40 >] comme gardien et seulement de temps en temps avec le code ci-dessus. Je viens de réaliser que le contrôleur "gravity" ajuste la vitesse verticale lorsqu'on rencontre le sol de manière à ce que la chute se termine sur le sol. Ca casse évidemment tout mon beau mécanisme puisqu'au moment de l'évaluation des transitions, ce n'est plus la vitesse de l'impact étoile-sol que je lis, mais la distance à laquelle l'étoile se trouvait par rapport au sol. Je vais réviser ça. Ca pourrait bien expliquer quelques autres bugs dans le comportement de Bilou et de l'Appleman.

Oh, and btw, here's a small UML snippet of the classes involved in such "extra actions". The 'red path' show interactions when an action definition is parsed, and 'blue path' how the actual "shooting" occurs.

Tuesday, March 30, 2010

Gobs Dynamiques

Pour permettre que Bilou soit assailli encore et encore par (e.g.) des Applemen, il me faut ajouter à mon moteur de jeu le support des objets dynamiques. Jusqu'ici, chaque élément "vivant" du jeu (les "GameObjects" ou "gobs") est déclaré dans le script produit par le level editor. Il possède un numéro d'identification unique qui détermine sa place dans la "table" des gobs. Si ça marche plutôt bien pour les ennemis classique, c'est évidemment insuffisant pour les tirs (pensez à un shoot-m-up), les bonus mobiles (le champignon de super-mario), les petites animations sympa (la petite étoile qui apparaît quand Kirby se cogne trop fort) ... et ... les monstres créés à la volée par un "générateur" (qui sont une variante des tirs, finalement).

J'ai déjà en partie la logique qui permet d'invoquer la construction d'un objet depuis la logique du jeu, je dois encore m'assurer que j'ai la possibilité de décrire le fait qu'un tel objet peut disparaître ... et mettre en place un petit test pour vérifier que tout ça fonctionne bien.

So far, most of the sprites in Bilou are statically defined in the game script produced by the level editor. They have a unique ID, well-established initial coordinates and so on. And that works pretty well, mostly because I haven't introduced anything like "shots", moving bonuses or any run-time generated monsters. One of the key elements of "Apple Assault" is precisely that there will be more and more monsters coming like in a Game&Watch.

I've got some of the logic to bring new monsters to life during the game ready, which has been tested for sound effects. I need to check that such monsters can also be terminated, both during the game (e.g. at the end of an explosion animation) and when the level is completed/restarted.
Then I'll need to put this all together and check it indeed works as expected in a small "gedsdemo".

I'm not pretending it's a tedious task. I'm just a bit overwhelmed IRL to start coding something that allocates memory dynamically after office hours.


Et pour être tout à fait honnête, les parts de Munchkin et autres pizza-buffet initiés par mes collègues sur le temps de midi ne sont pas complètement étranger à l'apparente lenteur sur cette tâche.

Thursday, March 25, 2010

LE Bilou's Book

C'est un cadeau royal que mon frère me fait là! La toute première instance du Bilou's Book, reprenant mes p'tits dessins les plus aboutis sur ces 10 dernières années en un album "extrafilm", avec quelques extraits de ce blog, et une petite rétrospective du projet. Je devrais être en mesure, d'ici quelques jours, de vous permettre de l'avoir vous aussi.

Les épisodes du premier tome ("green woods") sont étonnamment bien rendus, de même que les quelques interventions des soldats-crayon. Je transmettrai à mon frère les fichiers initiaux des planches colorées, histoire qu'il puisse les mettre à résolution maximale. On a par contre été tous les deux un peu déçu du résultat "jpegifié" du pixel art, en particulier avec le fond mauve de SEDS ou du RSD Game-Maker. Si quelqu'un a des conseils dans ce domaine-là, je suis preneur ^_^

I think my brother offered me my best birthday gift ever since I stopped receiving LEGO blocks: the first tome of the Bilou Book, printed on glossy paper, including the comic strips "crayon & sharpenher", "sponge bop",
"inkjet escape" and other blog heroes. It also features a surprisingly hi-quality set of the early "green woods" comics, and of course, bits of this very blog, detailing the story of a 15-year-long project.
We'll work on making it available to all Bilou's fan as soon as possible.


Ca y est ? vous avez compris comment Apple Assault est revenu en première ligne ?

Tuesday, March 23, 2010

Apple Assault

A force de compter les moutons pour essayer de me rendormir cette nuit, ils ont fini par se transformer en Applemen ... et Bilou était assailli encore et encore. Et à chaque collision, mon écran de débug confirmait les zones et les testpoints. En rebondissant sur plusieurs applemen d'affilée, la barre de punch de Bilou augmentait, ce qui lui permettait des "finishing moves" assez dévastateurs.

It was another such night, where I just can't get no sleep. It is supposed to help if you count sheeps, and so did I ... until sheeps started turning into angry applemen. They were assaulting Bilou, again and again, and there was no hope to escape them. It was punish or perish. And by chaining bounces over applemen's "heads", Bilou was gaining more punching strength that let him release impressive "finishing moves".

Then the sound got clearer, as letters "R E A D Y" were falling from the sky, prompting me for another round. Small echoes set the rythm, until in a zaash! they zapped to the right, letting the action start again. It was the sound of my bro' String Tracking.

Puis sur un "dit dililit dut dut deut deut" les lettres "R E A D Y" tombait en rebondissant avant de partir en trombe vers la droite sur un "ch..ooOO()()WAh!" et la bande son enchaînait sur la version 6 pistes du "String Tracking" de mon frère.

Ca doit venir du cadeau que mon frère a choisi pour mon anniversaire, qui reprennait ce dessin destiné à Romain. A l'arrière plan, le côté "débordé par l'avalanche de monstres" m'avait servi à illustrer le principe de "Bilouh-lanta" lors du petit sondage de janvier. Titre peu accrocheur supposé indiquer qu'il s'agit en somme d'une opération survie. "Apple Rumble 2" aurait été sympa, mais confusionnant. Ce sera donc "Apple Assault". On verra bien qui de lui ou de "Nuts'n'Bolts" peut être réalisé en premier.

If you followed January's Poll on "what should be the next milestone", you may have identified the "Bilouh-lanta" study case ... Which is more likely to be renamed "Apple Assault". I can't tell yet whether i'll focus on this and come back to "Nuts'n'Bolts" afterwards or whether I'll honour your preferences and keep working on the not-so-obvious-to-code distant clone of Manic Miner. Only time will tell, I guess.

Friday, March 12, 2010

Crumbling Floor ... revisited.

Alors quoi ? Si c'est si simple de faire un sol qui croule dans Manic Miner, pourquoi est-ce la prise de tête ici ? Me suis-je trop compliqué la vie avec mon moteur de jeu et mes scripts ?

L'état est entièrement encodé dans le graphisme

Willy ne tourne qu'à 25Hz, Bilou à 60. A chaque frame, le sol de Willy est dégradé d'un pixel de plus si Willy est toujours dessus. Si je veux faire un autre style d'animation ou si je souhaite quelque-chose comme des morceaux de pont qui balancent quand on marche dessus puis tombent dans le vide après un bref délai, la "technique Willy" n'est plus appliquable. Bien sûr, en 1983, Matthew Smith ne s'était pas encombré avec "mais, on pourrait vouloir faire disparaître le sol un peu différemment plus tard dans le jeu" ^^"

J'ai une approche "bottom-up"

Le programme de Carles est contruit en divisant le problème (coder Jet Set Willy) en sous-problèmes (déplacer Willy, gérer les collisions), etc. Dans mon projet, j'ai une machine (la DS) et un objectif un peu difficile à réaliser directement sur cette machine (Bilou). Du coup, j'essaie de me construire une machine virtuelle (moteur de jeu, langage de script, outils d'édition de maps, etc) dans laquelle le problème serait plus facile à résoudre. Cela se prète mieux à la généralisation à un "game maker" par la suite, mais ça veut dire aussi que tant que je n'ai pas trouvé le bon jeu d'abstractions, les solutions sont bancales.

J'évite de sur-utiliser les sprites

Je pourrais ajouter quelques "actions externes" à mon langage d'expressions qui altèreraient le contenu de la map, et tout gérer avec des sprites. Je marche sur un pont ? hop, le fond disparaît et est remplacé par un sprite du même morceau de pont qui bascule. Si je ne suis pas resté trop longtemps, le sprite "réécrit" le bloc sur la map avant de disparaître. Ce genre d'approche risque d'introduire trop de sprites sans qu'on puisse contrôler combien il devrait y en avoir. Vous vous souvenez du "spinning block" de Mario World ? Imaginez un peu qu'il ait fallu animer un sprite pour chaque block qui se mette a tourner parce que vous l'avez touché ... bonjour l'horreur!

L'idée est donc de rajouter quelques abstractions de base, telles que "une animation liée à une position sur la carte" (pour les ponts, le spinning block, etc.) et "une portion de la map dont je peux changer le contenu" (pour les passerelles que l'on fait apparaître ou disparaître à coup d'interrupteurs comme dans Keen). Les cogitations sont en bonne voie. Le code suivra ... comme les autres éléments de mon énorme "todo list". Derrière la façade de "vous aimez le nouveau look du site", il y a donc une sorte de "bouillonnement" de choses difficile à décrire qui avance dans le bon sens dans les slots de temps libre qu'il me reste. J'espère parvenir à en dire plus long prochainement.

A+

Thursday, March 11, 2010

HD mais pas trop.

Au n° 1 des choses à modifier sur la banderolle actuelle, Gédéon listait "Bilou en gros pixels". Voilà. C'est chose faite. Le crayon et la souche suivront.

J'ai appliqué la même technique que celle qui me permet de faire mes vignes et tout ça : zoomer le sprite puis le sauver et retoucher dans SEDS, ce qui me permet d'avoir un bilou de 32x32 pixels.

Alors je vous le dis tout de suite pour que vous n'alliez pas vous emballer : c'est chiant comme la pluie à faire et je ne vais certainement pas jouer à refaire ça avec tous mes graphismes. La banderolle suffira amplement.

Mais bon, puisque je m'attaque à une nouvelle démo inspirée de Jet Set Willy, autant remettre à jour ce qui sert de "page d'accueil" avec des graphismes vraiment utilisés pour mes jeux ... Le Bilou précédent avait quand-même été dessiné sous Delux Paint IIe pour MS-DOS ^^"

Wednesday, March 10, 2010

B_CRUMBLINGFLOOR

Somehow, I stumbled upon this re-implementation of the Manic Miner / Jet Set Willy engine in Visual Basic. I'm unsure on how I should implement crumbling ground in Bilou (or any block animation in response to character's presence). Let's see how a +20 year old game handled it...

Bon, je l'avoue, je suis intrigué par la quantité d'"éléments spéciaux" présents dans un jeu aussi vieux que "Manic Miner" contient, et la difficulté que j'ai à trouver une manière convaincante de réaliser la même chose dans mon moteur de jeu actuel. Du coup, j'ai mis la main sur une ré-implémentation du jeu en Visual Basic. Voyons donc comment les blocs-qui-disparaissent-quand-on-reste-dessus ont été gérés ...

' block type constants
Private Const B_CRUMBLINGFLOOR      As Byte = 2
Block types are encoded in a separate array, with one byte per 8x8 tile. One such type is "crumbling floor". Other block types include B_AIR, B_FLOOR, B_WALL, B_CONVEYOR and B_NASTY (two of them) and B_SPARE (for switches). Jet Set Willy only has one B_NASTY type, and the other one is converted into B_SLOPE. This is consistent with my own engine.

Carles a construit son moteur de Willy de manière à réutiliser les données du jeu telles quelles -- sans être le code original sous Z80, ça donne malgré tout une bonne idée de ce qui aurait pu être fait. En l'occurence, par exemple, la structure de chaque niveau est donnée par un tableau de la taille de l'écran, indiquant quels graphismes utiliser, mais aussi le type de chaque bloc entre 0 et 7.

B_CRUMBLINGFLOOR est celui qui nous intéresse. En cherchant "crumbling" plus loin dans le code, je tombe donc sur la fonction DoWilly (extrait ci-dessous) qui gère toutes les interactions entre Willy et le monde qui l'entoure. DoConveyors ne fait qu'animer des blocs, de même que DoGuardians se contente de déplacer les monstres. Ce sont les sous-fonctions de DoWilly qui détectent les collisions et altèrent le déplacement du personnage. Exactement le genre d'approche que j'utilisais dans Calimero et Bilou en QuickBasic.

What's interesting (for me :-) in Carles' approach of redoing Willy's world is that he operates directly from the tape file of the spectrum, so not only it has the "readability" of modern BASIC (i'm not that much into Z80 assembly ^^") but it still explains the logic of the original game (how switches, witches and stuff are encoded).
If (.mode = [eWalk]) Then
If Not (WillyCheckFeet()) Then
' code for falling stripped out ...
End If
Call WillyCheckConveyor(keys)
Call WillyCheckCrumblingFloor
End If
The DoWilly() sub shown above proceed step by step, handling interaction of Willy with every item "present" in the game. That is, we have DoConveyors or DoGuardians as well, for sure, but they merely perform animation and movement job. WillyCheckConveyor makes sure conveyor pushes Willy. That's the real job.
Let's thus have a look at WillyCheckCrumblingFloor just below ...


Voyons donc WillyCheckCrumblingFloor dont le code est ci-dessous. Après s'être assurée qu'il y a bien un bloc friable sous les pieds de Willy, elle va utiliser FXCrumblingBlock pour procéder à l'animation (décalage du tile d'un pixel vers le bas) et transforme les propriétés du bloc donné en "B_AIR" si FXCrumblingBlock lui dit de le faire à travers la variable f.
o = .x + (.y \ 8 + 2) * 32
For c = 0 To 1
If (m_RoomBlock(o + c) = B_CRUMBLINGFLOOR) Then
Call FXCrumblingBlock(m_DIBBack, 8 * (.x + c), .y + 16,
                      CAPaper(m_RoomData(o + c)), f)
Call FXCrumblingBlock(m_DIBMask, 8 * (.x + c), .y + 16,
                      I_BLACK, False)
If (f) Then
   m_RoomBlock(o + c) = B_AIR
   Call FXRect(m_DIBBack, 8 * (.x + c), .y + 16, 8, 8,
               CAPaper(m_BlockCA(0)))
End If
End If
Next
FXCrumblingBlock will not be shown here, because it's a pretty dirty function that mixes up game logic, tile animation and rendering engine commands. What I can tell you is that everytime it is invoked, it scroll downs the data of that specific tile, and insert a "blank" line at the top. Once this is done, it scans the whole tile again and sets the "cleared" flag (variable f) to false if it found any non-blank pixel. That's precisely what triggers transformation of B_CRUMBLINGFLOOR into B_AIR.

As the tile "crumbles" exactly one pixel per frame and Willy walks one pixel per frame, it means if you simply walk on crumbling floor, it will be completely crumbled when you're done walking.


Pour moi, c'est là que le bât blesse: FXCrumbblingBlock mélange allègrement rendu vidéo, manipulation des animations et logique du jeu. Je ne la reprend donc pas ici, sachez juste qu'elle décide si oui ou non l'animation est finie en parcourant les pixels qui viennent d'être édités. Si tous les pixels sont "transparents", c'est qu'il n'y a plus du tout de sol et on peut remplacer B_CRUMBLINGBLOCK par B_AIR.

Là-dessus, je vous laisse bras-dessous: il est temps que je prépare ma pitchounette à aller rechercher ma fée à Belle Ile. Ciao.

Monday, March 08, 2010

Turning a Dream into Reality.

I was somewhat fed up of the fairly "narrow" layout of Blogger. I grabbed a page and toyed with Mozilla Composer (or whatever name it has now) to optimise css "divs" for 1024 pixel screens. Then, I opened the previous "top banner" and started extending it. 

The banner's core idea was "turning a dream into reality" -- which is more or less what this blog is all about. Sketches show on the left, then pixel art and code lines so that environment builds up into a game. I thought the picture my Bros' shot would fit quite nicely the right of the "timeline".

It's a temporary banner, anyway. So feel free to comment items you like/dislike about it, and to answer the little poll. The "polished" 1024-pixels wide will at least replace old "double-pixel" art by something fresh at full resolution. Stay tuned. 

Je commençais à en avoir sérieusement marre du layout par défaut de Blogger où je ne sais même pas mettre deux captures d'écran côte à côte. J'ai donc profité du week-end pour mettre en place une petite expérience, élargissant la "zone de texte" à 640 pixels et le contenu du blog à 1024. Selon mes sources, aucun de vous n'utilise un écran plus étroit pour lire ce blog, de toutes façons.

Restait à mettre à jour la bonne vieille banderolle du mois d'aout 2007, et pour rester dans le thème "faire d'un rêve une réalité", je m'étais dit que, parmi les photos que j'ai, celle prise par CJ donnerait plutôt bien. Tout à gauche, le "monster design", tout en gribouillage ... puis du code et quelques pixels, et sur la droite, le jeu qui prend forme et vie sur DS. Qu'en dites-vous ? Ca reste une version temporaire, bricolée un peu à la va-vite, bien sûr. Je voudrais notamment remplacer Bilou(edit 11/03: c'est fait), le crayon et la souche en "gros pixels tout carrés" par des graphismes plus en phases avec mes dernières avancées, et à plein résolution (et c'est pas Gédéon qui s'en plaindra :). 

En toute franchise, ça risque de rester temporaire un moment ... A moins que l'un d'entre-vous ne veule mettre ses talents de webdesigner à l'ouvrage et me propose une banderolle alternative?.

Ah oui. Au départ, c'était le thème 'tic tac', en vert.

Saturday, March 06, 2010

Revoir le mode "debugging".

Je continue mon petit "tour de piste" de la todo list de l'autre jour ... Les collisions entre Bilou et les monstres ne sont pas tout à fait fiables. Si vous essayez d'assomer un appleman ou un woodworm en lui sautant dessus, vous avez un risque non négligeable de le "louper" et de vous faire blesser.
J'ai tenté à plusieurs reprises de "debugger" ça à l'aide de mes petits messages affichés sur le 2eme écran, mais sans grand succès. Et contrairement aux soucis rencontrés dans la gestion du sol, gdb n'est pas très utile non plus.

I need something to help me debugging collisions. Trial-and-errors allowed me to have woodworms stomped with sufficiently high probability, but stunning an appleman is still a pretty risky task. It's not that I haven't cared it, it's just that I miss the proper tools to investigates what happens. Dumping state changes on the console doesn't help because too many things occurs. I've got "step-by-step" system, but doesn't help either because it freezes monsters and only moves Bilou step by step. Finally, proceeding with gdb and ddd for a regular debugging session is helpless: problems are located in state transitions and collision area definitions, not in C++ code as with slopes and controllers.

D'où l'idée d'un écran spécifiquement prévu pour la mise au point du jeu, qui présenterait l'état actuel de Bilou, les différents contrôleurs, testpoints et zones de collision ... et les transition d'état qui y sont associées (event, fail, hit et found), les GOBs qui entrent dans la zone d'intersection, leur propres zones de collisions, etc. Chaque transition pourrait être "cochée" de sorte que le jeu soit mis en pause dès qu'on essaie de l'emprunter.

Je sens qu'il va être temps que je regarde comment fonctionne la commande "friend" en C++ ...

So I've been thinking about a specific game debugging screen that would show current hero state, active controllers and their "internal state", testpoints, collision areas. State transitions would have a special importance: each "item" that could trigger a state transition would list (a few) possible output states and the user (me ^_^) could then click them to force the game engine to enter debugging mode if that transition is attempted

Vous remarquerez peut-être que j'associe les transitions systématiquement à des éléments (contrôleur, test-point, zone de collision) ... c'est une des prochaines "refontes de code" à laquelle je dois m'attaquer ... la clé de voûte de la prochaine release. Aussi bien l'éditeur de niveau que le debugging et l'augmentation du nombre de monstres (et de types de monstres) en dépendent d'une manière ou d'une autre.

edit: j'étais ennuyé par l'entrelacement entre cette nouvelle fonctionnalité et tout le "refactoring" que je souhaite faire par rapport à la manipulation de la machine d'états. En fait, pour mettre au point les collisions, c'est essentiellement les zones de collisions qui m'intéressent, évidemment. Et pour elles, la liaison zone/transition est déjà une réalité. Je peux donc commencer par ça et ajouter le reste par la suite.

I've been concerned by the interleaving between this new debugging screen and the under-planning refactory of linking between controllers and transitions. But actually, it's something that can happen smoothly. The debugging screen can focus on "areas" first, and transitions due to "controller-generated events" can be added to the InspectorWidget after the refactory took place.
Oh, it will be my first time with C++ friend classes, too.

Friday, March 05, 2010

Flash Famous ... and then ?

You may wonder why I'm restricting myself on the Nintendo DS -- where a mere handful of players are going to enjoy my work -- rather than embracing Flash and reach millions (?) of gamers, possibly earning even just €.O1 from each of them, getting famous, got hired by a serious gaming studio and then getting rich. Especially when there are now powerful environment suited to chip-tunes-and-pixel-art such as the Flashpunk and flixel libraries.

If you do, I don't expect that whatever I could tell you about the magic of coding on the DS could enlighten you ... Instead, I'll say this: every single person I watch playing a drafty version of my little game is bringing me so much more joy than a pile of €.01 ... and the DS is just perfect for that. It has intuitive control, and I can carry it along with me everywhere.

Friends, friends of friends, nephews, step-brothers, colleagues and even EU project partners. They tried it. They failed or succeeded. We laughed. They asked questions and I answered them with as much enthusiasm as I did spoke of micro-engine programming during my PhD. Kids hanging around in my family are proudly showing their own drawing of Bilou.

That's not to say there will never be a flash version of Bilou. But if there is one, I think it will mostly be a short-cut demo that will be designed to draw attention to the polished product available for Nintendo DS (natively or on emulator, btw). Whether it will be even more retro by then doesn't care a bit.

Monday, March 01, 2010

Bug ou Feature ?

Bin finalement, ça n'aura pas été trop compliqué de bidouiller SEDS pour qu'il me permette de copier mon "fameux tile perdu" d'un fichier à l'autre. Enfin, dès que j'ai pensé à bêtement retirer la carte microSD pour placer le backup dessus en tant que SPRITEX.SPR plutôt que de m'entêter à utiliser runme pour un transfer par Wifi ^^".

SEDS-sheet-to-sheet-copy-1650Un fichier .spr est organisé en "feuilles" (les spritesheets), c'est à dire la zone de 64x176 pixels sur la droite de l'écran d'édition, et au début de la version 0.3, j'avais ajouté un mode "copie feuille-à-feuille" avec un second "viewer" indépendant. Tellement indépendant, qu'en fait, si je commente une ligne dans mon code, il devient capable de conserver les données (en lecture seule) malgré les chargements de fichier. Juste ce qu'il me fallait pour sauver le week-end.

Et pourtant, je ne pense pas qu'il serait judicieux de garder ça comme une "feature" dans la prochaine version de SEDS. C'est totalement contre-intuitif, et 9 fois sur 10, la spritesheet du fichier précédent est de toutes façon inutilisable parce que travaillant avec une autre palette. J'ai beau penser que "Si on ne sait pas le désactiver (à la demande de l'utilisateur), ce n'est pas une "feature" : c'est un bug!", cette bidouille serait perçue comme un bug puisqu'il faut "ruser" avec le programme pour le faire fonctionner normalement rien que pour bénéficier d'une option en plus.

The Lost Tile has finally been recovered with a fairly simple hack on SEDS. Funny enough: the "hardest" part was to transfer the backup .SPR file on the media card ... which turned out to be trivial as soon as I stopped trying to use runme for that purpose ^^".

The solution is based on the "sheet-to-sheet" copy feature that I introduced a while ago, and that allows to view two sprite sheets (those 64x176 pixels area SEDS edits) face-to-face once you press the "START" button. The second sheet is "so independent" from the file we actually edit that -- when commenting out one line -- it can preserve its contents accross "load file" operations.

Now, unfortunately, this is not a "feature" I can keep. For the end-user, it will definitely look like a bug! Just like you wouldn't call a "feature" of a word processor the ability of copy-pasting from two different files if that implies you only have meaningful text pasted when the two files use exactly the same set of fonts. I have a rule to distinguish a(n unwanted) feature from a bug: if you can't disable it, then its a bug. I can disable this one, so I'll do.

Click the picture and discover more of the "spriteset management screen" of SEDS on flickr.