Thursday, February 25, 2021

spr.more et sprdo

J'avais prévu de commencer par "Bon, ça commence à prendre forme", mais le temps que me mette à blogger, j'ai presque fini. L'idée est donc de montrer qu'il est possible de charger les sprites d'un jeu GEDS en deux fois, avec un morceau pour le personnage principal et un morceau pour les monstres, par exemple, histoire de pouvoir avoir des monstres liés à l'environnement traversé par notre personnage (comme dans quasiment tous les jeux assez longs).

Si je dis "les monstres" et pas "les blocs", c'est que dans leur cas, le fichier .spr contient aussi les animations, et que ces animations font directement référence à des numéros de page. Charger en deux fois, ça voudra donc aussi dire modifier à la volée les animations pour s'adapter aux nouveaux numéros de pages. C'est codé, mais pour le tester, il me faut des fichiers à fusionner. Or jusqu'ici, je n'ai pas énormément de fichiers .spr avec des animations. J'ai l'école, le personnage-easter-egg de la présentation de AnimEDS, peut-être un 'papa Noël' quelque part (mais où?) et peut-être un badman (mais où??).

Bref, j'ai fini par me dire que le plus direct, c'était sans doute de couper bilou+école.spr en deux fichiers bilou.spr et école.spr pour montrer qu'on pouvait les recombiner ensuite. Pour ça, ça m'a semblé utile de revenir sur un de mes outils de hacking de fichiers .spr: sprdo. Il s'agit d'un programme linux tournant en ligne de commande et qui utilise le même modèle de manipulation des .spr que le Sprite Editor lui-même. (mon collègue parlerait-il de code métier?). 

Un argument Lfilename.spr, et voici un fichier chargé. Un deuxième argument pk6, et on fait comme si on effaçait la page n°6. un p? et on voit des informations sur chaque page présente dans le fichier en mémoire. C'est un peu primitif, mais ça fait l'affaire.

Il fallait donc y ajouter une commande "montrer l'animation unetelle" puis faire en sorte que "supprimer la page unetelle" supprime aussi automatiquement les animations qui y font référence.

ça n'a pas été sans mal, mais j'y suis presque (reste à "nettoyer" les fichiers .spr de tous ces sprites qui n'ont plus de raison d'être, histoire de ne pas dépasser les 64K au moment de fusionner les deux. (normalement, j'ai déjà du code pour ça)

edit: on y était presque. Inkjet et les power-ups se sont chargés correctement. une partie de Bilou.cmd ausi, puis on arrive à une animation située sur la "deuxième page" d'animations avec Bilou (0311) et là bardaf: il n'y a plus personne. En compactant le spriteset les doigts dans le nez, sprdo m'a visiblement perdu certaines animations (la plus haute étant la n° 107 alors qu'il faudrait que j'aille jusqu'à la 129)

  • [done] use the right anim (the one using the right page) for the waves
  • [done] apply waves animation from the proper page (that also fix blinking of Bilou's limbs)
  • [done] pendat and blador use proper shared limbs page
  • [done] understand why the heal pick-up is gone
  • [done] proper animation when we pick up a bonus
  • [done] proper animation when we bounce on an eraser.



Thursday, February 18, 2021

github discussions / show-and-tell

 Je suis forcé de l'admettre: les discussions github, ça a de la gueule. On est vraiment très proche de ce que j'imagine comme idéal de présentation pour parler de développement. Mieux que mes tentatives de 'litterate programming', sans doute. Mieux en tout cas que le fait de devoir les accompagner d'un post sur un forum. Et mieux que ce blog (avec sa balise '<code>' et les liens vers les commits subversion / mercurial)

Si j'avais commencé avec github, avant que Microsoft (1,2,3) ne rachète tout je prendrais mon pied. Mais github est arrivé 2 ans derrière le blog, et mes tentatives d'utilisations de git n'ont pas franchement été très encourageantes. Ce n'est qu'en 2015 que j'ai délaissé SVN pour passer à Mercurial, poussé par les collègues au bureau. (Ouais, je suis pas franchement un 'early adopter' sauf quand je veux).

Il est probable que le fait de passer à github ne provoquerait pas franchement un afflux de collaborateurs ou d'enthousiastes: le ndsdev est devenu franchement anectdotique et le concept de 'faire des sprites dans le bus' risque de ne plus tenter grand-monde.

Il est probable que Microsoft ne fera rien de mal à tous les repos github, mais après l'abandon de Google Code, je ne suis pas trop tenté. Je préfère être hébergé par une organisation clairement dédiée à l'hébergement des projets open source (sourceforge) même si leur site web manque de réactivité.

Et puis malheureusement mon Boox ne sait toujours pas lire les certificats github. Bon, c'est plus un problème chez Boox que chez github, je le reconnais.

Plus important: qu'est-ce que je ferais de toute la partie "analyse de game design" ? Non, définitivement, ce n'est pas un candidat pour remplacer le blog. Par contre, le blog n'est pas le bon moyen de fournir de la documentation sur les outils, donc sans doute que les pages "manuel de l'utilisateur" seraient les bienvenues sur un github.

Monday, February 15, 2021

Your First Koopa ...

As I was enjoying my free week of Super Mario on Switch, I found it interesting to compare how we are introduced to Koopa Troopa mechanics in Super Mario episodes. Because, yeah, I'm fond of Koopas mechanics. 


Koopas are dangerous, but you can turn them back at their allies (same for dumbladors, you'd say). And you can dispatch many of them at once that way (unlike dumbladors) if you follow it closely enough. But then it can trick you if it bounces on a wall.

In SMB1, you're welcome to kick in and dispatch 2 goombas, then another 4 if you're running after the shell, but then it will bounce back at you. To some extent, your first experience with Koopa Troopa is the full experience. Dangerous/helpful/treacherous. You're warned: this is what the game has for you.

You'll have to clear about one half of that level before you can see your first koopa, though. And you can easily miss the only one of the level if you take the secret pipe.

SMB3 comes with something new for you. Koopas shells can now be used to unlock contents of question blocks that lay on the ground. This can be discovered from the very second screen of the first level!
 
Note how you can decide not to face it by sneaking under the green block or escalading the pink and white blocks to easily jump past it. Note, too, how the shell bounce on the question block may be harmless as it will be cleared out through that 'under green block' route, optionally dispatching a goomba. (That might possibly be a bit too much complexity packed into one first screen, but it surely offers you plenty of alternatives and replay value).
 

Weird enough, the first koopa in SMW is not in its shell. It falls towards you at the very start of the level, giving you only a few seconds to find the JUMP button. Its shell awaits you nearly half a level away, ready to let you discover you can kick things upwards. 

But we all know the real first level in SMW is Yoshi Island 2, where plenty of koopas await you, harmless unless you decide to face them, and a free shell ready to line them up for a free 1UP

When you do so, there is high chance that the shell will eventually slip past the edge of the screen and be discarded by the game engine. You're safe. pfewh. You'd have to race the shell for more than half a level before it eventually bounces on a solid stairs-like structure.

This, my friends, is the price to pay to have a 'first' level where you have no risk of falling into a pit before 3/4th of the level. 

Saturday, February 13, 2021

Higher Order Blog ...

Of course, it's been a long time since I first read the guide to implementing 2D platformers on the Higher Order Fun blog. I believe it's been part of my research on how people implement slopes together with the MC Kids talk on implementing sophisticated platformers on NES. So somewhere around 2007.

Un tout bon blog, qui continue à nous proposer des conseils pour implémenter un jeu de plate-forme 2D depuis facilement 2007, époque où j'ai dû le rencontrer pour la première fois. Mais en repassant dessus il y a quelques mois (magie Twitter), je me rends compte qu'il y a encore un bon nombre de fonctionnalités discutées que je n'ai pas encore implémentées dans mon moteur à moi (échelles, plate-formes dont on peut redescendre), et d'autres qui sont en cours de révision (pentes, plate-formes uni-directionnelles). Je repasserai dessus dans les jours à venir (j'espère)

There's still a number of topics I haven't implemented in GEDS that are discussed in that post, including ladders, refined slopes and one-way platforms. So I finally printed it all so I could take the time to read it quietly and take notes on what was neat and what needs more thinking. That was over 6 months ago.

So unfortunately, the toughts aren't fresh in my mind anymore. I'll have to read them back *too* before I can talk about it more.

The blog post presented different ways to implement a platformer. Tiles-based, of course, as it was de-facto technique used on virtually all 8-bit and 16-bit consoles that used tiles-based hardware (and still an efficient technique on page-flipping hardware), but also vector-based levels (only mentioned, though) and bitmap-based. I wish there was more being said about the techniques used with bitmap-based level modeling, as I believe it was the technique used in Fury of the Furries. 

Mais une particularité de l'article de Rodrigo Monteiro, c'est qu'il ne se limite pas aux jeux basés sur des tiles: il discute aussi le cas des niveaux modélisés par des vecteurs (Braid), à positionnement forcé sur des tiles (Prince of Persia, Flashback) et basés directement sur un bitmap (Worms). Et là, je trouve qu'il a peut-être été un peu léger en oubliant de mentionner Lemmings. Bon, d'accord, l'article est bien plus ancien que le talk de Mike Dailly présentant le fonctionnement (et l'éditeur de niveau :P) de Lemmings 1 et 2. Bon, on est d'accord: ni Lemmings ni Worms ne sont à proprement parler des jeux de plate-formes, mais ils restent en vue latérale avec de la gravité, et à voir la physique du personnage dans Fury of the Furries, je dirais qu'on pourrait bien en avoir un troisième.

I also know for sure it was used in Lemmings for levels up to 5 screens-wide (that would be about half the conventional RAM available on an IBM-PC, btw). 

Since the storage space on floppies was limited, levels weren't stored as a large bitmap, though: they were stored as a set of 'paint brush A at location (X, Y)' plus a set of (deluxe paint) brushes -- think of them as 256-color stamps The level editor calls them 'rocks' and reports how much are used so far. Some brushes may even be used as 'clearers' instead of 'drawers', exactly like what is seen in the New Super Mario Bros. level editor.

A true puzzle for those who later had to port DMA Design's success title to tile-based consoles of the time, if you ask me. But it allowed complete freedom that was precious to design appealing and challenging levels. Lemmings 2 was later developed based on an editor that aligns everything on a grid to ease porting to Nintendo and Sega (?) consoles, and while it had charming new themes, I never felt them attractive the way the original Lemmings were to me.

A noter que traiter la map comme un gros bitmap n'implique pas forcément de stocker la map comme un gros bitmap. En fait, pour la majorité des machines d'avant le CD-ROM, ç'aurait été tout simplement impensable même avec des niveaux de taille modeste comme ceux de Lemmings (5 écrans). Pour faire tenir tout ça sur une diskette, les gens de DMA design ont construit leur niveaux sur base 1) d'une palette de 'brosses' (des bitmaps de taille quelconque provenant de Deluxe Paint) et une série de commande 'ajoute la brosse A aux coordonnées (X, Y)'. L'éditeur permettant d'ailleur de garder une idée du nombre de 'coups de pinceau' utilisés jusqu'ici dans le niveau.

Bon, vous l'aurez compris, cette technique bitmap pour les données d'un niveau marche surtout bien pour les jeux où l'environnement est complètement destructible (chose qui devenait moins vrai avec Lemmings 2, prévu pour consoles 16-bit) et à un style graphique plus proche d'un Rayman que d'un Mario. D'une façon assez amusante (mais foireuse), c'est aussi ce qui était utilisé pour la version BASIC de Bilou's Adventures ;-)

Wednesday, February 10, 2021

Connection failed


 arf. Bon, le laptop pro que j'utilisais depuis mars dernier pendant les heures de bureau a claqué. Le disque SSD, plus que probablement, et sans espoir de récup pour autant que je puisse dire: les systèmes Linux ne parviennent même pas à initialiser le contrôleur et il n'est plus dans /dev/sd*.

Ce qui est dommage, c'est que puisqu'il ne s'agissait pas de matos à moi, je n'avais encore jamais fait de backup de ma VM 'machine à écrire' et que du coup, je suis reparti pour une installation d'une LTS ubuntu dans une virtualbox. Oui, encore.

Au moins, avec les package 'virtualbox-guest-dkms' et 'virtualbox-guest-x11' installés proprement par apt-get, j'ai un copier-coller complet, chose que je n'étais pas parvenu à mettre en route la fois dernière.

Rongtudju! Le nouveau laptop n'a pas de prise VGA. Heureusement, j'avais acheté pour mon NUC un petit adaptateur HDMI->VGA qui n'avait encore jamais servi. Le temps de forcer dans 'Advanced Display Settings' le rafraîchissement à 75Hz, et j'ai un second écran de nouveau d'attaque. Oui, parce que sinon, j'ai un signal tout pourri avec une image compactée sur 2/3 de la largeur de l'écran. Allez comprendre ...

Rongtudjuu! C'est assez facile d'avoir le réseau wifi et Internet accessible depuis la virtualbox: il me suffit juste de me mettre en 'accès par pont'. Mais le VPN depuis la VM ? ... Ah ? Configurer la première interface réseau en mode NAT a l'air de faire l'affaire... Par contre, du coup, je perds l'accès à mon WiFi. ça semble tolérable...

Rongtudjuuu! mais qu'est-ce que c'est que ce clavier !? Il est bien joli avec son métal entre les touches, mais pourquoi avoir piégé la touche "ENTER" de la sorte (avec un effet camouflage, en plus, hein?) Pourquoi avoir décidé que les touches F1-F8 devaient céder la priorité au contrôle de volume et de luminosité (on fera donc ALT+Fn+F4 pour fermer une fenêtre et fn+F5 pour rafraîchir une page jusqu'à ordre contraire!) Enfin, pourquoi oh grand pourquoi avoir mis sur une même touche des éléments de navigation comme home et end avec les touches F11 et F12 !? Voilà pourquoi je reste farouchement opposé à ce qu'on m'impose un laptop comme outil de travail quotidien. Ok comme solution temporaire. Ok pour bricoler un peu le soir, mais rongtudju, vu les décisions débiles et anti-codeurs que les gens qui montent des laptop prennent, s'il faut de toutes façons une docking station complète pour s'en servir, alors donnez-moi un NUC! -- un job pour https://github.com/randyrants/sharpkeys ? 

ou alors ...

 git clone https://github.com/Lexikos/AutoHotkey_L
F11::home
F12::end
Launch_App2::F11 ; calculator
<+Launch_App2::F12 ; LSHIFT+calculator.

 

RongtudjuUuu! après quelques heures de travail en musique, voilà que l'audio introduit du bruit dès qu'il y a un peu de charge sur le réseau >_< -- (fix: driver DELL mis à jour)

Saturday, February 06, 2021

2048 triangles

Cette histoire de Big Level Objects me turlupinait: est-ce que je ne fais pas le mauvais choix en laissant de côté le hardware 3D de la DS pour dessiner les niveaux ? Plusieurs autres homebrewers ont déjà indiqué qu'ils parvenaient sans trop de difficultés à gérer tout l'affichage d'un platformer 2D à coup de polygones sur la DS.

Bug! (1996) Saturn / PC

Given how natural "big level objects" are in 3D engines and how hackish they are in tiled-based engines, I wanted to give a second chance to the all-in-3D option. I know some homebrewers have succesfully walked to path opposite to that of New Super Mario Bros: sprite entities in 3D worlds that actually render 2.5D. Don't let yourself fooled: it's a tempting trip since the first screenshots of Bug! got printed in my favourite PC magazine.

A second tempting trait is that a 2.5D setup can make the "goal" of a level as clear as Journey's mountain. In a pure 2D platformer, you don't see where you're heading, hence the "walk to the right" stereotype.

Bon, je me suis laissé dire que les calculs pour que les graphismes tombent justes sont assez dégueulasses, ce qui a plutôt tendance à me refroidir.

Mais bon, en 1996, j'étais séduit par l'approche de la 3D par le jeu Bug! (en fin, au moins sur photo dans les magazines). Et depuis Journey, je dois reconnaître que voir dans l'arrière-plan l'objectif à atteindre, c'est une manière intéressante de travailler, tout en proposant un déplacement latéral pour les phases de plate-formes plus exigeantes. Sans doute que si j'avais vu la réalisation de Hercules, j'aurais poussé l'idée plus loin.

Donc, supposons que ... Qu'est-ce qu'elle a dans le ventre, la bête ? 2048 triangles. Ou 1024 quadrilatères (oui, on peut alimenter le chip 3D soit en triangles, soit en quads). Si on donnait un quad par tile à l'écran, il ne resterait plus que 256 polygones pour faire les personnages ou les particules. Pas énorme.

Fuzed by Relminator

One clear drawback is that the computations to get it right are ugly. Everybody who's been trying to do pixel art in Unity eventually says so, and I have no reason to believe it would be otherwise with NDS hardware. I don't mean the maths behind 3D projections here, but the setup to ensure that pixels got rendered as they are intended to, with one cell in memory exactly matching one cell on-screen.

But nonetheless, I looked up the "manuals". The NDS can render 2048 triangles or 1024 quads. That's 130% of  the number of 8x8 pixels tiles I've got on one _plane_ per screen. No doubt that if I go the 2.5D-with-GL path, I'll have to design levels with coarser objects (maybe not as coarse as Relminator's 32x32 pixels cubes), but thinking of some extra quads so that things are effectively 3D and not all flat might be necessary.

Now, to be honest, I don't really see Bilou fitting a cubical world like the one seen in Fuzed (or in Lemmings 3D), nor a origami-like world à la Mario 64. I gave that a try back in the Deluxe Paint days. Picking my best 'dirt' picture and soft-render it like if it was a Wolfenstein view. And to be honest, Badman 3 story that was rendered in a similar way look gorgeous in comparison.

Du coup, je m'attends à devoir travailler avec des objets plus larges, un peu comme ces cubes de 32x32 pixels comme on les voyaient dans le jeu "Fuzed" de Relminator. Là, avec un bon moteur on aurait 3 quads par bloc (5 avec un moteur minimaliste), et je compte un maximum de 62 cubes visibles à l'écran (donc 180 à 300 quads sur les 1024)

Bien sûr, si je veux aussi montrer une deuxième "couche", plus éloignées, les cubes seront plus petits, et donc plus nombreux.

3D made with Deluxe Paint for Badman.
Maintenant, il faut bien admettre un truc: ce genre d'esthétique toute cubique, ça n'a jamais vraiment été mon trip. J'avais fait un essai avec la fonction 'projeter une brush en 3D' de Deluxe Paint aux alentours de 1998 avec ma meilleure "texture" de terre pour refaire la cachette dans les racines de l'arbre creux de la green zone, et c'était pathétiquement catastrophique. Ça pourrait marcher un peu mieux avec la School Zone ou la pyramide, mais on devrait partir sur une esthétique plus proche de Phantom Hourglass (qui ne m'a jamais vraiment séduite non plus).

Bref, faute d'élément motivant, je reste gentiment avec mes p'tits tiles et mes p'tits sprites.

that would be 1024 quads. So we can fill the screen with 32x32 pseudo-tile and we'd have saturated the 3D pipeline of the NDS. 


https://github.com/AntonioND/nitro-engine

Friday, February 05, 2021

Programming Pitfall Harry

L'aventure racontée par 8-bit show and tell est presque surréaliste: un dévelopeur de jeu qui vous envoie un morceau de son code source comme ça, juste sur demande. Et pas n'importe quel développeur: le créateur de Pitfall!

Pitfall, pour ceux qui n'ont pas vécu ça, c'est ce qui se rapproche le plus du phénomène Super Mario Bros pour les possesseurs de micro-ordinateurs jusqu'à ce que Great Giana Sisters ne devienne facile à trouver.

Je m'attendais à un bouquin/carnet déjà costaud, du coup, en fait, la chose tient sur l'espace de menu de mariage. juste une page US letter pliée en deux, l'extérieur contenant un petit mot du créateur et des illustrations.

C'est un programme a priori typique de la "programmation système" en BASIC C64, avec plein de POKEs pour modifier des registres du contrôleur vidéo et des DATA avec les trucs à y mettre. Le machin bien opaque pour qui n'a pas un bon manuel pour décrypter ce qui se passe. En plus des DATA avec des sprites convertis en décimal, il y a un autre jeu avec du code machine pré-assemblé qu'on va aller POKEr dans un coin de mémoire pour pouvoir l'exécuter. (Là aussi, il y a un bouquin, mais c'est plus chaud).

Au final, on aura 'juste' le personnage Harry qui se promène à l'écran. Ouaip, je vois déjà les blasés du Scratch qui rigolent au fond, mais eh. 1) il est multi-colore. 2) il court (animation) et bouge tout à la fois. 3) il est grand. Rien à voir avec la démo-ballon du manuel C64, hein!

Et surtout, tu fais RUN STOP pour revenir à l'interpréteur BASIC, et le mec, il continue son footing. C'est le Mario-de-l'éditeur-de-Bisquit avec 25 ans d'avance!

En fait, on a pas ici une boucle BASIC qui anime et déplace: c'est un morceau de code machine installé juste avant le code qui fait clignoter le curseur texte qui s'occupe de faire bouger le personnage. Tout ça tenant dans le tampon mémoire prévu pour la lecture des cassette.

Pour se situer, le tape buffer utilisé dans le programme présenté dispose d'à peu près 200 bytes. A côté de ça, l'autre zone mémoire qui est disponible sans toucher au setup habituel pour faire du BASIC fait 4K et se trouve en 0xc000, juste avant les ROMS CHR et KERNEL.

Je ne peux m'empêcher de penser ... et si ... Et si au moment de commencer à travailler sur Logic Labyrinth j'avais eu accès à un petit programme de ce genre qui puisse déplacer un objet de manière quasi-autonome.

On aurait gardé un programme BASIC qui dessinerait la bonne salle et ajouterait quelques POKE pour chainer les uns derrière les autres character_interrupt, puis hshot_interrupt et walking_monster1_interrupt pour que les différents "personnages" de l'écran soient présents.

Ensuite, on aurait eu une boucle qui faisait de son mieux pour tester la position du personnage par rapport aux triggers du niveau et qui aurait fait apparaître ou disparaître certains éléments...

VRAM tricks used by Lazycow
Mais bon, mon seul contact avec le code machine du C64, c'était en 1997, 10 ans trop tard, et tout ce que mon bouquin proposait, c'était de charger un bout de code pour remplacer les caractères ROM par des caractères RAM histoire de pouvoir remplacer le T par un smiley.

Par contre, il faudra que je tire au clair cette histoire de 'VIC bank'. Quand j'ai commencé à écrire des programmes plus grands (pour Space Mission) mélangeant des tableaux de grande DIM(ension) et plus de sprites, je finissais par avoir mon programme qui provoquait des "erreurs systèmes", au point que le listing lui-même n'était plus garanti. Et si c'était simplement parce que j'écrasais des morceaux de listing avec mes POKEs ?