Tuesday, September 17, 2019

ImportsWindow::render()

Bion, la nouvelle garde-robe est installée ... j'ai eu un peu de temps pour regarder comment m'y prendre pour avoir les images des différents personnages du jeu sous le contrôle de la nouvelle "ImportsWindow" et en tracer les grandes lignes dans le code
[done] utiliser les ImportBlocks pour choisir quel état afficher où
[todo] mettre en place une matrice de scaling pour les éléments secondaires d'une ligne 'import'
[don't] sauver les noms ?

Saturday, September 07, 2019

272 sprite pixels / line.


Si faire une image sur DS c'est un peu comme monter une bibliothèque-étagère contre un mur, alors faire une image sur Super Nintendo, c'est pareil. Sauf que le toit est en pente, qu'il y a un conduit de cheminée qui dépasse, des poutres de toiture apparentes et une tablette d'appui de fenêtre dans le chemin.

Bref, il y a des contraintes à gogo et il faut tenir compte de toutes ces contraintes-là en même temps. Une qui m'a particulièrement perturbé, c'est la limite à 34x8 pixels de sprites par ligne horizontale en plus de la contrainte d'un maximum de 32 sprites par ligne (sur un total de 128 sprites, quand-même. ouf.)

En clair, la console a beau être capable de faire le rendu d'un sprite de 16x16 ou 32x32 pixels d'un coup, ça ne lui donne pas plus la possibilité d'utiliser les sprites pour faire une ligne de vagues couvrant tout l'écran (256 pixels) avec 8 sprites de 32x32. Enfin, si, mais vous n'aurez plus droit qu'à deux personnages sur la même ligne, et pas 24 autres sprites.

Je me suis donc mis à essayer de comprendre comment la structure du chip graphique de la Super Nintendo pouvait bien expliquer ça. L'idée de base, c'est que la console n'a qu'une bande passante limitée à sa mémoire graphique, tout juste suffisante pour aller chercher assez d'informations pour construire une ligne d'image sur le temps qu'une ligne de graphisme est tracée à l'écran par le canon à électrons. J'avais déjà appris que c'était vrai pour les décors -- c'est ce qui explique qu'on doive descendre à 4 couleurs par plans si on veut ajouter plus de plans -- reste à comprendre ce que ça implique pour les sprites.

Pour chaque pixel que le contrôleur du signal d'écran produit, il va falloir tester les sprites actifs et pour certains (peut-être chacun) d'entre-eux, il faudra regarder si le pixel correspondant est transparent ou opaque. Le premier pixel opaque dans l'ordre de priorité défini par le hardware gagne le match et les autres ne seront pas pris en compte. Ce genre de chose peut être réalisée efficacement avec un bus à collecteur ouvert et un circuit de contrôle des sorties de chaque unité "pixel pour le sprite S" dépendant du résultat des circuits précédents. Mais ça suppose qu'on ait, pendant toute cette phase de génération d'image, accès à l'ensemble des pixels de tous les sprites pour la ligne en cours.

La bande passante de la mémoire n'est pas suffisante pour aller regarder chacune de ces valeurs à chaque pixel, il faut donc supposer qu'il y a à l'intérieur du chip graphique un cache de 8 pixels de large (d'où le x8) pour chaque comparateur et que ce cache est rempli une et une seule fois lors du traîtement de la ligne.

Il me restait à comprendre comment ce genre de préparation est compatible avec des sprites dont on peut modifier la position en cours d'image. Et là, surprise: selon Upsilandre,

[...] Tu peux pas modifier la [Sprite Attributes Table] pendant l'affichage, ça veut dire pas de multiplexage software possible contrairement à la megadrive.

Le principe des sprites au raster c'est que les 34 patterns sont chargé en amont pendant le Hblank dans des registres internes. Ensuite c'est un jeu de priorité cablé dans le hardware qui va fait que tel pixel de tel registre aura la priorité sur les autres.

En arcade c'est mieux, t'as un (double) line buffer donc ils peuvent charger les pattern pendant toute la durée de la scanline précédente (et pas juste pendant le Hblank) c'est ce qui leur donne ces performances bien supérieur

J'aurais cru que la technique de multiplexage -- classique sur C64 ou NES et possible sur NDS -- était omniprésente sur console, et sur la 16-bit de Nintendo aussi. Visiblement non.

Et pour creuser un peu plus loin, les chiffres sont sur http://folk.uio.no/sigurdkn/snes/timing.txt. C'est un peu difficile d'en tirer un nombre d'instructions possibles par ligne retracée à l'écran, mais les chiffres annoncés me portent à croire que le 65xxx dont la Super NES est équipée garde une architecture interne très proche de celle du 6502, avec un bus unique entre les différentes unités internes et du "microcode" qui s'exécute à la fréquence de la master clock de la clock processeur mais qui peut nécessiter un nombre de cycles d'horloge variable (de 3 à 6) pour exécuter une instruction, ce qui donne entre 200 et 500 50 et 73 instructions par ligne retracée à l'écran.

On comprend mieux du coup les ruses de sioux du style "on ne va pas tester toutes les collisions à chaque images" qui régnaient en maître à l'époque..

Friday, September 06, 2019

Feedback in Iconoclasts

I've been playing a few shooting-based games lately. Iconoclasts, obviously, where you shoot, run, fight bosses, talk to NPCs and solve some puzzles. Flinthook, too, where you shoot, zoom through levels, shoot again, explore, die, repeat in another ship. And Owlboy, too. I'm ashamed I haven't posted anything about that one for so long, as I've been waiting for it since around 2015!

Bon, je ne suis pas grand consommateur de jeux-à-flingues en général, mais cet été, je viens de m'en faire quelques uns. Iconoclasts, bien sûr, qui mélange les traditions des run-and-gun avec ceux des castlevania pour donner une sorte de successeur de Cave Story avec une dimension RPG plus prononcée. Il y a eu ensuite FlintHook, mon premier roguelike qui m'aura bien tenu en haleine avec sa bande son sur-vitaminée. Puis Owlboy, plus zen sur le long terme et moins succeptible de m'envoyer à la pharmacie chercher de l'anti-inflamatoire que les deux autres grâce à son auto-fire. Owlboy aux graphismes superbes dont j'aurais dû parler depuis 2015, mais au gameplay améliorable.

And with the mix of all these, I start to better appreciate the way feedback information is conveyed in those games. I'll use Iconoclasts as an example of how it can be made right. Granted, they somewhat overdid it, but they allowed player to immediately know whether they picked the right action and to reduce the feeling of the game being unfair to them.


There are 3 main weapons in Iconoclasts plus a few alternate ways of attacking monsters. And frequently some monsters are vulnerable to some weapons and shielded against others. The feedback here is pretty simple: a small red skull moving away from the monster denotes a successful hit while a blueish cross indicates that the monster blocked our attack.

Ce mélange me permet de mieux apprécier les choix de certains jeux: parfois j'aimerais que l'un se comporte plus comme l'autre pour tel ou tel aspect. Et en particulier les choix de feeback visuel dans Iconoclasts qui me semblaient discutables montrent toute leur force de design tandis que je me casse les dents sur les ennemis de Owlboy.
Vous voyez, les explosions des armes de Iconoclasts sont assez impressionnantes. Peut-être à l'excès. Et elles pètent tout pareil que votre tir fasse mouche où qu'il ait été dévié par les défenses de votre cible. Heureusement, Konjak nous a prévu un petit symbole discret mais efficace qui évite qu'on ait l'impression que le jeu était vraiment trop injuste. Une petite croix bleue en cas d'échec, une petite tête de mort si on a "blessé" notre adversaire. On peut donc rapidement changer d'arme si on se rend compte que celle qu'on utilise n'est pas appropriée.

Cette convention est appliquée à l'ensemble du jeu, du plus petit blob aux boss les plus gros. D'une certaine façon, c'est une version plus rapide à traîter (parce que sans lecture) des chiffres et des statuts du genre "manqué" ou "blocage". Ça s'intègre mieux dans l'univers du jeu, aussi.

This convention is applied game-wide, from the smallest critter to final bosses, and they work even though most our shots create pretty huge explosions. To some extent, this work a bit the same way than the "blocked", "hit", "severe hit", "missed" etc. statuses and damage numbers  that got shown in action-RPG games, but more integrated into the game's universe by not requiring reading.

The last sort of such feedback is how some attacked are telegraphed to the player, namely those that must require a parry with the wrench. They are identified with a big green circle and small icons depicting rotating wrenches just before the shot. Again, it is applied game-wide, letting the player quickly react rather than requiring fail-and-retry learning with every new monster we encounter.

I'm not completely fan of that one, though. Although I agree with the idea, it is too obvious, and poorly integrated with the game's universe.


Par contre, il y a un type de signal qui ne me convainc pas. Ce style de cercle vert accompagné de petites icônes représentant une clé à molette qui tourne indique que l'ennemi correspondant est en train de préparer une attaque qui pourra être parée en faisant tourner notre clé à molette (normalement utilisée essentiellement pour activer des portes, etc.) ça m'a sauvé la vie dans plusieurs combats et c'est impossible à louper, mais on a un peu l'impression d'être dans un logiciel ludo-éducatif tellement c'est "Captain Obvious". C'est mieux que pas de feedback, mais tout juste.

Monday, September 02, 2019

Super Bilou ?

Because yeah, I can't help: the SuperNES draws me like a magnet. No matter how many times I refrain myself from looking deeper into it, I keep wondering how school rush would feel on the 16-bit queen.

But there is no easy answer. The SNES means only 128 colours for all 3 tiled layers. It means that either the ink or the owl must be patched to work with only 4 colours per tile. And it most likely mean that the twin playground layers of School Rush levels must be merged into a single one, with sprites automatically used where Bilou must enter objects like big binders.


Parce que oui, il n'y a rien à faire: la Super Nintendo exerce un magnétisme sur moi, et quelque soit le nombre de fois que j'aie décidé de ne pas m'attarder dessus, je ne peux pas m'empêcher de recommencer à me demander comment Bilou tournerait dessus. Après tout, le jeu a été conçu à une époque où les 16-bits régnaient en maîtres, et faire tourner le jeu sur une vraie machine 16-bit, ce serait la consécration. Et la Super Nintendo est à mon avis la seule machine grand-public qui serait capable de faire tourner un portage correct du jeu. La Mega-Drive et l'Amiga manquent tous les deux de couleurs ... puis je me vois assez mal demander à mon frangin de travailler sur une bande-son Mega Drive, même si l'assembleur 68000 est définitivement plus sexy que le 6502+ de la SNES.

Mais tourner sur SNES, ça veut dire tenir sur 128 couleurs pour l'ensemble des décors, retravailler l'encre ou le hibou du décor parallaxe pour qu'il ne prenne que 4 couleurs par tile, et autres contraintes de ce genre. Et ça veut dire aussi que je dois fusionner les deux couches de tiles en une seule, parce qu'il n'y aura pas assez de plans sans ça. J'ai bien tenté de faire l'encre avec des sprites ou une tranche de hibou en sprites pendant qu'on bascule un des décors du hibou vers l'encre, mais les ressources de la console en terme de sprites sont trop limitées pour ça. Ce n'est pas pour rien si les vagues des niveaux d'eau dans Sonic montrent un clignotement pair/impair ... mais je ne peux pas faire ça si je veux que l'encre ait l'air opaque.

But even with all those limitations, I feel like it would be the only mass-marketed 16-bit  that could host ports of the game. Both Mega-Drive and Amiga lack colours , and I don't feel like asking my bro to give Sega FM chip a try, even though 68000 assembly has more hex appeal than SNES 6502+ instruction set.

I tried other approaches, like using a row of sprites for the owl statue if the ink approaches enough, since there isn't enough sprite resources to implement ink waves as sprites as on the DS (more on that in a later post). But I had to come to the conclusion that merging the two layers into one is the only practical thing to do. So the next question is: how much overlap between layers is there in the levels of School Rush?

Voyons donc cette histoire de fusion. Ayant un niveau modeste en pixel art et un moteur de jeu basé sur un contenu quasi-statique de la mémoire vidéo, j'avais essayé au maximum d'éviter dans School Rush d'introduire des tiles qui seraient une combinaison de deux objets (un classeur à l'avant-plan et un morceau de bois à l'arrière plan). Au lieu de ça, j'utilisais deux plans verouillés ensembles tout en mettant les graphismes sur l'un ou l'autre plan selon les besoin. Avec le GPU sous stéroïdes de la DS (si, si), il me restait encore de quoi faire tout le reste. Ramener les deux plans sur un seul est possible parce que la SNES permet pour chaque tile dans la map de fixer sa priorité par rapport aux sprites. Reste à trouver des solutions pour afficher les superpositions. Du coup y en a-t-il beaucoup dans School Rush, et où sont-elles ?

I have fairly simple tilesets in School Rush, and used overlap to make object-bridging tiles. Merging means that these tiles now need new slots in the tileset. How many of these are there ? Can they fit the remaining space in the tileset or do I need to use virtual tilesets as I plan to implement in later versions of libgeds.

In most of the game, there is only a few tiles of overlap, in corners, often with green books or binders. These could either be done with overlay sprites or merged tiles. No problemo.


Les plus fréquentes proviennent des livres et des classeurs verts. Je dis 'fréquents', mais il n'y en a pas tant que ça par écran. Ce ne serait probablement pas pratique de construire une palette qui permette de combiner 'verts et mauves', une autre avec 'verts et bruns', etc. donc je m'orienterais probablement vers une implémentation avec des petits sprites 8x8 par-dessus le graphisme de la "couche" la plus distante de la version DS. Pas de soucis en vue ici.

Il y a ensuite une série de structures où la superposition n'est pas fondamentale pour le gameplay, voire parfois carrément accidentelle. C'est le cas avec la zone encadrée en bleu clair sur l'image ci-contre. Là une simple modification de la map suffira.

Viennent aussi les graphismes qui sont réalisés avec une combinaison de deux tiles plus simples pour des raisons de facilité, comme ce tube qui rentre dans le classeur, mais qui en réalité ne se coude pas et passe simplement par-derrière. Là, on pourra probablement se contenter d'un nouveau jeu de tiles parce que les version "simplifiées" ne sont pas utilisées telles qu'elles dans le niveau.

There are other locations where overlap allows to create sophisticated tiles with simpler ones -- like with the purple areas on the screenshot next. But in the level where I find these, the 'simpler' tiles aren't used anywhere else, so I could just have these in the SuperNES vram and that's it. Then there are locations where the level could be simplified to avoid overlap (like with the cyan area) without altering the layout of the play area.

Then there is the annoying areas. Those where we don't see parallax background layer with some wooden walls. They lead to a significant amount of additional tiles, especially given the complexity of that background (16 unique tiles). There isn't much else in these areas, hopefully. And not so many structure. Stacking sprites should work, but that makes more palettes needed. Alternatively, I would have to simplify the background texture locally and have a copy of those tiles with a simple, but opaque background.

Là où les choses se corsent réellement, c'est pour les "cachettes", ces passages du niveau où on est à l'intérieur d'un banc. Ici, n'importe quel objet qui n'est pas simplement rectangulaire introduit des nouveaux tiles. Et pour corser encore les choses, la texture de "fond de bois" prend facilement 16 tiles. On va avoir des combinaisons dans tous les sens si on n'y prend par garde. On risque de manquer de palettes si on essaie d'utiliser des sprites pour tout ça. Par contre, je pourrais essayer de faire une variante de ces tiles sur un fond opaque mais plus simple, et ajouter une variante des tiles de la texture "bois" qui permet la transition vers les objets. A condition que j'aie assez de place dans mon tileset pour caser tout ça.

Likely, the last, vertical level will be impossible to port to the SuperNES, and it is the reason why I started consuming the last 256 tiles of the 1024-tiles set.

So final move. Let's pick the latest tileset. Let's clear out all the tiles that feature only opaque pixels. Then let's clear those that are mirrors of each others (maybe not that wise, but there weren't so many of them). The result is about half the free room that not implementing the vertical level leaves. I can have two alternate (opaque) backgrounds of these. Or at least, I could if the SNES had 96 or 128KiB of video memory. But it only has 64.



Ce ne sera probablement pas le cas avec la version finale de School Rush et son niveau vertical qui introduisait justement plein de nouveaux tiles-de-raccord, mais si je m'en tiens aux 4 niveaux horizontaux d'origine, il me reste un bon quart (256 tiles) de mémoire disponible. Belote.

Maintenant, voyons un peu quelle quantité de mémoire représentent tous ces tiles qui possèdent des pixels transparents. On est dimanche soir, j'ai la flemme de scripter quelque-chose de pratique. J'y vais à la main comme un bourrin. Verdict: on pourrait faire tenir encore 2 à 3 copies de ces tiles-là dans un tileset de 1024 éléments. Rebelote.





Mais la Super Nintendo n'a que 64KiB de mémoire, à partager entre les graphismes des décors, des sprites et les "maps" (comptez 4KiB pour un écran qui scrolle horizontalement, 2KiB pour un arrière plan qui reboucle), et un tileset complet en 16 couleurs pèse 32KiB. Mon décor de hibou (534 tiles et 10 couleurs) est légèrement au-dessus des 16 KiB. Les techniques de "virtual tilesets" seront donc incontournables.

Tuesday, August 27, 2019

The last Inoxcrom

Ami du futur, archéologue, passant d'un soir, écoute et apprends. En 2000, nous étions capables de faire des stylo-billes parfaits: les Sierra Inoxcrom Fine. Ces bics avaient une finesse d'écriture incomparable, leur bille toujours prête à fonctionner impeccablement dès le premier traît - et même après avoir passé plusieures années ignorés dans un pot à crayons. Ils ne demandaient pas de forcer sur le papier et fonctionnaient aussi bien sur papier très absorbant que sur papier quasi-glacé. Cerise sur le gâteau, leur bleu n'était ni trop pâle ni trop contrasté.

J'ai écrit mon TFE, débuggué mon kernel pendant 5 ans, corrigé les épreuves de ma thèse et tous mes articles avec ces bics. Puis un jour, plus moyen d'en trouver nulle part. Et quand j'ai fini par essayer d'en télécharger sur Internet, la déception fut encore plus cruelle: la société a fait faillite en 2009. Ils ne reste que quelques lots dans des pays éloignés sans même la possibilité de les commander depuis l'Europe occidentale.

Pendant des années, je lui ai cherché un remplaçant. Je commence à apprécier les 'pilot frixion 0.5', mais ils n'ont pas la même vitesse de séchage et de tout-terrain qui me permettait de faire instantanément des diagrammes UML. Et je n'essaierais sûrement pas de les utiliser pour écrire entre les lignes d'un article prêt-à-imprimer.

Au delà du côté nostalgique et de mon incapacité à entrer dans une ère du tout-numérique, je trouve regrettable que ce savoir ait été perdu, qu'il n'y ait plus dans nos papetteries que du matériel de seconde zone et que les distributeurs ne s'en préoccupent même pas, puisque pour la plupart ils ne sont plus papetiers, mais vendeu·rs·ses-réassortisseu·rs·ses, ou gestionnaires de stock H/F.

Voilà donc. Je comprends qu'il soit ridicule de faire tout un papier d'un sujet si banal, mais il reste un espoir. Après 10 ans (dont les 3 derniers sans aucun inoxcrom), j'en ai finalement retrouvé un bleu chez mes parents. Il fonctionne impeccablement. Je l'ai juste relogé dans un corps vert parce que j'avais la fâcheuse tendance à les mordiller pendant que je cherchais mes bugs et que l'arrière de son corps d'origine n'a pas tenu le coup.

Monday, August 26, 2019

MonsterPropertiesWindow

At last, I've got a first working sketch of the 'monster properties window'. It turned out quite tricky to get it working. It can report whether gobs have links and initialization expressions in addition to tehir class. There still is plenty of work, like being able to actually update state when you use the widgets, and write an expression by using the customized 'TypeWord' widget featuring the full gobscript characters set.

Trickiness came from window-to-window communication, so that the right widgets got displayed at the right time (having to hide the whole "tileset" widgets)

Wednesday, August 21, 2019

a + b = idea


+
+
= idea.

Let's just use flowing sand in desert zone as a way to test the new tile engine ideas ...

Background: there is a strong motivation that keeps me working on the GEDS project nowadays, and revising all the things I'm revising rather than just calling it done: I'd like to be able to make things like riverflows that push player around. when I say "motivating me strongly", I mean I considered replacing the banner of this blog to show Bilou pushed by such a river on a slope. As I mentioned back in 2009, I like that this picture I see every time I visit my own blog to act as a reminder of the goal I set, by showing me something I'd like to see working when I play the game.

I was a bit annoyed that the level where I'd need such rivers and the tileset / game I'm working out these days were disjoint, but seeing the 'sand rivers' tiles of Sandopolis made me realise that they could be the perfect match for trying things here already.


Il y a encore des choses dans l'étude des moteurs de jeux de plate-formes qui m'intéressent suffisamment pour me garder accroché au dévelopement de 'libgeds'. Des mouvements style "corde ninja". Des rebonds sur les murs. Toutes des choses que j'espère bien voir figurer dans 'infinite pyramid', mon prochain projet.

Il y avait par contre un truc qui ne collait pas avec le thème de la pyramide: les zones qui forcent Bilou à avancer dans une direction précise. C'est le cas avec la rivière que j'aimerais introduire dans la version revisitée du niveau 1-1 de Bilou, à la placedu tapis roulant que mon frère avait dessiné en guise de passage à sens unique. Parce que cette rivière justifie la révision du système de "propriétés des blocs", en cogitation depuis le début de l'année.

Mais c'est bon. Je me suis retrouvé avec les méga-tiles de Sonic juste à côté de Bouli expliquant le nouveau système et ça a fait "a + b = i * d" : je n'ai qu'à mettre des rivières de sables (comme tout le monde?).

Pas oublier non plus les escaliers-qui-deviennent-des-tobogans du chateau gadget. Mais à condition que ce soit fun!