Sunday, July 21, 2024

map poked!

map.poke is done. Okay, it doesn't read "map.poke" in the level script but rather block (coordinates) = (hex) so that it mimmics the block (hex) { ... } definition. And that makes it specific to special blocks.

But there it is. After some branches untangling and more commits weaving, I could use it to add a secret exit in the trunk of the 'greent' room without having to go through the now-clumsy steps of patching the level on NDS while editing code on the PC.

Bon, je crois qu'il n'y a pas besoin que je vous dise que quelque-chose n'a pas marché, hein ? vous vous en doutez rien qu'en regardant l'image... En mars, j'avais évoqué la possibilité de reprendre les vieilles maps pour étoffer un peu "Dreamlands" (ou à tout le moins, proposer un peu plus de contenu pour la démo "3 rooms"). Et bonne nouvelle, j'avais fini par retrouver les maps en question. Je m'étais donc rajouter un peu de script qui dise "alors, le bloc de type 11, c'est une sortie secrète, et dans le niveau greent (le nouveau), si on la touche, tu charges le niveau greeny (l'ancien)". Sauf que pas moyen de tester, évidemment, parce que sur greent.map, il n'y a aucun bloc de type 11...

C'était donc l'occasion de se bouger un peu et de coder le mécanisme dénommé "map.poke", à savoir permettre au script d'aller modifier les propriétés d'un bloc du niveau sans rien demander à personne (et en particulier pas à l'éditeur de niveaux ;P). Et oui, la vie est telle qu'il m'aura fallu un bon mois pour que ces malheureuses lignes de code finissent compilées sur le PC qui avait aussi le fichier greeny.map ce matin. Tout ça pour se rendre compte qu'avant de pouvoir faire une "release" avec la vieille map n°1, je vais devoir lui faire un sérieux ravalement de façade pour l'adapter au nouveau tileset ^^"

Oh I presume you don't really recognize the big tree of my so old two-levels demo: since I re-structured the tileset, there are quite some editing to happen there before you can actually enjoy anything :P

Friday, July 19, 2024

Soudliers (encore)

 mais cette fois ci, je suis aux manettes :P

Le jeu est de toute beauté, et je dois dire que le level design me convient assez bien. J'avais un peu joué en fin de soirée, j'avance tranquillou (je me suis en mode "exploration", pas fou), mais je trouve prenant en ayant suivi un tunnel pour me retrouver dans une chute d'eau tout en sachant que j'ai laissé une autre route derrière moi avec cette sensation de "mais alors ? qu'est-ce qu'il y avait de l'autre côté ?_?

Je joue l'archer, aussi. Le jeu a la réputation d'être crapuleusement dur alors fort de mon expérience dans Shantae, je prends un perso qui peut attaquer à distance.

Deux boutons d'attaque - une flèche instantanée mais qui nécessitera un recovery plus tard, une attaque tournoyante de portée plus faible et qui nous prive de tout autre attaque jusqu'à ce qu'elle soit finie mais qui peut être enchainée à l'infini - un bouton d'esquive pour contourner un adversaire - que pour une fois je parviens à utiliser pas trop mal - et bien sûr un bouton de saut. Un panel de mouvements qui n'est pas sans rappeler le combat dans HoB, soit dit en passant. Tout le reste sera sur les gâchettes ou les entrées directionnelles supplémentaires des joy con. Et du reste, il y en a, comme le lancer de bombes que j'ai dû remapper parce que je le déclenchais à chaque fois que je voulais utiliser le bouclier (qui pare entièrement les assauts mais qui fait baisser la barre de statut mauve.

Il n'y a pas à dire, les mécaniques de gameplay sont riches, plutôt bien équilibrées. Mon seul coup de gueule c'est cette "roue des compétences" qui me permet pour l'instant de choisir entre les armes de base et les armes de feu (ouh, J.L.N va adorer, ça) qui est mappée sur le stick directionnel de droite et que j'accroche donc accidentellement quand je tente un combo "sauter/tirer" trop souvent à mon goût.

Les niveaux sont immenses, mais un mécanisme de téléportation entre points de sauvegarde est proposé d'entrée de jeu ... heureusement. Seul point noir, le temps nécessaire pour les sauvegardes et les téléportations (ou les changements de maps, d'ailleurs).

edit: je suis arrivé dans la pyramide qui m'intéresse lors du premier week-end de jeu. Le mode "explorer" porte bien son nom, même si je dois quand-même sortir une potion de soin de temps en temps...

edit++: au bout de 8h30 de jeu, un boss atypique dans le fond de la pyramide me met finalement game over en boucle. Il m'aura fallu un moment d'étude de let's play et beaucoup de chance pour le vaincre.

Tuesday, July 16, 2024

How GEDS scrolling works

The scrolling routines of InfiniMap weren't as well documented as I hoped. Not even when I blogged that "yeah, it finally works". And while trying to document them, I noted some undesired difference between what the code does and what I claimed it does in the comments. So here it goes. First this is the full level map, stored as a 2D array of tiles. Within them, we define an area of world coordinates (xmin,ymin)-(xmax,ymax) that is guaranteed to be present in the video memory as well. That is the "invariant", the condition that was true on the first line of a scroll_*() call and that must be restored before we leave the function.

if (py < ymin + WH / 2)
do { up_scroll(); } while (py < ymin + WH / 2);
else if (py + WH / 2 > ymax)
do { down_scroll(); } while (py + WH / 2 > ymax);
if (px < xmin + WW / 2) left_scroll();
else if (px + WW / 2 > xmax) right_scroll();

WWxWH is the dimension of the validty area. We will never let xmax - xmin < WW happen. To decide whether scrolling routines should update the contents of video memory, the scrolling code compares the position of the camera (i.e. the center of the viewport) with the coordinates of the area. If it gets too close to one edge of the 'validity area', video memory contents will be updated and that edge will be moved, possibly dragging the opposite edge along (since we have fixed-dimension video memory)

void right_scroll() {
unsigned xoff = (xmax - xmin) / TL;
// compute target position in video memory
u16 *src = dataview + xoff;
xmax += SQ; // new validity window will end 64 pixels on the right.
if (xmax - xmin > 512) {
xmin += SQ;
xview = (xview + SQ / TL) & 63;
dataview += SQ/TL;
}
// copy from src to video memory
// so we fill the expanded area with valid tiles. 

Then, this is the video memory. The hardware reads it as a 2-dimensional wrapping array, that is if it cannot read more at the right, it goes back reading on the leftmost column. The (xview,yview) reference point corresponds to "where in the video memory is (xmin,ymin)" (that was the part that needed a patch).

Note that only a part of that valid area will show up on screen (highlighted here).

Note that whatever happens, xmin always shifts by 64 pixels. That's the horizontal copy granularity SQ (because it was meant to be square), and no, I never checked it led to better performance than 32. We must have ScreenWidth + 2*SQ < VramWidth, though.
 

Saturday, July 06, 2024

Test tile type from state transition

As I update an old post to explain that yes, cando() finally managed air/water transition I note that the whole blog is still missing a key explanation of how this was made possible. It happens in state machine transition expression (in the predicates, actually) and says "tell me the properties of the world n pixels above my hotspot".

$FALL->$INWATER on fail [2 H WATER ?]
                        (v1 v5 + 2 / :1 0 :5);

$INWATER->$RBOUNCE on event0 [D_FOOT 8 H AIR ? &]
                        (800 ~ :1);

You see it there. H is the new OP_HOTTILE for the GobExpressions. it picks the value on top of the stack, the constant 2 or 8 here. We can then test bits against the constants WATER or AIR with the ? operator.

Without that, the trick about a slice of tiles that are both water and air is useless, because you couldn't make the difference between falling into water and falling on the ground anyway.

(and yeah, I still have to add those get-worldwide-flag and set-worldwide-flag opcodes as well as the roll-the-dice opcode)

Tuesday, June 25, 2024

Baies pas mûres

 

Eh si, il me reste encore des gribouilles du 1er Janvier 2022 à poster ... dont cette idée d'un berry-bat pas encore mûr qui essaie de se s'attaquer à Bilou mais qui reste attaché à sa branche ... qui a bien fait rire les gens qui l'ont vu, d'ailleurs.

Mais pourquoi, me direz-vous peut-être ? Eh bien outre son rôle de bow-wow rigolo, ces baies encore vertes sont plus dures et pourraient donc rester à trainer sur le sol une fois assommées par un saut. Quelque-chose qui pourrait se révéler utile dans les montagnes, par exemple, où les Applemen ne poussent pas...

There are sketches in a notepad, which were drawn on new year's day two years ago and that haven't been blogged yet. This is one of them. J.L.N and I were revisiting the green zone baddies and came up with a variant of the berrybat that isn't ready to leave the vines. 

It would play a bit like a bow-wow, it would be green, to show it isn't matured, and it will likely be a challenge to animate, especially if I want the vines to be a bit flexible (at least, flexible enough to justify they cannot suport Bilou's weight). But they would be harder than their matured, flying counterpart, meaning that they would stay around once stunned, could be picked up and thrown on things to stun them.

Il était aussi question de s'en servir pour faire enfler certains piafs et s'en servir comme plate-forme.

Saturday, June 22, 2024

map.poke

I will try to get energy again for DS development. Not that I have dropped any Bilou-related activity, but I would like it to lead to code, and not just sketches. One of the last notes I wrote were about live-patching the map from scripts. That was before going on short vacation and no, I did not have my source code along this times (kids have grown up ;)

I know I've been tempted to dismiss it as "not so important", "low priority", but then I realised: if I want to start working on new controllers like "hanging" or "between", I will likely need special tiles to use them. And if I have to go for a full power- NDS- wifi stick- NUC- emulator cycle every time I need a new tile somewhere, I'll never be done. (proof: it's been two month and I haven't done that a single time).

I already have methods in the FlatWorld class that could take care of updating graphics and physics layers as needed. The thing that has been holding me back so far is the fact that this class isn't reachable from ScriptParser.

But well, things aren't as bad as I thought: GameScript keeps a physWorld reference to the objetct that has the desired interface. We're just one getWorld() call away from being able to implement map patching...

Once I'll have the a tile flagged as "hang here", I'll give a try to a new Hanging state ... Even without fancy swinging animation, it should already take us much closer to the gameplay I want for "dreamland"...

edit: just as I was checking the state of my working folders, I found the old maps I had considered merging into the current demo. So I went on and coded a 'secret exit' special block that could send us to one such old map ... And haven't tried it yet because I of course don't have any block of that type on my map ^^"

SMBW: comme dans le jeu du blob

J'ai bien souri quand j'ai vu la gelée quelque part dans les mines fongiques de Super Mario Wonder: un clin d'oeil bien vu à une mécanique jusque là unique d'un niveau de Super Mario Land 2.J'ai souri encore quand Mario s'est vu changé en blob à son tour, collant aux plafonds (comme avec le très réussi power-up foreuse) et suivant le parcours sur les murs ...

Vous pensez bien que quand J.L.N est arrivé là-dedans, il est parti dans un "wouahh. C'est génial! On peut aller Partout!", parce que évidemment, la mécanique est entièrement neuve dans la série Mario. Enfin, il y avait quand-même un peu de ça avec la super-étoile dans Yoshi's Island et il a joué à des niveaux de Rayman où on court sur les murs, mais dans les deux cas, si on s'arrête, on tombe, alors qu'ici on a tout le loisir d'explorer le niveau pendant qu'on colle au mur...

Mais moi, ça m'a surtout rappelé une vignette dans un vieux magazine de l'époque Amiga. Sauf que pas moyen de me rappeler son nom pour vérifier. j'y avais repensé au moment ou "the blob" est sorti, quoi qu'en réalité le gameplay serait plutôt à rapprocher de Super Morph auquel je n'ai pas joué non plus (mais j'aurais bien voulu).

Ce n'était pas non plus Super Putty, toujours dans la catégorie "plate-forme avec un blob bleu", mais bien Globdule, un jeu de Psygnosys (!) tout en rampes et en arrondis avec un blob bleu qui est mauve, apparemment... tout en glissades et en adresse.

Et si j'ai finalement remis le doigt dessus, c'est parce qu'un internaute maîtrisant le japonais a un jour décidé de faire un recensement de tous les jeux 8-bit et 16-bit où on contrôle un blob. Eh oui. C'est ça aussi Internet...




Thursday, June 06, 2024

RTTI vs getSubClass()

I was doing OS development when I started learning C++, and then I went on with DS development. In both case, the amount of memory you're willing to devote to the code of your program is limited. I remember I heard of -fno-rtti on the osdev wiki and thought "well, yeah, that makes sense". I'd rather not have something I know almost nothing about making key decisions on my objects when I have an instance of SomethingGeneric and want to turn it into SomethingMoreSpecific to use its advanced API for any purpose.

Here and now, I had something where I'd be in a similar situation, but there's actually just one way it could be more specific. I had added SomethingGeneric::isSpecific() virtual function and used it to see whether I should reinterpret_cast<SomethingMoreSpecific&>(myGeneric) here and there. Then the colleague who reviewed suggested it might better be a dynamic_cast<SomethingMoreSpecific&> instead ... or we could have SomethingGeneric::getSpecific() instead. and, well, yeah. I like that.

That wouldn't work with SomethingImplementedWithOpenGL vs. SomethingImplementedWithDirect3D vs. SomethingImplementedWithBlitterAndCopper, but for this use case, it's just fine. I don't have more weight on the virtual table ... I don't depend on unknown run-time ... I don't need to add exceptions catching in case of std::bad_cast ... So long, dynamic_cast: I won't need you, after all.

Wednesday, June 05, 2024

Les cages

Délivrer des animaux dans des cages, c'est tout à fait dans les attributions d'un héro tout rond tel que Bilou ... Le fait de les délivrer, ça justifie qu'ils soient disposés à aider Bilou malgré la difficulté apparente, et ça donne des combinaisons clé/serrures pour le level design. 

Mais une question restait sans réponse: "qui les a mis en cage" ? Et qu'est-ce qui a pu motiver ça. C'est pas comme si on avait un Bowser dans l'univers du jeu ... J'ai posé la question à J.L.N en fin de promenade, et il m'a proposé une cage-à-pattes qui court derrière les oiseaux pour les enfermer. Sympathique assurément, mais d'un point de vue game design, ça pose plus de question que ça n'en résout ... mais ça m'a inspiré une variante des berry-bats qu'on pourrait baptiser cage-berries, une sorte de plante pirhana qui ont la dent longue.

So, there shall be mountain peaks and gaps in-between. There shall be ropes that Bilou can hang to. That last part has became almost a mandatory part of platforming since Rayman Origins (or even New Super Mario Bros ? ). So at some point, I figured out that I could replace the need for "wide floating things" by "ropes carried by two round-shaped birds".

That sounds like a nice gameplay idea, so I wanted to extended with key-and-locks mechanics with caged birds. And unfortunately that got me trapped into a design pitfall: how did they got trapped into cages ?

I know, the question is fairly irrelevant in terms of gameplay: when you knock a question block in Mario, you don't worry about who has been placing coins in there and why. But it turns out I do when it's my own world. And since I've long decided that there is no global invasion army in Bilou's Adventure, I don't have any off-the-shelf baddies that could have captured all the helpful birds.

Hopefully, when I asked J.L.N about it, he suggested some legged-cage that would have caught them on its own. Something reminiscent of legged-chests in recent platformers, I guess. That might have worked, but that triggers other game design questions like "how fast should it run away", "can it leap over small gaps", which I'd rather not address because all I truly need is a cage to lock the bird in it.

His suggestion did inspire me sort of giant berries with fangs that locks the bird in. It's not moving much as the berry is still on its vine, but it could move enough to make animation interesting. It integrates quite well with the return-of-the-berrybats already envisioned for Peaks Zone. I could give it a frog-tongue to catch back birds if we stay too close ... and above all that, J.L.N likes it ;)

Wednesday, May 29, 2024

SMBW: flying hazards

J'avoue que quand Mario Wonder a été annoncé, ça ne me gênait pas trop de devoir attendre 3-4 mois que mon frangin me l'offre. Quand je l'ai essayé chez lui, il était déjà au monde 2 ... la prise en main était plutôt agréable.

Mais en voyant les pikdors j'ai su que j'avais là une pépite de game design dont je blogguerais encore des années plus tard. Et en particulier que ce jeu allait peut-être apporter les références complémentaires dont j'ai besoin pour ma "peak zone".

I wasn't very hyped by Mario Wonder until I played the level with the condarts on my brother's switch. Then I knew behind dubious decisions, I had a pure gameplay gem in hands.

Granted, it's not the first time you see some ennemy breaking things in a (new) Super Mario Bros game, but the diversity of the design patterns they used with the condor-darts was brilliant. By that time, I was somehow in a dead-end with Peaks Zone design, especially monster design, and that Super Mario Bros Wonder might be the inspiration I (deseperately?) need to reboot my creativity.

Il faut dire que des ennemis volants, j'en ai déjà envisagés quelques uns, mais rien qui ne soit suffisamment convaincant. Bon, en soi les picdors n'ont pas un comportement si différent des mini-necky de Donkey Kong Country, juste qu'ils sont dans un Mario et viennent s'ajouter à la liste de plus en plus longue de briseurs de briques du dernier jeu SMB*.

Pourtant, le fait qu'il soient aussi utilisé comme une variation des thwomps m'a finalement donné envie d'avoir ... bin juste des plumes qui attaquent Bilou. Un clin d'oeil aux "esprits volants" du tout premier univers parallèle de mon frangin ;)

Et ça reste dans le thème de la planète bizarre. Vu l'effet que les "corbeaux" d'Ori m'avaient fait, ce sera précieux.

One of those patterns was thwomp-like behaviour but where the bird moved sideways horizontally so it wouldn't necessarily always hit the same place. That also means you may try to lure them and have them hit a target you're interested in.

And so I came up with that little sketch of a feather-eye ennemy that could hover out of jump reach and attack when the player is spotted. Nice, although, I don't think it would work with the "use as lift when it moves back" or "use as extra cliff while it is stuck into the wall" patterns.

And then I came back to the old menacing bird design of 2021, the one that has Bilou-compatible shape (I don't want the peaks zone baddies to be "just birds", they also have to fit the planet's theme) and found a fun way to make it fly. That dude could attack and move quite freely in the sky, be attracted away of its resting position, get stuck in walls and all.

Ah, et oui, pendant que je préparais tout ça et que je suis retombé sur mon espèce de vautour à tête de ptérodactyle (c'était l'idée), j'ai fini par trouver une manière rigolote de lui faire prendre les airs qui ne demande pas d'en faire un modèle 3D.


Monday, May 27, 2024

Compile-Time Regular Expressions

Well, guess what: there's a C++ header/library out there that allows regular expressions compiled at build-time. And I've got state machine parsing code that could use a little performance boost, especially if I envision GBA support rather than NDS for some future release.

#include <ctre.hpp>
#include <optional>

std::optional<std::pair<std::string_view, std::string_view>> 
match(std::string_view sv) noexcept {
    if (auto re = ctre::match<"state([0-9]++) *-> *state([0-9]++) *on (hit|found|event|fail)">(sv)) {
        return std::pair{
            std::string_view(re.get<1>()),
            std::string_view(re.get<2>())
        };
    }
    return std::nullopt;
}

Is what the siscanf(ln, "state%d -> state%d on %[hitfoundeventfail]%n") test for state transitions would look like, for instance. Some things will be cheaper, like testing explicitly for one of the 4 transition types rather than getting any garbage word you could craft with their letters and testing if (strcmp(reason, "event")) afterwards. 

Other things will require more code, like converting re.get<1>() into a digit as a post-processing step, since regexp do solely text matching and extraction, no text-to-number conversions. 

The code generated was quite convincing on x86_64, I'm a bit more suspicious about its ability to improve performance on 32-bit ARM processor, given how it requires 9 instructions to match every single character of the "state" constant string, for instance. If it helps for speed, it might have a significant impact on code size...

It seems to build even for GCC 10.2.0, the latest I installed from devkitpro, but not for the one used to build SchoolRush ...

Friday, May 17, 2024

Goodboy Galaxy

I owe you a presentation of "Goodboy Galaxy", an indie exploration platformer for the GameBoy Advance released for the 20-years anniversary of the device. I heard of it while following developer hot_pengu on twitter (since 2015!) 

The game has high-quality pixel art graphics that perfectly fit the theme of "stranded on an alien planet" and super-smooth animation. To be honest, the animation is so rich that it feels like the artist did not have to worry about technical limits at all.

I don't own the game yet. I haven't decided whether I'd rather run it on a true gameboy or wait for a Nintendo Switch port ... having my GBA power supply lost somewhere in house mess does not help deciding ^^". But I played the free demo a few times, the first being in September 2021 during the kickstarter campaign (which was completed in a mere 8 hours).

Original jam (Goodboy Advance) was in Dec '18, then we (very slowly) worked on a demo of what a full game could look like (Chapter Zero) which we released I think in May '21, then we spent a few months working on a Kickstarter campaign before finally starting the full game.

precised hot_pengu when I asked. I admit that the name's pun on Commander Keen's title "Goodbye Galaxy" created some expectation, but it's not that kind of exploration.

Voilà deux fois qu'il est question de "Goodboy Galaxy" sur ce blog. Je voulais que la 3eme en soit une présentation officielle. Idéalement, je l'aurais faite après avoir passé un certain temps sur la démo (au minimum), voir après avoir joué au jeu complet. Mais voilà: ce monde n'est pas idéal ...

Goodboy Galaxy est sorti en 2023 sur Gameboy Advance après 4 ans et demi de développement en indé. La campagne Kickstarter de 2021, c'était une folie et le budget espéré était disponible en 8 heures à peine. Je suivais déjà le développeur depuis un moment, mais plus occasionnellement que ce que je n'ai fait avec le dévelopement de CyberShadow ... Vu le jeu de mot sur "Goodbye Galaxy", la 2eme aventure de Commander Keen, je m'attendais à un gameplay qui serait à Keen 4 ce que Duck Tales est à Megaman ... Mais non. Le jeu qui s'en rapproche le plus dans ma mémoire, c'est Pharaohs Curse.

Low jumps (1 block), respawning one-way elevators, klap trap monsters, wrapping map ... I had a reminiscence of Pharaohs Curse during my first attempt playing the demo, and the author confirmed it was one of his references.

There are some sections where you have a bit more freedom of movement (2+ blocks, and double jump)  ... that is when your jetpack hasn't been stolen by a weird portal. Your (auto-regenerating) shield and blaster may also be stolen by other portals. If there is a way to tell what the portal will do before taking it, I haven't figured it out.

Cette impression, c'est principalement aux phases d'exploration sans le jetpack que je l'attribue, mais il y a aussi quelques rencontres qui y contribuent. Les générateurs d'assenceur unidirectionnels, par exemple, ou ces machins qui sortent du sol pour vous gober avec un léger retard (heureusement!). C'est que hot_pengu a adopté une approche plutôt inattendue où on commence l'aventure avec tout son équipement (blaster pour tirer, bouclier auto-régénérant et jetpack), mais on rencontre ça et là des portails à sens unique qui nous privent d'un de ces éléments pour un portion du niveau. Ajoutez à ça un level design où vous vous retrouvez tout à gauche du planétoïde si vous allez tout le temps à droite, et vous comprendrez qu'on finit par être un peu déboussolé... 

I must admit this approach of taking your equipment away and then giving it back to you in almost every level is quite unusual, if not unique. The closest I can think of is the "give/take color" doors of Fury of the Furries, although it doesn't affect that much the core gameplay. There have been things like that in Rayman, too, but that was part of the game's ultimate challenge, not part of every level.

Saturday, May 04, 2024

Goodboy('s geyser) was here

J'ai quand-même commencé à tenter de dessiner un jet d'eau. J'avais lancé un appel sur twitter, pour essayer de trouver des références. Il faut dire que les cascades de l'époque 16-bit étaient encore plus convainquantes que les jets d'eau de la même période.

J'ai eu une réponse en or, du genre de celles que j'ai eues pour les arbres l'an dernier. Le temps de faire le point, et je vous raconte tout ça ;)

"I can't draw convincing water jet from below" did not sound like a very convincing reason for not using a water jet if it is the proper game mechanic to use. I finally have a good one to pixel study and started doing my own, as you can see on the photo, but allow me to rewind and start where it started.

Un pas en arrière pour revenir à l'époque 16-bit. On préférait souvent éviter d'avoir de trop grosses animations à gérer sur ce genre de machine, et animer de l'eau se faisait généralement avec un dégradé et une modification cyclique sur la palette de couleur (palette cycling). Le foncé devient blanc pendant que le clair devient foncé, le très clair devient clair et le blanc devient très clair...

Back in the 16-bit era, it was frequent to do color cycling to animate a waterfall. Sometimes it worked nicely, sometimes it was so-so. It works best if the raster is long enough and if the animation speed remains movie-quality. At cartoon-12fps, you start seeing as flashing more than falling down water.

But you'll note the bottom of the waterfall is often missing in those scenes. And when you look at the few game art that tried having upwards water jet, you understand why: it no longer works. We expect water to become darker with density increase. In a waterfall, vertical density variation are interpreted as downwards waves, but when water eventually widens up in a fountain-like mushroom cap, it is always more dense at the center and less dense on the "edges". If you do palette-cycling here, you break that.

ça donne une illusion potable de cascade, pourvu qu'elle ne soit pas trop grande et que la vitesse d'animation soit réglée au millipoil. Et si possible, utilisez plus que 4 couleurs pour le cycle, parce que sinon on se retrouve avec quelque-chose comme le décor de Yoshi's Island qui tient plus du clignotement que de l'écoulement d'eau. 

Et malheureusement, la même stratégie est appliquée dans les (nettement plus) rares jets d'eau de l'époque. Je dis "malheureusement" parce que pour un jet d'eau, on va forcément devoir aussi animer le "chapeau de champignon" qui va avec, pour lequel la surface animée est encore plus grande. Et l'effet clignotement encore amplifié. On l'a déjà dans Bubsy, où les pixels isolés clignotants ne parviendront pas à faire oublier le fait qu'ils sont statiques. On l'a dans le final de Link's Awakening et dans le jet d'eau d'un jeu obscur avec la mascotte du Mac Do.

In Bubsy, for instance, the artist sprayed out the water pixels as the water starts falling down. This is coherent with the style, but animating them will just give you blinking static pixels of water. And the stylized 'mushroom cap' used in Link's Awakening and Mac Do game flashes even more aggressively.

Là où ça coince tout particulièrement avec le "champignon", même quand on évite les pixels statiques, c'est qu'avec ce type d'image, le clair et le foncé ne sont plus interchangeables. On voudrait que le bord soit plus clair parce que l'eau y est plus éparpillée. Faites-y du palette-cycling et vous aurez des images qui donnent l'impression d'être en négatif.

J'avoue que je trouve un peu dommage qu'avec les resources graphiques de la SNES, on en soit réduit à ça pour animer l'eau. Mais il faut reconnaître qu'en misant tout sur de la RAM vidéo, la console n'a plus la possibilité de reprogrammer les plages d'adresses (bank switching) pour faire des "animations gratuites" comme la génération 8-bit. Toute animation va impliquer un transfert DMA vers cette VRAM et le budget pour ces transferts est limité (comme toujours).

Truly, the "cap" of the fountain/geyser needs dedicated animated tiles, but we're unlikely to see that on 16-bit engines. 8-bit machines could have done that with more ROM and evolved mapper chip, but 16-bit consoles no longer try to pull pixels directly from the ROM. They put them in dedicated video RAM, and rely on DMA channels to bring animation frames in due time. But the amount of pixels you can transfer per frame is limited. Animating Bubsy's geyser that way at 60fps would consume 25% of your animation power:

On NTSC with overscan mode turned off, there are 262 - 224 = 38 scanlines in vblank. Subtract one scanline for prerender time, and you may end up with 165.5 * 37 = a smidge under 6 KiB per vblank.

6K, sur SNES, c'est 46 blocs-question de Super Mario World. Animer quelque-chose de la taille de la fontaine de Bubsy à 60fps, ça demanderait donc 1/4 de la puissance dans la partie critique du moteur de jeu.

Bon, et après l'époque 16-bit, alors ? Du côté de Super Princess Peach, par exemple, qui est plutôt réussi côté pixel art ? Un jeu ou pleurer est une mécanique de jeu, il doit bien y avoir des jets d'eau dedans non ? 

So, well, my game is not for a 16-bit system anyway, so could there be any water jet pixel art for 32+ game that I could study instead ? Say, in Super Princess Peach ? A game where you cry waterjets sure should also have some geyser-like elements, right ?

Well, it does indeed, in Wavy Beach 2. It uses a "cone" of water that might be animated through color cycling plus a "flower" top that follows the rule "keep the center dark and the edges light". But even then, I don't find it appealing, and I don't see how I could make it match anything but the super-stylized environment of SPP.

Eh bien oui, en effet. Dans le niveau 2 de la plage. Mais je dois bien avouer que je ne suis que moyennement emballé par le style. On a un premier élément (le cône) qui utilise un effet de palette qui ne fonctionne pas trop mal, les traîts latéraux restant sombres en permanence. Puis on a cette "fleur" qui grandit et rétrécit, gardant toujours le sombre au centre et se permettant des éclaboussures au bord des "pétales" sur la dernière frame.

Mais ... bof. Même en corrigeant le truc pour que la princesse apparaisse par-devant la fleur, ça ne me convainc pas. Oh, ça marche plutôt bien avec le reste de l'esthétique stylisée de SPP, mais ce type d'animation dans Bilou ? Pas convaincu.

Et depuis ? Parce que bon, le modèle pour la cascade de Bilou, il ne date pas de 2005. Mais le truc, c'est que j'ai surveillé les cascades en pixel art pendant pas mal d'année, sachant que j'en aurais besoin tôt ou tard. Alors que des geysers, c'est plutôt un truc de dernière minute.

Et c'est là que hot_pengu, l'auteur de Goodboy Galaxy, m'a pointé vers la vidéo de son jeu sur GBA

And so I finally asked hints to people on twitter who might have seen something I could use as a reference, or ever proper keywords to search for one, and to my surprise, I received an answer from indie game developer hot_pengu:

We call it a 'geyser' internally for goodboy, and this (timestamped vid) is how we represent it.

Je jette un oeil, je prends un petit screenshot pas fou mais qui pourrait donner un point de départ, et là,

Here's a better look, if it's useful! (there's two versions, one comes out of a monster)

He added as I posted a quick snapshot for future pixel study, handing the Goodboy Galaxy spritesheet with 2 sizes of exactly-what-I-needed material that you see printed on the top photo. 6-frame stunning animations, with tileable base and stylish top. Even the style isn't that different from the one I have for my waterfall!

Une animation pixel-art moderne, tout en fluidité et utilisant bien les 6 frames, qui peut être étirée en hauteur comme on veut ! C'est celle que vous avez vu tout en haut de cet article, imprimée et que je suis occupé à étudier. Parce que là, j'ai bien mieux qu'une référence pour donner une seconde chance au cas du bouchon: j'ai une idée.

Voyez, ce geyser, je peux le placer au fond du trou, directement, sans avoir besoin de bouchon. Il bouge, il attire l'attention. Pas moyen que le joueur ignore sa présence. Il a un look quelque-part entre la plate-forme et le bumper ... on pourrait toujours sauter dessus, on ne sait jamais. 

I like how it simply requires the player to hop into the proper spot to trigger. Much cleaner gameplay than the "pull the cover" I had thought about, but it remains interactive. Plus, by being already flowing before we interact, there's no more questions about "where does this water comes from, where does it goes afterwards", etc.

Deuxième bon point, une fois que Bilou a sauté dessus, je peux réutiliser le type de comportement que le joueur rencontrera plus tard avec Inkjet: Bilou reste "coincé", la pression s'accumule et wouf! on est projeté vers le haut.

And that would match the way 'inkjet' monsters will lately be used as delayed bumpers in the School Zone ... Since this game will no longer feature a welcome screen with the inkjet, it's a good thing the player can be shown early what happens after the "caught in a boiling pot" animation.

Et si il a raté son premier saut, il peut retomber sur le "chapeau" du geyser et re-sauter de là.

Mieux encore: si le joueur n'est pas resté dans le geyser jusqu'à être projeté, on peut le pousser vers le haut s'il entre en contact avec le "pied" du geyser. Et si rien de tout ça ne se produit, on peut directement réessayer la même manipulation. Pas de risque d'aller se coincer en nageant, de faire redescendre l'eau trop tôt ou quoi que ce soit de ce genre.

Bref, j'avais pensé vous redessiner *mon* geyser sur DS pendant la petite semaine de vacances, mais au final, j'ai juste eu le temps de faire une petite feuille de notes pour illustrer ce que j'imagine comme mécanique avec mon geyser ... parce que les vacances d'une famille 11 + 15, ça ne ressemble pas vraiment à la dynamique 8 + 12 et ses plaines de jeu à surveiller :-P

I expect that the platform-look of the geyser top will invite even the younger players to jump on. I expect that its animation will catch their attention much more than a purple block or handle. Should they fail to use the bump effect to reach the key, they can be caught by the platform-top and jump again. If they jumped out before the geyser happened, they can jump into the flowing geyser and be pushed up to the platform-top. It's flawless ^_^

Now I just need to find enough time in the upcoming evenings to complete it ^^"

PS: if you want to animate something like that, consider animating it without the vertical motion first: just the wobbles and the sparkles, and only then apply the vertical shift to each frame. Unsure I will follow that advice myself this time.

Wednesday, April 24, 2024

'faut pas pousser!

Vous êtes devant une porte verrouillée au fond d'un tunnel. Il y a un trou rempli d'eau sur le chemin menant à la porte, alimentée par une chute venant de la galerie supérieure. Votre sens de l'exploration vous sussure que la clé pour la porte doit se trouver dans une des galleries supérieures que vous avez aperçues durant votre chute. Vous pouvez sauter avec (A) et ramasser des objets moins lourds que vous avec (B), mais la galerie supérieure est trop haute pour que vous puissiez l'atteindre en sautant.

Bon, vous l'aurez compris, je suis à la recherche d'une alternative pour le niveau 1-1 de Bilou qui ne dépende pas d'une action a priori peu maîtrisée à ce stade comme "pousser un bloc". Mais j'ai quand-même envie que le joueur ait la sensation de s'être tiré d'affaire, pas juste d'avoir fait demi-tour.

Ayant tout juste rejoué à DK Tropical Freeze, ma première idée était de mettre un gros bouchon au sol et de le retirer avec (B). Si il faut, on pourrait même faire en sorte que le bouchon dépasse un peu et qu'il laisse passer une goutte de temps en temps, pour attirer l'attention du joueur. Sauf que ... dessiner un geyser, c'est plus facile au bic qu'en 256 couleurs ... l'animer, c'est plus facile dans la tête du lecteur qu'à l'écran... Et ce n'est pas l'époque 16-bit qui va m'aider, cette fois-ci. >_<

How do you get yourself out of a hole when all you can do is JUMP and GRAB but you cannot jump high enough ?Maybe you're lucky and there's a plug-like think holding water that was just waiting for you to spring out. That would save me the trouble of needing to code raising water level and making the player confident that they won't drown if they fill the room with water ... But I have no idea how I could make a convincing geyser and '90s pixel art really does not help this time.

A supposer même que je trouve des graphismes concluants, et si le geyser a l'avantage de ne pas demander de jouer dès le niveau 1 avec de l'eau qui change de niveau, il reste un problème physique: il faudra que je trouve un layout qui explique que l'eau du geyser monte alors que l'eau du "puits" non.

Est-ce qu'on pourrait s'en sortir avec le bouton de saut ? C'est quand-même la mécanique de jeu n°1 ... On pourrait donner un coup de tête dans un truc ou tomber sur un machin qui ferait apparaître des plate-formes (disons des feuilles depuis des lianes, pour rester dans le thème de la forêt) puis sauter de feuille en feuille pour se tirer d'affaire.

Mais j'ai le même soucis qu'avec les Ethers en 200x: c'est un comportement de sale garnement et je voudrais que Bilou reste un personnage exemplaire (malgré son caractère ronchon). (De nouveau, le lecteur attentif sentira l'influence de DKTF et de ses plate-formes rangées contre le mur qu'il faut faire basculer à l'horizontale ... mais dans l'autre sens)

Could there be anything that would trigger a useful event if jumped on ? Like making buds bloom into leaves large and strong enouh to be used as a platform. But unfortunately the only such trigger I could think of imply that Bilou is hurting the target and that pain is the thing that forces blooming. I'd rather not have Bilou do such things if I can avoid it.

Par contre, l'avantage de cette idée, c'est que comme j'ai l'intention de permettre à Bilou de s'accrocher en appuyant sur (B) en l'air, on peut remonter soit en combinant attraper/sauter, ou en utilisant le "mécanisme" pour faire apparaître les feuilles. (détail sans importance puisque le joueur un poil rôdé au jeu n'aura pas oublié d'aller chercher la clé en premier)

Mais sinon, il y a une alternative plus sympa, inspirée du "dragronce":

Dans un recoin obscur, vous remarquez une sorte de tête, mi-crocodile, mi-végétale inconsciente et a l'aspect desseché. Vous faites immédiatement le rapprochement entre la texture de son "cou" et celle des lianes qui sortent ça et là de la paroi

 But maybe there could be something that can be grabbed and carried around to produce the same effect. Like the head of a thirsty dragonthorn, since there's water just nextdoor. That would be nice from Bilou to bring them into water. Might be a bit tricky to draw too ... even with pencils, I'm not convinced by those sketches... and it's a bit ... convoluted.

On peut ramasser sa tête comme les autres objets... on peut l'amener jusqu'au point d'eau pour qu'il reprenne des force et que ses feuilles se changent en plate-formes. La bonne nouvelle c'est que ça fonctionne même si le joueur n'a pas encore compris que B=ramasser et pas B=frapper.

Et avec le saut comme mécanique, est-ce qu'il n'y a pas moyen de faire quelque-chose qui soit sympatique ? Disons qu'il y ait une grosse racine qui soit juste un poil trop haut pour profiter de toute cette eau pour grandir, hein ? il suffirait de lui tomber dessus pour l'enfoncer un peu, elle se réveille, elle boit, les feuilles repoussent. C'est simple, c'est visuel, c'est le bon plan. Non ? 

'bin pas forcément si j'en crois mon frangin... lui, en tous cas, il n'a pas franchement accroché à cette approche.

Or maybe there could be something that wouldn't mind being jumped on and yet make the leaves bloom? Like a big fat root just about to reach water? It would actually be friendly and helpful to push it into the water just enough so that it could come back to life, bloom, etc. Well, I thought I had the perfect solution here until my brother seemed unconvinced.

Bon, qu'est-ce qu'il me reste ? En fait, dans le design d'origine, il n'y a même pas ce genre d'ascenseur interactif à mettre en marche. Le frangin, il avait dessiné un tuyau, une chute d'eau alors qu'on est déjà un demi-écran en dessous de la galerie supérieure, une pente-qui-pousse avec l'eau qui dévale et qui nous entraine jusqu'au bassin Est.

Celui qui n'a pas la clé n'avait qu'à penser à aller dans l'eau et prendre le téléporteur si tant est qu'on ait de l'air jusque là ... ou mourir et recommencer.

That brought me back to the original level design from my brother, only to realise that there was just nothing to help you climb back and get the key you need. Actually, he did even put one-way-watery-slope (inspired by Sonic's Labyrinth zone ?) to push the player into dive-or-door decision. If you dive, you'd have had limited time to locate the teleporting device that brings you back overworld where you could try a better route and find that key.

I don't think it could be used as-is in a modern game (and I want Bilou's Dreamland to feel modern) but since I now have waterflow tiles, I could definitely have some spot reachable from the water surface (Bilou can't dive freely in this game) where you're swallowed by a stream bringing you back where the teleporter would have dropped you. I think I'll have that anyway. But not just that. 

Pendant tout un temps, pour la reprise du niveau, c'était hors de question parce que mourir, c'est has been et que l'eau nous fait flotter, pas couler, donc pas question d'aller explorer le fond des choses avant d'avoir débloquer le bon pouvoir (metroïdvania avant l'heure).

Mais là, maitenant, j'ai des blocs qui permettent d'envoyer le joueur à travers un courant forcé ... je peux donc prévoir qu'une petite partie de ce bassin serve de départ pour une trajectoire "remontante" vers l'emplacement prévu pour la sortie du téléporteur "ah ouais. Comme dans Bubsy" ajoute mon frère.. visiblement, cette stratégie-là, ça lui parle. Je tâcherai donc de la mettre dedans, mais j'aimerais quand-même avoir une alternative plus directe pour le joueur qui a envie de trouver la "solution" plutôt que de contourner le problème.

Saturday, April 20, 2024

The first push

J'avais un joli projet pour le niveau 1 de la Green Zone: si le joueur est arrivé à la porte sans la clé, il pouvait libérer l'eau d'un réservoir et s'en servir pour remonter plus haut dans le niveau rechercher la clé manquante. Et pour décider si l'eau est là où pas, j'envisageais un mécanisme-à-la-fury où on pousse un bloc pour lui faire un passage.

Le hic, c'est qu'on est dans le niveau 1-1, là, et que ce sera aussi la première fois que le joueur devra pousser quelque-chose. Est-ce que je ne risque pas de reproduire le problème de la craie des 20 ans où une majorité de joueurs vont se retrouver bloqués après quelques écrans parce que tout un coup, il ne suffit plus de pousser sur A ou B mais qu'il faut interagir avec le décor en insistant un peu alors qu'on ne sait même pas si l'eau est dangereuse ou non.

How do you set up your level design so that players understand they should push a block to keep going? How will they understand that they're not in a dead end, but that there's just one more interaction to learn and use to progress further into the game ? I wonder because I thought about using "push-the-block" as a way to get my players out of what would otherwise be a dead-end.

Par curiosité, je suis passé voir des vidéos pour me remémorer comment d'autres jeux ont géré la chose. Dans Fury of the Furries, notamment, où on va pourtant pas mal se creuser les méninges par rapport à un Kirby, il faut quand-même aller jusqu'au niveau 9 du désert (premier monde, qui en comporte 10). Et là, le bloc à pousser n'est pas dans un coin ou masqué dans un mur ni rien de ce genre. Il est clairement positionné en "porte" entre le haut (vide, joli, mais inintéressant) de l'écran et le bas (clairement là où il faut aller, avec des panneaux, des objectifs, des dangers ...)

I had memories that almost every platformer character of the '90s would be able to push things, so it would be easy to see where they first do it and what the level looks like around them. But let's be honest: finding pushers among platformers isn't that easy and numerous characters don't do it. Cool spot, Aladdin, Zool, Mickey (in Magical Quest), Twinbee, Soccer Kid ... and that's only to name those which I truly expected to push things. I did not even thought you'd encounter that in Rayman, Donkey Kong or Titus games given their primary mechanics

But Fury of the Furries did ... you won't have to push anything before you reach level 9/10 of the first world! And there, the first block to push is clearly not part of a puzzle. It is merely a door between you (in a non-interactive rectangular space) and the level you're about to play. And even that wasn't obvious to everybody since I heard a twitcher noticing loud that "ah ? So we can push things, too" and checking the user manual live.  

Et même comme ça, on a des joueurs qui ont twitché "ah !? ils peuvent pousser des trucs, aussi" et de ressortir la page du manuel avec les mouvements possibles. Alors bon, moi avec mon bloc tout seul dans un recoin où le joueur peut légitimement se demander s'il ne va pas mourir noyé s'il pense que le bloc pourrait éventuellement être poussé, hein ...

Bon, évidemment, il y a des jeux où "pousser un truc" est au coeur du gameplay, comme une version plate-forme de waimanu Daring Slides. Et des jeux où "pousser" est une mécanique secrète pour dévoiler des salles cachées du même tonneau que le "reste abaissé 3 secondes devant le soupirail" de Titus the Fox. Je ne suis pas dans le premier cas avec Bilou (le coeur du gameplay, c'est sauter+attraper) et si ce serait sympa d'utiliser le poussage de blocs pour trouver des cachette secrètes, ce n'était pas l'idée ici.

Alors il y a l'approche moderne, évidemment: mettre le budget pour traduire une infobulle dans toutes les langues possible, et indiquer au contact du premier objet à pousser comment il faut faire pour le déplacer. Et pourtant, je sais que j'ai perdu un long moment dans une partie de Ori parce que je ne me rendais pas compte que je devais pousser quelque-chose plutôt que de trouver un double-jump.

But let's be honest: even if I did invest time into a printed manual, future players of Bilou: Dreamland are not going to read it. Players of School Rush barely checked the interactive book on the bottom screen unless they had a sibling actively watching them play! How is that handled nowadays ? Ori did push things in the Blind Forest... It requires you to hold a trigger while you move left or right. Pushable things are highlighted as you approach them and you've got a helper text when you first encounter one. That should be perfect, right ?

Well, unfortunately it isn't. I remember I got stuck at some point in some game of Ori by something I should simply have pushed but I couldn't remember how and I had forgotten what the highlighting meant. It was as simple as picking an old save months after finishing the game: the helping text will only show up once. Not 'only for the first block you have to push', mind. Really just once. How cool for kids that are not reading yet, or not that language, or are distracted by something (a monster and freaky spikes ?) while they should be reading ? 

C'est que ce message-tuto, il ne s'affiche pas systématiquement: uniquement au premier contact. Heureusement, sinon l'aspect "utilise tes méninges", ce serait un peu loupé... Avec un rocher qui se retrouve entouré d'un halo quand on arrive au contact, on a peu de chance de s'en servir pour des cachettes. En revanche, le fait de devoir maintenir un bouton pour pousser les choses, ce n'était pas naturel pour moi, et donc faute d'emploi régulier, une pause un peu longue dans le gameplay ou un retour en Nibel au milieu d'une partie sauvée, et je me suis retrouvé obligé de retourner voir un let's play T_T

Sonic utilise des blocs à pousser, et c'est probablement la manière la plus propre possible de l'introduire:

  • ils n'arrivent qu'en 2eme monde, quand le joueur est bien rôdé sur les mécaniques principales du jeu
  • il est d'abord utilisé en mode 'clé' : le joueur sera obligé de maîtriser ça avant de passer à la suite.
  • le bloc à pousser et l'endroit où le placer partagent une palette de couleur qui est absente du reste de l'écran
  • dans les écrans précédents, on a régulièrement été confronté à un obstacle qui nous oblige d'attendre et où le joueur verra Sonic tenter de pousser l'obstacle s'il maintient la manette dans la bonne direction
  • what could possibly go wrong ? (est-ce qu'on peut bloquer ce bloc contre le mur, au fait ?)

So where did I get that feeling that "every character will push", then ? Marble Zone, of course. It had a significant impact on my brother when he drew his first level maps. And I must say that the introduction of pushing blocks in Marble Zone is almost flawless. You've just been forced to stop and wait by crushers, maybe for the first time of the game, so you've see your hedgehog pushing the wall or the crusher while you had the DPAD pushed to the left while waiting. It is world 2, so you already have good knowledge and understanding of all other actions and you can use some concentration to notice that. Maybe you're in a dead end, but there's a unique color-coding for that unique-looking block and that switch that makes the gate open when you stand on it. And the block would fit that slot almost perfectly. The only thing that could go wrong would be that player could push it to the left until it is stuck against the wall. Nothing to prevent that. 

J'ai continué mon tour d'horizon, mais il faut bien le reconnaître, l'omniprésence de l'animation "pousser un bloc" dans les jeux de plate-forme 16-bit, c'était une hallucination de ma mémoire. C'est fréquent, mais c'est loin d'être omniprésent. Et même quand c'est utilisé, c'est loin d'être une action de base. On en trouvera 2 ou 3 apparitions, à des positions diverses dans le parcours d'un jeu à l'autre mais jamais autant que les blocs-à-pousser de Zelda. Et sans grande surprise, il faut le reconnaître: dans un jeu de plate-forme, il y a quand-même nettement moins de variantes possibles.

There are quite a number of other blocks to push in the Marble Zone. It is quite unusual even among the games that use push blocks. Fury won't reuse them until mid-world 2. The Lost Vikings have one at the end of world 2, one at the start of world 3 and then nothing until the end of world 3. Bubsy only in level 7, and never mandatory (although used to create a nice puzzle in the hideout to get a Continue). It would have been tricky to make it mandatory in a game where you're killed so easily and when there are so many alternate routes that they can hardly be called "routes". 

It should also be mentioned that the pushable block for Bubsy is a crate, and there had been many crates before. They're almost like Sonic's TV blocks. Crates with collectibles, crates with traps, crates with bananas or anvils. But these two in the desert have no label. They don't break when you jump on them like any other crate in the game would do. That's teasing enough to make the player want to find a way to open them, in my opinion.

Mention spéciale pour Bubsy, qui n'utilise que deux fois (dixit la soluce) la mécanique, et dans le 7eme niveau. En particulier dans un 'puzzle' où il faut pousser la caisse et faire un détour pour la pousser à nouveau, mais l'enjeu est de taille: un "continue", l'item le plus précieux dans ce jeu die-and-retry.

Est-ce que le joueur a eu l'occasion d'expérimenter avec les caisses avant ? Bin dans le jeu, on en a juste eu une plus tôt pour nous éviter de devoir faire demi-tour dans un wagon. Mais soyons sérieux un instant: si le joueur ne se rend pas compte qu'il peut pousser cette caisse et essaie de passer malgré tout, il se prendra les pics, mourra instantanément ... ce qui arrive en général toutes les 30 secondes dans ce jeu. Au prochain passage, il sera probablement trop rapide pour ne serait-ce qu'apercevoir la caisse, vu le nombre de trajets alternatifs que le jeu propose. Et puis un joueur qui arrive au 7eme niveau de Bubsy n'est certainement pas un débutant. Il a d'autres jeux derrière lui où il a pu apprendre à pousser des trucs ... et en particulier des caisses. Une caisse dans un jeu, c'est à peu près aussi "louche" qu'un bloc avec un point d'interrogation dessiné dessus.

Another first-push that is worth noting is in Mr. Nutz. You'll have to push a chair next to a table so you could progress in the Living Room level. Nice little puzzle in an action platformer, and quite unusual to have something that big that your character can push. But what makes it interesting is that the same wood texture is used on the table's legs and when you encounter the chair, you've just been walking past the table unstopped. I'm sure half of the kids have started pushing the chair without even thinking about it because they had not realised it was in their way. It was just like the table and like everything else since the start of that level: scenery.

Other good point on how Mr. Nutz introduces those pushable platforms: they cannot be pushed too far and couldn't be locked or fall out of the place where they are helpful. 

Le plus étonnant dans les setup, ça restera Mr. Nutz, où la chaise-à-pousser est une énigme pour le début du niveau du living qui est probablement devenue iconique du jeu, et révélateur d'une époque de conception. Mais le plus impressionnant, c'est que ça marche sans le moindre accroc. Au moment de rencontrer la chaise, on vient de passer 3 écrans à avancer tout droit devant un décor détaillé mais vide d'un point de vue level design: pas d'ennemi, pas de bonus, pas de power-up. Rien. Et au milieu de ce décor, la table, qui utilise les même recettes graphiques que la chaise. On est passé devant sans soucis, et donc alors qu'on aurait pu avoir le réflexe de sauter par-dessus un rocher ou de faire demi-tour devant un mur, ici on va spontanément se mettre à pousser la chaise (dans le mauvais sens) parce qu'on ne se rend pas compte qu'elle nous barre la route.

Autre jeu dans lequel on pousse sans s'en rendre compte: Mickey Mania. En tout cas, si vous tombez à l'intérieur de la cabine du bateau. On voit à peine son personnage, et il passe derrière le décor, donc pourquoi ne sortirait-il pas par derrière les caiss... ah ? il les pousse ? ... okay. ça me va aussi.

Notez qu'on ne peut pas pousser les caisses vers l'intérieur du bateau, par contre.

I'm more sceptical regarding how Mickey Mania deal with it: you've got an exemplary use of the pushed blocks with the crates next to the cabin of Steamboat Willie: you've fallen into the cabin and when you move left to go back, you see yourself through the window but you don't see whether there's a wall or not on the left. And as you keep moving left, you end up pushing crates, opening your way out of the cabin again. Here you didn't realised you were going to push something because you didn't know where you were. That's great.

Unfortunately, it isn't a mandatory step and the other things to push in the game will not have such clear level design. A giant chest or some plump pudding, where you can easily jump over them if you thought they are an obstacle. With a good amount of other things in the same room that might distract your attention so you could think "noo! why have I killed that monster ? now I can't use it to bounce my way over that wall and I have to reset and redo ..." . Well, you see what I mean.

Enfin, ce que je dis là vaut pour le premier niveau. On retrouve des objets à pousser plus loin dans le jeu (fiole, plum pudding, coffre ...), et là c'est "débrouille-toi, mon grand". L'objet est mis au milieu du reste dans des salles remplis de trucs. Si on compte sur le fait que la cabine du bateau était une salle bonus secrète, un joueur pourrait très bien débarquer là-dedans sans avoir eu droit au tuto "si, regarde, on sait pousser des trucs", et là, bon courage sans SOS vidéo games ...

En comparaison, Ardy Lightfoot prend littéralement le joueur par la main, avec une caisse-tutorielle dans le "prologue" du jeu (même si un speedrunner trouvera le moyen de passer sans pousser) avant de s'en servir au sein d'un puzzle dans la pyramide du niveau 8. Les développeurs iront même jusqu'à utiliser le niveau-prologue en mode "démo automatique", histoire que le joueur puisse voir que "ah, mais attend ça ce pousse, ça!".

Bref, je vais devoir en rester là. Si vous mettez une caisse-à-pousser dans votre niveau 1, l'approche de Ardy est probablement ce qu'il y a de mieux à faire pour éviter les frustrations, sauf si elle sert pour un passage secret.

Two last to check: Super Mario Wonder below, with clever use of a dedicated foe to show you some stuff may now be pushed -- but we're quite far from level 1 although we're still in world 1, and Ardy Lightfoot (above) that will introduce pushing crates mechanics in the 1st level, let you see that it can be used in the "prologue" demo that actually plays level 1 with credits, and then use them in puzzles in the pyramid level, somewhat near the half of the game.

edit: challenger de dernière minute ... Wonder serait-il le premier Super Mario où l'on peut pousser des trucs ? Avec carrément un Koopa dédié au fait de nous montrer que c'est possible sans devoir nous le dire. (ce qui n'est pas sans rappeler les WaddleWing de NSMBWiiu, soit dit en passant :)

Well, I guess that's all. Push mechanics is less frequent and less helpful in platformer where you can easily jump over things that could be pushed than in top-down games like Zelda. If you have to use some in your game, better introduce them at the start of the level where they are used, although it cannot hurt to have them shown up front in level 1 like in Ardy. But if you do have them in your level 1, it will be critical to setup the stage so that the pushable element stands out ... unless it is just a way to open a secret passage, of course.