Thursday, April 29, 2021

UsingSprites was a mistake. Wasn't it ?

 While refactoring the animation editor, I tasted a new design pattern as an alternative to the usual Singleton pattern: the Using* anti-pattern. The idea was simple: for every item that needs to be there one and only one time, there is a class who has the sole responsibility for holding the variables describing that item. Let's take for instance the hardware sprites of the Nintendo DS. We have an array of 'sprites', an array of 'rotations' and a z-order list.

The Using* anti-pattern said "these 3 should be static members of UsingSprites, and any code who needs to access them (read or write) will derive from UsingSprites". What it guarantees, is that if something messed up with * global, shared state, then that something is in one of the classes Using*.

The one nice thing, is that code in those sub-classes can access the array quite directly: the location of UsingSprites::sprites is stored next to the functions that need it and it just needs a ld r*, [pc, offset] to be ready to use it. No additional pointer dereferencing required. This is the very same as accessing e.g. the address of a constant string (ARM thumb code doesn't seem to have mov reg, imm32 instruction).

What I hadn't foreseen when I decided to generalise that to the whole game engine, is that a) there would be so many Using* for simple classes such as an animation and b) that they would all introduce a virtual table where the pointers to virtual methods for that class are stored.

The issue with that is that when you have multiple inheritance, you need one vptr (pointer to a virtual table) per super-class. That means every GobAnim instance must dedicate 5 full-sized pointers to virtual tables in addition to the 'real' data of the object.

Hopefully, it turns out to be a worst-case. GobState has 4 superclasses and most of the state-machine only one or two.

When looking at that inheritance graph again, I wonder if Using* is the right one to blame. iReport is there just to bring action/step/report/diagnose functions into the local namespace, but they are actually just static functions manipulating no particular state. Same goes for iAnimUser. iReport is so omnious that it could really be dropped and the functions just promoted to global namespace just like printf. iAnimUser could just be a namespace and not mess up with the inheritance, as it just provides constants and helper inline functions with, again, no dedicated state.


Wednesday, April 28, 2021

Le journal de Link: Remontant l'Endurance ...

Grimper à une tour, en repérer une autre, sauter en paravoile puis tracer son chemin à travers tout jusqu'à la-dite tour... escalader. Reconnaître les alentours. Recommencer. ça peut paraître répétitif, mais je n'ai rien ressenti d'aussi grisant depuis que je me suis réveillé.

Bon par contre, au niveau de l'escalade, j'avoue que je suis un peu rouillé. Je tiens bon à coup de potions, mais clairement, je manque d'endurance.

Dire qu'il y en a qui préfèrent les îles mystérieuses et leurs temples perdus. A moi les grands espaces, les chaînes de montagnes à la beauté sauvage où l'on peut tracer pendant des heures sans rencontrer âme qui vive. J'irai de sanctuaire en sanctuaire, triomphant d'épreuves sans nombres jusqu'à ce que la Déesse entende ma prière et me rende ma force d'antan.

Bon, la dernière m'a donné encore plus de fil à retordre. J'avais repéré un bel angle d'approche qui ne m'aurait demandé que quelques instants d'escalade. Malheureusement, dès que je m'en approchait assez, c'était la drache. 

En cherchant à trouver un autre moyen, je tombe sur un Prince Zora. J'ai dû me faufiler en terrain inconnu à travers des lézards cracheurs d'électricité pour trouver leur ville, puis me faufiler au sommet des montagnes ruisselantes jusqu'au repaire d'un Lynel géant pour lui voler ses flèches-éclairs, après quoi on affronte avec le prince une machine géante en folie dans laquelle se trouvait un démon ténébreux. Il a beau être tout sourire, je trouve que les catastrophe s'enchaîne un peu trop aisément pour être naturelles quand il est dans les parages, le Prince... et tout ça sans savoir où je mettais les pieds, évidemment. Je commence à croire que les tablettes nous ramollissent la cervelle et qu'on devient incapables de se débrouiller des qu'elles sont en panne. 

Hyrule et sa fille on peut-être eu raison de faire en sorte qu'il n'y en ait qu'une seule pour tout le royaume, après tout...

Monday, April 26, 2021

pyramt.map

Files transferred. Last week, I had just complete mess of tiles, some even not part of the file, but things remaining from the previous level. Hopefully, each of these level worked fine in the level editor on the NDS.

With a bit of tweaking, I could also get the shown in runMe. After I remembered I had a button to show the loading log in case of failure, I realised I had a few files missing (mostly .gam files) and I could get school title screen working with sprites as well.

But as far as pyramids and green zone maps are concerned, I'm still trying to get them working. Dreams.nds itself triggers a blue screen somewhere in GobAnim::translatecommands.

Avec un peu d'astuce, je peux maintenant avoir un niveau "pyramidesque" dans l'éditeur comme dans runMe. Pour runMe, il aura fallu que je me souvienne d'activer l'affichage du log (parce que oui, il est toujours là, juste caché), histoire de réaliser que la DS n'a pas le fichier .gam demandé. L'éditeur de niveau peut passer par-dessus un problème de ce genre, mais pas le moteur de jeu. 

One thing, though. It's nice to have a memory crawler embedded into my exception handler, but I should make sure it doesn't trash the precious registers I had on-screen when I'm exploring invalid addresses (first, because it is impossible to hop from 0x0b00xxxx stack addresses to 0x020xxxxx heap/code without entering some invalid addresses, and second because moving down to higher addresses makes the DPAD to enter addresses confusing at best)

Tuesday, April 20, 2021

Le journal de Link : j'ai cassé ma hache T_T

C'était une belle hache, en plus. Le premier truc tranchant que j'ai pu utiliser pour me défendre contre tous les *oblins qui infestent ces régions. Sans elle, j'aurais dû étourdir un boko à coup de feuille de palmier jusqu'à ce qu'il perde son arme ? Et si je l'avais cassée à force d'abattre des arbres avant de penser à couper des feuilles ? Je n'ose même pas y penser ...

Tout ça, c'est la faute des rochers vivants qui trainent dans les monts géminés ! tu fais une approche furtive pour augmenter ton stock de viande de moufflon (revenu au beurre de Coccorico avec des champis sautés et des sauterelles enduro. Une tuerie! Passez un coup au village, je vous ferai goûter ça). Eh bin paf! avant que t'aies eu le temps de lancer ta première flèche, c'est le rocher derrière lequel tu restais planqué qui sort de terre et qui s'acharne sur toi! Et attention, hein, je ne vous parle pas d'un p'tit caillou du genre de ces cracheurs de noix qu'on peut voir dans les plaines en bas du Plateau du Prélude, hein! Ce truc fait bien deux fois la taille d'un centaure.

Qu'est-ce que vous auriez fait vous ? Bin j'ai décampé, évidemment. En jetant un oeil en arrière pour m'assurer que je le semais. C'est comme ça que je suis tombé sur un camp de goblins des montagnes que je n'ai pas pu approcher par surprise. 

Je me suis retrouvé à devoir me battre la tête dans les buissons et j'ai démoli mes épées. Une autre rencontre du genre un peu plus tard, et c'est la lance de soldat que j'avais troquée contre mon javelot au pied d'une tour sheika qui part en échardes. Elle était pourtant bien pratique quand les goblins arrivaient les uns après les autres sans pouvoir me lancer des trucs dessus.

J'avais espéré me refaire un stock au village Coccorico, mais ils n'ont que des légumes, ces gars-là! Il y avait bien un sabre antique dans le temple d'entrainement au combat, mais il n'a pas tenu le coup, le temps que je comprenne la théorie des esquives, vous pensez bien. J'avais aussi espéré tomber sur l'une ou l'autre cachette d'arme dans les ruines sur la route de l'Est, mais je suis surtout tombé d'embuscade en embuscade jusqu'au moment ou j'ai dû choisir d'affronter un Moblin géant soit avec ma hache, soit avec cet espèce de crochet que j'ai pris à l'assassin qui m'attendait à la sortie du village d'Impa.

J'ai pris ma hache. C'était elle ou moi.

Allez, tout n'est pas perdu. J'ai toujours cette lame lumineuse. Elle est réputée pas très solide. On verra bien.

Ah, du coup, je n'ai plus non plus l'épée rouillée suspecte que j'avais sorti d'un rocher au milieu d'un lac du Plateau. Tant pis pour l'Histoire.


Mais ?_? Mais ?__?


Sunday, April 18, 2021

Dreams/efsroot/*

Premiers pas vers mon objectif des trois "téléporteurs": j'ai une structure capable de produire un .nds qui comporte aussi bien les graphismes de la school zone que ceux de la green zone, avec un bilou.spr partagé entre les deux et la possibilité de passer de l'un à l'autre pendant un chargement de niveau.

Bon, j'ai eu droit à mon compte de p'tits bugs pendant que j'ajustais les pages de sprites à utiliser pour les monstres de la green zone, évidemment.

Et si une grande partie de ces défauts sont maintenant corrigés, il reste quelque-chose de travers avec la gestion des palettes. Pour la school zone, bilou.spr et school.spr contenaient exactement les même palettes, mais green.spr en a une autre. Et essayer d'afficher les applemen avec la palette des pendats donne des résultats pas tout à fait esthétiques.


Le journal de Link : de la venaison pour mon doublet

 

Quand la déesse du temple en ruine réclame la même chose que le vieux barbu bizarre en échange de son paravoile, on finit par se dire que c'est un signe du destin. Du coup, je me suis mis en chasse des sanctuaires sheika même si je préfèrerais perso essayer de comprendre pourquoi je continue à entendre la voix de mes rêves pendant que je suis éveillé.

L'ennui c'est que les autres temples sont du côté des sommets, et que ça caille sérieusement, par là. Avec ma chemise centenaire, je ne tiens pas 2 minutes. J'ai l'impression d'avoir déjà révé quelque-chose de ce genre, où je partais vaillamment, la torche à la main, allumer un feu de camp le long de la rivière pas-assez-gelée, puis un autre, puis lacher ma torche parce qu'un monstre apparaît, occire le monstre en caillant, retourner rallumer ma torche, reprendre des forces, repartir ... Sauf qu'ici, ça ne m'avancerait pas: je serais de toutes façons coincé du mauvais côté de la rivière.

J'ai croisé une cabane avec un vieux livre de recettes au piment, ce qui m'a rappelé un autre rêve, ou je me cuisinais des plats toujours plus épicés pour tenir face au froid, puis j'errais dans les montagnes à la recherche d'un sanctuaire, puis je n'avais plus rien d'épicé à manger pour rentrer et je mourrais de froid et de faim.

ça devait être un rêve prémoniteur: je crois avoir trouvé la cabane du vieux barbu bizarre (qui fait une fixette sur les recettes pik-pik) dans laquelle il y a des piments. J'essaierais bien de lui tirer les vers du nez, mais je ne comprends pas grand-chose à son charabiat. "doublet" ... "venaison" ... je ne me souviens pas qu'on parlait comme ça avant mon grand sommeil. Bon, j'avoue que je ne me souviens pas de grand-chose d'avant mon grand sommeil, non plus. Mais j'ai l'impression que si j'arrive à faire la recette qu'il a oubliée, il me donnera un truc utile.

Friday, April 16, 2021

vu sur dev-fr... il y a longtemps

dev-fr.org ... le site web que je regrette le plus (vu que Nectarine est re-là de nouveau ;). J'ai retrouvé pas mal de monde sur twitter, mais ce n'est pas vraiment la même chose. Il est rare de parvenir à avoir la même quantité et qualité d'interaction à propos d'un nouveau projet ou d'une mise à jour. Et j'ai toujours cette impression d'y être un marchand-ambulant plutôt qu'un villageois membre de la communauté.

Enfin, il y a heureusement la machine à voyager dans le temps: archive.org ... On ne retrouve pas tout loin de là, mais quand-même de quoi reconstruire certaines pages aux liens cassés ou aux images perdues.

There was something I loved about the forums era (and the dev-fr forum especially), is that they made me feel like I belonged to a sort of nice village with people I somehow knew. Despite I managed to find many former fellows of dev-fr on twitter, it does not feel the same. More like I'd be a peddler. Both amount and quality of exchanges are far from being as satisfying as they were.

And it hurts even more that dev-fr website is defunct, not just forgotten. But at least, there's the archive.org time-machine to find back some of the discussions we had, like Apple Assault or school zone "launch". And even a french tutorial for LEDS. (got to capture all that once for all so they're not blocked by the firewall anymore)

 ça me permet de retrouver la présentation originale d'Apple Assault ou de la première démo de la School Zone. Ou à des fins plus pratiques, le tutoriel français de LEDS.


Saturday, April 10, 2021

spr.more in Level Editor

 

ça n'aura pas été simple de recommencer à avoir des représentations des monstres correctes dans le Level Editor. J'aurais probablement dû utiliser mon "autoexec.nds" pour le coup, mais j'ai procrastiné ça en insistant que 'nan, mais j'y suis presque, là'. J'aurais aussi eu plus simple si j'avais eu un affichage de la VRAM 'brute' dans mon émulateur, mais je n'ai pas encore ça non plus. Ou éventuellement un 'print' qui se mette à jour d'office.

Là, j'ai pu corriger pour que spr.more ne perturbe plus le chargement du 1er spriteset, mais je dois encore chipoter pour le 2eme. Je pensais que c'était lié aux arguments de la commande, mais en réalité, ils n'ont pas d'impact si on ne joue pas les animations.

Mais les dernières ruses que j'ai dû déployer pour que ça fonctionne (notamment un champ additionnel 'meds+%d') me mettent un peu mal à l'aise. J'ai l'impression que c'est le signe que le mécanisme spr.more n'est pas au point et demande de trop connaître son comportement pour pouvoir s'en servir.

edit: près d'une semaine plus tard, je finis par mettre le doigt sur le dernier problème. Une commande destinée à introduire une animation pour 'SimpleGob' dont j'ai changé la syntaxe dernièrement sans penser à changer la syntaxe aussi dans le parseur de l'éditeur de niveaux.

Donc, l'éditeur de niveau est prêt (mais pas encore uploadé), l'éditeur d'animations est prêt aussi (allez, je les uploade tous les deux sur le cube), les fichiers .spr sont corrigés (sur la DS aussi, je crois) ... On dirait que je vais depouvoir commencer à faire des maps pour Dreamland ?_?

La bonne nouvelle c'est qu'au passage, j'ai doté cmdck de nouvelles fonctions pour me montrer le contenu des tables régissant ces vignettes sans devoir faire appel à l'émulateur (?thumbs, ?page, ?states)

Thursday, April 08, 2021

Retro Game Dev

My brother got me a copy of Derek Morris' book on C64 game development. It is more or less a printed tutorial to his studio-like application that features code editor, resource packer, Commodore emulator and C64 graphic editors. I haven't managed to run that in WINE so far, unfortunately, but reading the book was already quite interesting.

One nice thing is that the games discussed in the book are programmed in assembly language. So we can skip the usual PEEK and POKE things and start straight with the main meal. I'd love to be able to say that the libraries that come with the studio let you focus on your game logic without having to figure out how to pull joystick state and push tiles into graphics memory, but the reality is that it adds a layer of confusion instead of abstraction.

Things like Screen_SetColors or Sprite_SetFrame are understandable and generic enough, but the "particles system" using special background characters to emulate more sprites would have been nice to see discussed in the book. Same goes for a few more key algorithms like map update after something got picked up, played monster collision, and the like.


A défaut de la démoparty espérée pour mes 42 ans, mon frangin m'a dégotté un bouquin sur la programmation de jeux pour C64. Il faut dire qu'entre Wolfling, PowerGlove et Relentless, mon frangin avait eu le temps aussi de cogiter à une adaptation de Spector sur C64 (mais bon, lazycow a finalement remis le couvert avec le chapitre II de Wolfling). J'imagine que ça pourrait être un appel du pied.
Le côté intéressant, c'est que le bouquin ne s'embarasse pas des PEEK/POKE bien connus de ceux qui ont essayé d'aller plus loin que le PETSCII en BASIC: ici, on code en assembleur. Enfin ... d'une certaine façon.
A côté du bouquin, Derek Morris nous propose en effet un "studio" pour windows, avec éditeur de salles, de sprites, de tiles et compagnie et une série de bibliothèques de macros pour pouvoir commencer son petit titre sans devoir se farcir les détails techniques de la programmation hardware de la bête.
C'est sympathique (et plus gamejam-friendly), mais ça transforme aussi une grande partie de la lecture en une sorte de visite-guidée-faites-moi-confiance où ira rarement plus loin avec l'assembleur qu'une petite augmentation du score ou une bidouille de la vitesse, parce que le reste se situe généralement à l'intérieur d'une macro qui n'est pas reprise à l'écran. Pour celui qui est curieux de savoir comment les tirs, les collisions ou les mises à jour de maps sont gérées, bin il faudra ouvrir le .zip parce que ce ne sera pas dans les pages.

Ah, par contre, sorry frangin: la gestion des musiques de fond, c'est aussi réservé au tome 2.

It is also a bit disappointing that the "engine" is only capable of scrolling 1/3rd of the screen, and thus the "platformer" example looks more like a simplified Wonder Boy title than the Great Giane Sisters.
60-fps full-screen scrolling requires page-flipping and interrupts, says the last page. It's a starter kit, in a sense, not a PhD thesis on Wolfling-like guru techniques that would push the limits of the machine. Well, I guess starter kits are good to have too, aren't they?
Now ... maybe for game jams ...Yes, I think that could be a good setup for an 8-bit game jam. 
 
edit: j'étais étonné de voir des macros un peu dans tous les sens dans le bouquin, et en particulier des macros qui font des appels de fonction ... un tweet vient de me faire comprendre pourquoi: sur 6502, on va devoir se souvenir du "protocole" d'appel de chaque fonction, qui n'a rien à envier à celui des appels systèmes MS-DOS. Si on a pas envie de se souvenir "mets la destination dans X, la source dans Y et la longueur du bloc à copier dans l'accumulateur", on peut se faire une macro qui prendra 3 arguments "simples" (disons une constante ou un nom de variable) et qui prépare l'appel à la fonction block_copy. Ce sera plus flagrant encore si on doit accéder à un chip externe avec un protocole du style "écrit le numéro du registre vidéo à l'adresse $8000 puis la valeur en $8001. Recommence ensuite avec la coordonnée Y que tu mettras dans le registre vidéo suivant".
Par contre, suivant le conseil de Mario Nesrock, on garde ses macros dans les sources principales (on ne les planque pas dans un .zip) et on les garde courtes (sinon gare à la taille de sa ROM).

Zoink/Fe

 Si vous vous demandez à quoi pourrait bien ressembler Ori en 3D, vous pouvez toujours essayer le jeu Fe de Zoink! studio (2018). Au niveau du gameplay, on est sur quelque-chose d'assez proche avec de l'escalade, du transport et du j'me-faufile-incognito (mais pas franchement de l'infiltration pour autant). Par contre, oubliez les techniques de ninja spiritique de 'Will of the Wisps', hein: on est plutôt sur un 'Ori Zero Mission' où on a même pas d'attaque et où il faudra faire s'affronter les créatures présentes dans le jeu entre elles pour parvenir à ses fins.

Visuellement, c'est très réussi, et ça me confirme que le 'low-poly' est tout à fait capable de me plonger dans un univers alternatif. Par contre, avec cette vision monochromatique et ce personnage tout noir capable de se tapir dans l'ombre, on est à l'anti-thèse de la lisibilité d'Ori. J'avais déjà du mal à m'orienter dans la première phase du jeu, mais quand j'ai commencer à me frotter à des monstres-piégeurs, je me suis retrouvé aussi mal embarqué que lors de ma dernière partie de Quake. J'ai fini par jeter l'éponge et regarder un let's play pour voir quel trajet prendre et m'y lancer 'en aveugle' tant il était impossible de voir à la fois mon perso, la trajectoire à prendre et le danger sur le même écran.

La musique est du grand art orchestral, quelque part entre celle de Gris, Hob et Ori sans toutefois être aussi 'iconique' que cette dernière. Il faudra que je partage ça avec ma collègue 'Sparkling' quand on sera de retour au bureau...

Un des éléments fondateur du jeu, c'est l'interaction avec les NPC. Ici, elle nécessitera au préalable de s'être "synchronisé" avec eux à l'aide du bouton "chanter" qui permet aussi d'interagir avec le monde de manière générale. Un peu l'équivalent du SAISIR/LIRE/PARLER des Zeldas post-OOT.

Ce qui est amusant, c'est qu'il y a quelque-chose d'un peu similaire dans Rime (moins mélodieux), dans Journey (les vagues d'énergie) et dans Gris (même si ça vient nettement plus tard dans le jeu). Et il y avait une mécanique un peu similaire aussi dans Juju & Peyo, même si son usage se rapprochait plus du "souffler les bougies" de Donkey Kong Returns.

Bref, une expérience sympathique mais qui ne me convient pas autant que hob, charmante mais pas autant qu'Ori (le p'tit elfe a une tête un peu flippante, quand on le voit de face, il faut dire ce qui est) et dans laquelle j'ai l'impression d'être perdu dans un monde immense plutôt que de ressentir l'excitation de l'explorer.


 



Saturday, April 03, 2021

Where are my thumbs ?

I'm trying to add support for spr.more in LevelEditor (so that we keep seeing monsters positioning while editing DreamLand maps ;) but it doesn't work well. After some debugging, I realize that the values for the 'animation number' stored in the first word of the 'TINY' section make no sense. Animation #17000 ? with 48 animations per sheet ?

A simple test with ./sprdo confirms that even if I just load-and-save a file that has meaningful thumbs numbers, we end up with bogus numbers in the saved file.

Still wondering what thumbs I'm talking about ? They are still 32x32 images produced while saving animations in AnimEDS that are then used in LEDS for monsters edition.

Watching the memory backing my vector through execution, I finally found a suspicious set of `free()` statements at the end of the 'extra/unknown data blocks to set of MEDS animations' function.

The history of that function is that it abstracted something from `spr.load` script statement so that `spr.more`can exist. When it is done with them, the GameScript used to dispose of remaining really-unknown data blocks. Such as thumbnails. They won't be needed while we play the game and they eat up significant amount of memory.

Then, there was the code of SpriteEditor, the FileModel, to be precise. It had been updated so that it could invoke the same sort of 'FromExtras' function, but since we're not interested in MEDS animations while editing sprites, template magic makes this whole function unused. And then is the new tool, that tries and use code meant to be for GameScript but in a load-modify-write setup. That one ends up with freed pointers in its array and then try to save back those opaque data in the file. This is where my 17000 comes from.

The perplexing thing is that AnimEditor itself doesn't seem to read back the TINY thumbnails, but still when I load a file from OtherFileWindow, I get no thumbs on my top screen. Not until I edit something and move to another page, that is.

It took me time to check everything, and it finally revealed that, yes, makeThumb() are properly invoked even for OtherFileWindow, as soon as we call MetaWindow::data_reloaded() to signal things were updated. But the setup ThumbsWindow::restore() installed to show and use the TileTable showing the thumbnails got screwed up by OtherFileWindow's default layers settings. forcing a call to THW::restore() within data_reloaded finally fixed the issue. So that means bilou.spr on lime DS is likely fine and I can download it to resume development of LevelEditor's support for spr.do ^_^ (erhm. Next time. It's quarter-to-midnight and I've got meetings tomorrow ^^")

edit: unfortunately, after retrieving bilou.spr and school.spr that had been edited by AnimEditor on the NDS, they still contain rubbish TINY sections... I'll have to work on a medsdo tool to study that...

Friday, April 02, 2021

Ma première forteresse.

On est toujours dans Badman 2, mais cette fois après que Piek m'ait proposé de faire un boss. Les possibilités du GameMaker étant ce qu'elles sont, le même ennemi 'boss' va être ré-affronté à 6 reprises dans des 'arènes' de plus en plus exigeantes. à chaque fois, il nous livre une clé qui permet d'ouvrir la 'porte-ours' rouge suivante.

Ce qui m'intéresse le plus, aujourd'hui, ce sont les 'mini-challenges' placés entre les arènes. Le premier fait appel à la mécanique 'pick up' utilisée jusqu'ici pour se saisir de power-ups, mais qu'il faudra utiliser pour ramasser l'échelle dans son inventaire et ensuite la déposer sur un autre bloc.

L'échelle est simplement un bloc sans gravitation, ça aurait pu être utilisé à plus d'endroit dans le jeu, mais ça n'a rien à voir avec le gameplay run-and-gun du reste de Badman.

Badman 2 could have been the game where I designed my first level-with-a-Boss: the badboy Burner. We'll meet him 6 times in the level, everytime in an arena that's a bit more difficult to survive than the previous one. You can see them in the top row of the level map. But let's focus on the trials we'll encounter in-between. The first one is just a tutorial on how to use the 'ladder' pick-up block (well, it'd have been a tutorial if you'd had any hint that you can pick that up, and not only the power-ups like the badarang)

Le deuxième passage fait appel à une variante d'échelle qu'on emporte pas. C'est dessiné comme des chaînes, mais en réalité, ce sont juste des emplacements où il n'y a pas de gravité. Si on parvient à y arrêter Badman, il aura l'air de marcher dans le vide.

Le deuxième mécanisme "unique" de ce niveau, ce sont les blocs qui rentrent et sortent du décor. Des plate-formes temporaires, en somme, qui ont été introduites dans le premier écran (pour récupérer de Badarang), puis servent de 'porte-temporisatrice' après le premier boss, mais là, on va commencer à les utiliser comme un vrai challenge, avec une alternance entre deux position de plate-formes qui nécessiteront de bien synchroniser ses sauts. (Bon, il y a 6 à 10 étapes intermédiaires de 'fade' où les plate-formes sont solides simultanément, donc ça reste gentil par rapport aux arbres de Gris).

C'est bon ? c'est bien rentré ? parce que juste après, je vous ai mis un loooong pont par-dessus les pics qui utilise une série de blocs disparaissant les uns après les autres. Il faudra être rapide et ne pas hésiter.

The ladder is pretty minimalist in RSD game-maker: it's simply a block where gravity does not apply. But it gave me the idea to draw 'hanging chains' that area also just gravity-less tiles. I guess navigating them with Badman's moves is closer to a bonus room (if there had been bonuses) than to a trial room.

The next one is the first real challenge, with blocks that fade in and out. Not that it will really stress your dexterity and timing skills, since both fading in and fading out blocks are simultaneously solid during the whole (fairly slow) animation. But immediately after, you'll get a super-long bridge of such blocks where you'd better ne quick (=jump) and steadfast if you want to make it to the final door.

And while we're in the 'bridge over spikes' theme, the next one uses falling platforms. That one is shorter, but the falling platforms are a side-effect of gamemaker's collision rules and tends to bounce you or let you fall through them.

Et puisqu'on y est, vu que j'avais découvert comment faire des plate-formes qui tombent dans le niveau précédent, bin je refais un deuxième long pont (moins, quand même) avec ces fameuses plate-formes qui croulent. (et qui sont peu fiables avec le moteur du RSD Game-Maker: on peut facilement passer à travers ou se faire repousser par le bord d'une d'elles

And then the pace changes, with the next transition being more a 'delevator' than a trial. Blocks are fading in and out, and let you slowly fall from cell to cell. There's nothing you can do to rush it.

The final trial will be much harder, with one-block fading mini-platforms. Badman's jump height is limited, though (2 blocks) so don't expect much variety here like having to move backwards or so.

Une fois n'est pas coutume, après ce deuxième pont (et son boss), un peu de temporisation avec les blocs-temporaires qui nous font une sorte d'échelle de descente où on a rien d'autre à faire que d'attendre.

Et après encore un boss, une petite échelle de plus, une autre chaîne et on passe sur l'incontournable série de mini-plate-formes (un bloc) qui s'effacent l'une après l'autre.

(bon, avec un maximum de 2 blocs de haut pour les sauts de Badman, la variété de ce passage reste limitée).
 



Thursday, April 01, 2021

Ma première pyramide

Assez curieusement, je n'avais pas eu le genre d'angoisse de la page blanche pour la pyramide de Badman II.


Mais bon le level design de Badman 2, c'était de la grande improvisation et pas mal de "bah si, regarde, on sait passer si ...". Et on a droit à un potpourri de vieux cliché de la pyramide de jeu. Voyons un peu.

Badman II was the first game where I did much of the level design myself. I guess my brother was on vacation or had found some student summer job. And I wasn't doing so much analysis paralysis on level design by then, as you can see. Let's have a look at the 'pyramid' level I wrote back in '96, since I'm currently struggling on designing pyramid levels for Bilou's Dreamland.

A peine arrivés dans la pyramide, on est accueilli par une sculpture lanceuse de flèches (A). On est sur RSD Game-Maker, donc quand ça tire, ça tire à intervalle régulier, qu'on soit présent ou non. Petite subtilité, cependant, si on s'accroupit, la flèche pas juste au-dessus de Badman et on est pas touché. J'étais tout fier d'avoir découvert ça :D

A peine quelques blocs plus loin, on rencontre le lanceur de grosses boules (B) à la Indy/Rick Dangerous. on est dans un corridor étroit, il vaudra mieux doser son timing. On enchaîne sur un saut pas évident pour Badman (j'y reviens) et on tombe sur les 'lances' qui sortent puis se rétractent (C) et plus loin dans la salle, des lance-flèches qui tirent depuis le plafond (D). Les 10 points de vie suppléemntaires trouvés devant l'entrée de la pyramide ne seront pas du luxe.

There are a few baddies in this level like lil'pharaohs and tank-like giant spiders, but your true nemesis is hidden in the walls and shoots things at you on periodic timers. It can be arrows (A), big boulders (B), ceiling-attached retractile spikes (C) or more arrows (D). 

On continue avec un choix: affronter toutes les araignées-tank ou escalader vers le haut de la salle et tenter de passer de pilier en pilier pour choper les 5 vies supplémentaires. En cas d'échec, on retombe dans les araignées.
 

ça mérite une précision sur le saut dans Badman. Dans la plupart des jeux de plate-forme, se cogner la tête au plafond signifie commencer à chuter immédiatement. Mais pas avec RSD. A la place, notre personnage 'vole' le long du plafond comme et la portée de son saut n'est pas diminuée. Le challenge pourrait donc sembler assez gentil et les vies sup' "gratuites". Oh que non.

Some of the level goes around the fact that some jumps are possible but tricky. If you just try them with a regular diagonal jump there will be some 'hanging-time' where you're almost there, but not quite. If you release "the jump button" then, you'll fall back to the ground. To reduce that time (where you'll be vulnerable to arrows in the previous screen), you'll have to chain a press on the '8' key of the numeric keypad and then only a '9'. Because unlike too-old-Mario, Badman's vertical (standing) jump goes higher than his running-jump.

La série Badman possède ce qu'on pourrait être tenté d'appeler "un nuancier de saut". En fait, il y a 2 sauts: le saut vertical et le saut diagonal. Chacun est mappé sur une des touches du pavé numérique, il faudra donc faire '6' pour courir vers la droite, '8' pour sauter sur place et '9' pour sauter vers la droite. Et si le saut en avant est légèrement plus rapide que la course en avant, en revanche, le saut vers l'avant monte moins que le saut vertical (effet inverse de Mario, en somme).

En plus de ça, à cause de notre mauvaises compréhension du moteur, chaque saut à une petite frame de non-saut lorsqu'on le déclenche. le résultat, c'est que pour monter par-dessus un obstacle de 2 blocs avec le saut-9 (au saut-7), ça 'coince' un moment et notre personnage va plus ou moins rester 'suspendu' près du bord du coin. Le truc pour passer en une fois, ça va être d'enchaîner rapidement un saut-8 puis un saut-9-maintenu. Ah, et oui, le moteur de jeu a une manière bien à lui de gérer l'inertie qu'on avait pas encore découverte, donc dès qu'on relache les touches, Badman retombe verticalement. Autant dire que sans être mauvais, la prise en main n'est pas immédiate.

Reprenons notre pyramide. On débouche sur un "gentil" zig-zag où il faut éviter les tirs de flèches et timer son passage. ça pourrait être une variation intéressante sur le premier passage si je ne commençais pas par le tir croisé.

On enchaîne sur un escalier plus long, de nouveau avec des lanceurs de gros boulets, mais cette fois-ci, l'espace étant plus dégagé, les boulets se déplacent presqu'en ligne droite (diagonale) plutôt que de "tomber" de marche en marche (la gravitation étant réservée aux seuls héros dans ce moteur). J'avais prévu qu'on doive "sauter" par-dessus les boulets façon Donkey Kong, mais le saut est trop court pour se tour-là si bien que la stratégie pour passer sans casse, c'est de s'accroupir au bord de l'escalier et de repartir une fois que le boulet nous a dépassé.

The pyramid features more zig-zagging areas with decreasing amount of 'cold places' and only the generous (?), amount of hit-point bonuses (those aces of tiles cards) you can use to heal. Apart from that, it isn't so far from the shot-frenzy of Commander Keen.

On enchaîne sur un faux-choix: à droite un sale moment à passer puis la suite du chemin, à gauche, un long corridor (quelques tireurs de flèches) et on retombe à l'entrée de la pyramide (mais en surplomb, ce qui ne sert à rien).

Et on ne va pas pouvoir souffler tout de suite. J'ai rajouté sur la section tortueuse suivante les trajectoires des projectiles: ça crépite de partout. Digne élève des pyramides de Commander Keen. Et seul l'absence de limite supérieure sur les points de vies de Badman rend la chose faisable tant les points de repos sont rares.

Dernier challenge avant le sommet, ces trois gardes à dégommer malgré le tireur sur le mur du fond (et un refill plus généreux de 10 points de vies). Mais les gardes ont un mouvement assez piégeux, faisant des "bonds" pour passer d'un creux à l'autre (en principe), inspirés des égyptiens-rappeurs de Lost Vickings.

Arrivé là, j'ai dû me dire qu'une pyramide sans clés, ça devait être un peu comme un soupe sans sel, alors j'ai rajouté une carte-clé et un bloc-serrure. Voilà. (ils étaient déjà dans le jeu Badman 1, celà dit, mais arrivaient nettement plus tard dans l'aventure)

Past the summit of the pyramid, I'll switch to a key-and-locks mechanics. The layout isn't that innovative, it's mostly an excuse to make you experience way-and-back motion versus one-way boulders or arrows.

Cette première clé n'est vraiment pas méchante. Elle fait presque tutoriel: on la voit en arrivant avant de tomber sur la serrure, et il suffit de partir dans la direction où on l'a vue pour tomber dessus en quelques secondes.

La deuxième (et dernière) va être plus chère à obtenir (en particulier à cause du nombre d'ennemis et de lance-pièges disposés sur le chemin), mais on reste sur la même recette.

Voilà. C'est le genre de niveau sans grande subtilité réalisé 'selon l'humeur du chef' qui constituait le coeur du jeu où j'étais seul à la manoeuvre (frangin en vacances ?) jusqu'à ce que Piek débarque fin-juillet.

Alors ? bon level design ?