Sunday, November 27, 2022

Tué par la caméra

C'est devenu un problème récurrent pendant que je progresse dans les niveaux de Super Mario 3D World: tôt ou tard, je finis en-dehors du niveau, et régulièrement, c'est suite à un mauvais mouvement avec le stick-caméra.

Le jeu a fait le pari d'un mélange 2D/3D qui (globalement) marche plutôt bien. la perspective montre une généreuse partie du sol, ce qui autorise la création de "salles" dans lesquelles les quatre joueurs peuvent aller et venir, coopérer ou entrer en compétition. La manipulation des personnages y est d'ordinaire plus proche d'un Link's Awakening Switch que d'un Super Mario. ça, c'était prévisible. Elle est aussi plus proche d'un Link's Awakening Switch que d'un Mario 64, et ça, ça vaut peut-être la peine qu'on y regarde de plus près.
Dans Mario 64, le personnage peut normalement prendre n'importe quel angle sur le stick. Le contrôle est doublement direct (pour reprendre le terme défini par Kirby Kid dans The Coefficient of Clean ): la direction du stick s'applique directement à l'orientation de Mario et l'amplitude du stick s'applique directement à sa vitesse (ou à son accélération ... ma mémoire du jeu me joue un tour). En comparaison, les mouvements de Mario dans 3D World sont confinés aux 8 directions accessibles à un D-Pad, comme si le jeu avait été conçu sur SNES.

It keeps happening again and again as I play Super Mario 3D World : sooner or later, I end up out-of-path and die. And most of the time, it is because accidentally I hit the camera-stick. I believe the core issue about it is linked to the 2D/3D gameplay mixture at the core of the game -- which for most of the game works quite well. The default perspective shows a good deal of the ground, creating room where the 4 players can come and go, cooperate or compete. Character control is looking more like Link's control in the Switch Link's Awakening game, with 8-directions (as if the design had happened on SNES pad) rather than direct-orientation direct-amplitude control used in Super Mario 64.

En soi, le 3D world étant principalement consitué d'objets alignés sur une grille cubique, c'est un excellent choix de design: quand il va y avoir une passerelle un peu étroite à franchir, le joueur aura toujours moyen d'être pile dans l'axe où il ne se met pas à tomber au bout de trois pas. Mario 64, au contraire, était construit avec des polygones "libres". Une passerelle pouvait se trouver sous n'importe quel angle entre deux plate-formes qui adoptaient une géométrie polygonale quelconque (croyez-en un vieux qui y a joué au pavé numérique sur émulateur, et qui donc devait zig-zagger dans ce genre de situation)

Although Link-like controls are surprising at first, they work fairly well, and that is mostly (imho) because every object in SM3DW is aligned on a cubical grid. SM64 instead used polygons much more freely with any-angle (narrow) platforms here and there, asking for precise adjustment of Mario's direction to avoid zig-zagging. Discretised directions in SM3DW work well with discretised world objects which works fine with the original SMB blocky world design. Next they discretise camera angles by 45° as well. Maybe that's where things get me killed.

Les mouvements de caméra eux aussi ont été discrétisés. On regarde de face, de profil, ou sous un angle de 45° entre les deux. Un léger mouvement du stick droit de la switch nous fait basculer d'une perspective à l'autre dans un mouvement adouci dans le temps mais déclenché d'un coup quoi qu'il en soit. Et ça, en jeu solo, ça fait mal: le stick caméra est alors normalement sous les 4 boutons d'actions. Le moment où vous avez le plus de risque de l'accrocher par mégarde, c'est au milieu d'un saut un peu long. Pour peu que vous soyez dans un niveau qui reproduit en réalité un parcours 2D dans un moteur 3D, il ne faudra pas longtemps pour que ce changement d'orientation se traduise par un changement de la trajectoire de Mario (la direction imposée par le stick est relative à la vue, pas à Mario lui-même, or la vue vient de changer). Le temps de s'en rendre compte, il est trop souvent trop tard pour réagir et on aura au mieux le droit à 2 ou 3 wall-kicks pathétiques avant de ouahaouhouahouahoahahahahaaa au fond du niveau.

You usually have the camera presented so that level goes left-to-right as in a SMB level, but with a short knock on the right-controller stick, you can trigger a responsive-yet-smoothed 45° turn of the camera. And with the camera stick being just below the RUN and JUMP button, it plays trick on me when I'm doing a solo session: most of my accidental camera turns happen in the middle of a long jump. And since the direction of Mario is relative to the view rather than to the world, I'm suddenly heading out of the screen. If that jump happens in one of those level that actually implements a 2D course with 3D objects, that 'out of screen' actually means 'into the bottomless pit that is everywhere around'. Remember how often you thought about a 2D platformer that "that pirhana plant sure inst' as wide as the road!" ? Here you can definitely sneak behind the plant, but you also can fall off the road any time. You'll be granted a few pathetical wall-jumps before dying if you're lucky.

Et pour ne rien arranger, le jeu nous met sur la même input (stick directionnel vers le haut) deux mécaniques: avancer vers le fond de l'écran ou grimper vers le haut. On casse ici le principe d'individualité des contrôle (chaque mécanique a son morceau de manette qu'il ne partage avec aucune autre mécanique, toujours d'après le lexique de Kirby Kid).

Dans la plupart des niveaux, c'est plutôt un bon compromis: ça rend le fait d'escalader un mur spontané par rapport au déplacement sur le sol bidirectionnel, de même qu'il paraît naturel d'utiliser le DPAD vers le haut pour monter les escaliers dans un Zelda 2D (et si on avait pu y escalader les montagnes, ça aurait marché aussi). Mais revoilà les niveaux linéaires où les traceurs de parcours ont décidé de nos faire profiter de la vue splendide sur les nuages en arrière plan plutôt que de nous coller un mur devant les yeux. Soit.

As if it wasn't annoying enough, pushing the direction stick up triggers two different mechanics: it makes you walk farther away from the camera, and it let you climb up. So much for controls individuality (another coefficient of clean control identified by Kirby Kid). It is a quite nice mapping in many levels: it makes climbing a wall natural in a world where 2D floor is used, the same way pushing a DPAD up feels natural to climb up stairs in a 2D Zelda game. But then came the sideways athletic levels again, where designers wanted us to enjoy a beautiful clouds background rather than a boring wall. As soon as you add a climbable obstacle in that setup, Mario will switch from climbing to "visit those beautiful clouds far far away" in no time once you're at the top of the obstacle. 

Sauf que si vous ajoutez une grille à escalader (direction vers le haut), une fois Mario arrivé en haut de la grille, vous avez assez peu de temps pour relacher la direction 'vers le haut'. Faute de quoi, vous irez dire coucou aux jolis nuages d'un peu plus près. "Dommage", comme dirait Bowser. 

Notez que les concepteurs ont réalisé qu'il y avait un problème, et qu'ils ont ajouté une grille-de-fond par-derrière la grille-à-escalader. ça rattrapera le J.L.N qui avait mis uniquement son stick vers le haut (et donc ira s'accrocher à la grille du fond une fois arrivé en haut de la grille-qui-bouge), mais pas le papa qui avait maintenu haut et avant simultanément dans une habitude d'optimisation des mouvements sur les lianes de la Jungle Jaja.


Notez aussi que le problème ne se limite pas aux niveaux sans mur en arrière plan. Ici, par exemple, on est supposé se promener en rebondissant sur les fourmis invincibles tandis qu'on passe par-dessus des pics. Fort bien tant qu'on ne se met pas en tête d'utiliser la 3eme dimension pour aller s'accrocher au mur avec le costume de chat. Parce qu'en réalité il y a un espace de la taille d'un Mario entre les fourmis et le mur, donc vous pouvez parfaitement vous retrouver à les louper parce que vous êtes par-derrière alors que ce tronçon de niveau est conçu pour être joué sur un seul plan. Et vous pouvez aussi vous retrouver à tomber par-devant le niveau suite à un rebond mal calculé sur le mur du fond, naturellement.

And unfortunately, that not only happens in levels where there is no background walls. In that last video, Mario is expected to bounce around from one invincible ant to the next, which can conveniently walk in spikes. Perfect as long as you don't try to use your shiny cat costume to explore the 3rd dimension and climb the wall for a shortcut. If you try that, you're most likely going to miss the next ant because they aren't wandering just next to the wall, but one Mario away from the wall. You are perfectly able to be between monsters and the "save"-your-life wall. And you can still fall by going towards the player after you (accidentally ?) wall-jumped against that background wall.

Sunday, November 20, 2022

#RIPTwitter ?

C'était un drôle de vendredi, ou tout Internet semblait convaincu qu'on vivait les dernières heures de twitter.

Cette année-ci, j'ai une bonne raison de ne pas me laisser affecter par ce genre de nouvelle, mais ça ne m'a pas empêché de voir que j'étais loin d'être indépendant de ce réseau social, même si j'ai pris pas mal de distance (plus de #screenshotsaturday ou de #OneTagPerWeek, par exemple)

Il faut dire que twitter a pris la place des forums quand j'ai migré hors de l'environnement universitaire (enfin, ceux qui étaient encore existants). Il a aussi bouché tant bien que mal le trou laissé par la disparition de Google Reader et des flux RSS. Et il me sert de va-et-vient pour les images et vidéos provenant de ma switch comme de ma 'liseuse' avant d'en faire quelque-chose de précis pour mon blog.

Mais plus gênant, j'ai pris l'habitude de faire des liens vers des conversations twitter quand il y a eu des discussions préalables, ou quand une image full HD d'un jeu switch est en ligne mais qu'une version réduite suffit pour les besoins d'illustration du blog. Et tout ça, ça veut dire que mon blog lui-même perd un membre si twitter disparaît.

J'ai donc demandé une archive de mes données twitter. Mais le 'takeout' est loin d'être automatique, et quelques heures plus tard, ne voyant toujours rien venir, je prend une archive de mon blog (instantanée) et je greppe tout ça un bon coup pour trouver tous les liens du blog vers twitter (enfin, je pense).

Mauvaise nouvelle, les pages correspondantes ne sont que des coquilles vides, dans lesquelles du code javascript ira écrire le contenu des tweets. Le seul outil capable de faire ça, c'est un navigateur complet (je pense). C'est donc au clavier-souris que j'ai passé presque la totalité de mon samedi à copier-coller les tweets identifiés dans un gros .odt sous google-document (365+ pages au final) avec les URLs par-devant pour pouvoir retrouver et reconstruire le contenu-satellite au cas où ...

edit: il aura fallu finalement près d'une semaine pour recevoir l'archive de 1Go avec entre autres toutes les images et toutes les vidéos postées dans mes tweets.

Bref, ça m'a permis de fortifier un peu mon compte Mastodon.

Et il faudra que je vous parle de ce

edit++: le week-end du 1/7/2023, twitter a été scellé derrière un mur. Plus d'accès possible aux tweets si on est pas identifié sur la plate-forme. ça signifie qu'il faut définitivement que je procède à la migration vers Mastodon.

edit+++: novembre 2023. Les notifications twitter sont pourries depuis 1 ou 2 mois par des qui veulent qu'on viennent voir leur profil payant ailleurs.

Sunday, November 06, 2022

Scorpeye... Enfin!

 Oui, je l'avoue, j'ai été lent. J'ai été distrait (au sens attention détournée). J'ai été démoralisé par cette "carapace" qui ne voulait pas faire demi-tour à chaque fois ou qui faisait des demi-tours intempestifs. J'ai douté, de cet empilement de couches qui devait me permettre de laisser des personnes non éduquées au C++ de bricoler aussi leur propres personnages. Sauf que tout ça, c'est bien joli mais que quand vous avez un dysfonctionnement quelque-part, le débugger vous balance des instructions machines alors que le problème est dans le bytecode qu'elles interprètent. Et mon "inspector widget" (pas encore fonctionnel dans le projet 3 rooms) est loin de valoir ddd.

It's been a long time, I have to admit. I've been slow to get things running; I've had lost the hope that I could get that scorpio-shell turning back when it hits a wall... and only when it hits a wall. It felt like I had built a Jenga stack of complexity in order to have a 'simple' interpreter for state machines. But a language is never less complex than the tools you provide to debug it. And Inspector Widget fell short when trying to explain the issue (partly because it is surprisingly not yet working on Dreams.nds)

Une intuition pendant mes vacances ... j'ai retracé la machine d'état de mon scorpion-cyclope. J'ai bien identifié deux ou trois incohérences, mais rien qui ne conduise au bon comportement une fois corrigé.

Oui, je sais aussi, par rapport à ce que je bricolais sur le côté pendant mes semaines de vacances, c'est maigre. C'était des vacances un peu ... particulières.

Puis hier, j'ai repris la machine d'état de pendat. Lui aussi, il réagit quand il fait demi-tour en se prenant un mur. Et il n'est peut-être pas parfait, mais il marche en général bien mieux que cette satanée carapace.

Alors que scorpeye tentait de reconnaître l'absence de sol à l'aide d'un testpoint, pendat se contentait de "dire" "ah bin si la vitesse horizontale est tombée à zéro, c'est qu'on s'est pris un mur. Sinon, c'est qu'on a plus de sol. C'est forcé."

I found only a small evening of ndsdev during my summer holiday this year, and I used it to map the state machine of Scorpeye. It helped me finding a few weird stuff, but it would not make things run properly enough, unfortunately. Then I realised past Inktober that I already had a 'working' monster that bounced off walls. That was the running pendat. And I started mapping its state machine too (granted, after all these years of dsgametools, I should have given myself a tool to make that automatically). To my surprise, it almost never used the same tricks to perform the same task.

For instance, I used a TestPoint below scorpeye to tell me whether there was ground underneath when it claims it failed to slide on the ground. But this is unreliable because it checks only one point to decide for ground while the WalkController checks the whole surface. Instead, the pendat would test whether it came to a halt horizontally. If it did, that means there has been a wall. Otherwise, it bets there's no ground left.

Same with fall/slide transition: the scorpeye tried to use a testpoint to know whether it FAILed because of a ground. Pendat code author (past self) knew the only thing that can make GobGravityController FAIL was a ground. Being stopped by a wall triggers an event. That means no testpoint validation is required.

Finally, I gave myself an extra variable (there are still plenty available for scorpeye) to remember the sliding speed so that we can bounce walls without having to rely on an ImpactController to save the last speed, because so far I don't think GobWalkerController is an ImpactController. It requires to double some states (like left-thrown vs. right-thrown), but that should not be a big deal.

Still, there's one thing that I'll need to fix with unit testing: from times to times, being stopped by a wall while 'walking' doesn't make the move FAIL, but it does clears the speed. Pendat doesn't suffer for that because it has an "increase horizontal speed" statement in its running states that prevents the speed to stay null. I had to add the same statement to the shell, but it shouldn't be required. that's a todo item for XMAS, I guess.

Il me fallait un double-état pour la carapace lancée, une variable supplémentaire pour retenir la vitesse à la place de la 'variable d'impact'... ce genre de choses. Mais il y a un élément suspect. Pour qu'il n'y ait aucun soucis, je suis obligé de mettre une instruction forçant la carapace à accélérer. Sans ça, il reste des situations dans lesquelles je retrouve ma carapace toujours dans l'état "on glisse vers la droite" mais avec une vitesse nulle est un mur juste à ça droite.

Comme si GobWalkerController avait un bug qui l'empèchait parfois de signaler l'échec (FAIL) même si la vitesse tombe à zéro. ça, ce sera une tâche pour un test unitaire.

Super Mario Bros 5

Ai-je eu raison de snobber Mario Maker ? jusque là, je n'en doutais pas. Parce que jusque là, les niveaux présentés étaient essentiellement des niveaux quasi-impossibles ou des productions fafelues avec des canons à Bullet-Bill accrochés sur le dos d'un parakoopa qui lancent des spineys ... ce genre de choses. Mais l'ami Antistar nous a annoncé il y a quelques jours qu'il allait tenter de traverser un jeu qui a retenu mon attention: Super Mario Bros. 5.  

Il s'agit toujours bien d'un titre Mario Maker, mélangeant essentiellement les thèmes SMB3 et SMW (miam) dont l'auteur cherche à rester fidèle à l'esprit des jeux de Nintendo tout en proposant des idées et du contenu original.

Replay Twitch du 29/09/2022 avec un let's play de Super Mario Maker 2 dédié au super monde "Super Mario Bros. 5" conçu par MetroidMike64, qui contient 8 mondes de 5 niveaux chacun. En voici le code : 0G9-XN4-FNF Session de jeu effectuée et streamée depuis une Nintendo Switch.
Maybe I should have installed Mario Maker2. Well, I've had no reason to install Mario Maker (1) on my switch so far because the levels available were essentially nearly-impossible (kazio?) traps or patchwork productions featuring bullet-bill-canons piggy-backed on parakoopas that spawn spineys (or something of that kind). But French journalist Antistar announced a few days ago that he was trying to make a run accross Super Mario Bros 5, and *that* caught my attention.

N'ayant toujours pas Mario Maker2 (essentiel pour tester ce titre puisque le 1 ne permettait pas encore de lier ses niveaux sur une map), je me contente donc du stream d'Antistar. Et au milieu de pas mal de bonnes idées, je me rends compte que les niveaux "maison fantôme" offrent probablement un excellent point de comparaison pour le type de niveaux qu'il faudrait que je réalise pour la pyramide de Bilou's Dreamland ...

Voyons un peu ... on y retrouve régulièrement des portes en apparence difficiles d'accès qui nécessiteront de récupérer un objet pour les atteindre. D'autres objets qui *pourraient* les rendre accessibles (les fantômes n'auraient-ils pas envie de se changer en blocs ?) sauf que non, et des objets qui pourraient aussi (les plantes grimpantes, sauf qu'ils ne sont pas au bon endroit.

SMB5, as you have guessed, is a MM2 game. Unlike its predecessor, MM2 allows users to bundle multiple levels together with a world map. I don't own MM2 but I can watch Antistar's replay and check whether there are interesting level design ideas in that game. And there were. More than I have noted here. What struck me, is that the Ghost Houses for the SMB series may be the closest reference I have for level design in Bilou's Dreamland Pyramid. We've got doors that are apparently unreachable (maybe if you could get an item, you'd reach them?), monsters that might be used to reach them (couldn't those ghost turn into stairs like in some SMW level ? well no), and objects that could help (vines) except they aren't at the right place for that.

Then you've got doors that are unreachable, enclosed in some other place. Doors to be used later that divert player's attention, especially since we can't tell inputs and outputs apart (don't do that in your open world, folks: that's a labyrinth-only feature) and room exits that remain off-screen as long as possible.

On y retrouve également des portes *carrément* inaccessibles. enfermées. Des portes pour plus tard qui détournent l'attention du joueur. En particulier parce qu'il ne sait pas dire à l'avance s'il s'agit d'entrées ou de sorties.

Et pour compléter le tableau, des sorties d'écrans qui sont ... hors de l'écran et que la caméra tente de garder invisible le plus longtemps possible.