Tuesday, January 18, 2022

Keen sur Switch!

 Oulah! On se calme tout de suite, les gars. Je vous vois déjà bondir sur le store, cartes visa dehors ... Il ne s'agit que de Keen Dreams, le poussin noir de la couvée. Le lost-levels 3.5 qui marque la transition entre le classique "invasion of the Vorticons" et le cultissime "Goodbye Galaxy".
Mais bon en promo à 2 euros, même si c'est le seul épisode pour lequel j'aie jamais dépenser un cent (bin oui, les épisodes 2,3,5,6 étaient introuvables dans mon rayon d'action et les épisodes 1 et 4 étaient redistribuables librement :-P), même s'il est affublé d'un scénario discutable, de graphismes meilleurs-mais-un-peu-à-l'arrache et d'un gameplay franchement perfectibles, je tente.

K1 : classique.
KD : meh.
K4 : cultissime

Allez, je remets un petit comparatif pour ceux qui étaient ailleurs dans les années '90. La première trilogie, c'est un personnage de taille modeste dans un environnement aux graphismes minimalistes: à-plats de couleurs, perspective frontale, décor épouillé ... mais c'est le tout premier jeu de plate-formes à scrolling sur PC alors on se l'arrache.

La suite "Goodbye Galaxy" prend le pari d'une perspective pas-complètement-cavalière (influence de Prince of Persia ?), offre un personnage plus grand et des décors nettement plus riche. Elle amène aussi une musique de fond et des effets numérisés (K1 devait se contenter de bruitages au PC-Speaker. Oui, ça fait mal aux oreilles).

Au niveau du gameplay, passer de K1 à K4, c'est un peu comme passer de MegaMan à MegaMan X: de 2 directions de tir, on passe à 4. On ajoute des pentes, la possibilité de s'accrocher aux rebords des plate-formes et de monter/descendre à des barres de pompier. Le jeu gagne ainsi énormément en souplesse. On rajoute aussi un saut plus ou moins haut et qui réagit au millipoil. Le saut minimum couvre les 2 blocs au-dessus de Keen. Le saut maximum (sans pogo) en prend 3 de mieux. (Keen faisant lui-même 2 blocs de haut).

Si graphiquement, on pourrait pardonner à Keen Dreams d'être un cran en-dessous du niveau de K4, le fait qu'on ne sache pas encore s'accrocher au bord des plate-formes fait nettement plus mal. En introduisant une perspective ou le sol apparaît presqu'aussi large que le personnage n'est haut, on introduit aussi une incertitude sur notre capacité à atteindre une plate-forme donnée. Comme en plus on nous a retiré le pogo, ça donne un jeu où on va souvent rater ses sauts. De plus, si KD réagit aussi au millipoil, il n'a qu'une hauteur de saut (peu s'en faut) à l'instar du classique "Invasion of the Vorticon". On ira donc souvent se manger le plafond ou finir dans les pieds du monstre situé au-dessus de nous, sur une plate-forme jump-through.

La dernière grosse différence entre Dreams et le reste de la série, c'est qu'ici Keen n'a pas un pistolet, mais qu'il lance des pastilles-fleurs affectées par la gravité. Vu le nombre d'années depuis ma dernière partie de Keen "canoniques", on va dire que je devrais m'y faire. En revanche, leur effet est limité dans le temps. A l'époque, ça m'avait valu quelques morts évitables. Ici, ce sera l'occasion de voir ce que les joueurs de Bilou: Dream Land ressentiront. Verdict: des munitions limitées avec un effet temporaire = panne sèche assurée. On veillera donc à ce que Dreamland garde "munition consommée = effet permanent" tout comme SchoolRush.

Que dire de l'adaptation sur Switch, donc ? Eh bien, figurez-vous qu'ils nous ont ajouté des musiques. Si si. En gardant un style assez proche des sonorités adlib de l'époque (bien), mais assez moyennement inspirées sur les thèmes. On est plus dans l'ambiance de Keen 6 que de Goodbye Galaxy et ses thèmes inoubliables, selon moi. Il nous ont aussi rajouté des petites bulles de texte ça et là, avec des polices de caractères improbables ou des menus avec des icônes douteuses. Jugez plutôt! Mais sinon, à part le fait que les vies semblent illimitées, on est dans une adaptation assez fidèle du titre original (encore heureux, vu que les sources du jeu étaient disponibles sur Internet :P)


 


Le fruit-bouffi

 

Dans un ancien post, j'avais des piafs-saucisses-plate-formes. Dans un autre, j'ai des piafs-copains-qui-nous-transportent-à plusieurs...

I've got an old post where birds have been stretched and helium-inflated so they could be used as walkable platforms, and another, more recent one where birds have birdish shapes and use ropes to carry the player -- but you need many of them if you don't want to fall down.

What if I could get the new-one turn into the old-one for some specific locations, as result of a key-and-lock interaction ? A possible key would be something you can feed the bird with, but isn't exactly part of their diet. Maybe a raw berrybat ?

Et si on pouvait faire transformer un piaf-copain en piaf-plate-forme ? par exemple en lui faisant avaler quelque-chose qu'il ne digère pas vraiment ...

Une chauve-souris-baie pas mûre, par exemple, qu'on aurait été pêcher dans une caverne de la montagne ...

à creuser.

It would introduce a valid reason for having caves in addition to peaks within those mountains (bats like caves more than peaks).

Saturday, January 15, 2022

Le HDMA

 Sur SuperNES, un grand nombre d'effets intéressants dépend de la programmation du HDMA: une sorte de 'blitter' synchronisé sur les retours horizontaux (Pour ceux d'entre-vous qui n'ont pas regardé une vidéo sur l'Amiga la semaine dernière, traduisez "un co-processeur déclenché à chaque retour de ligne"). A-t-on quelque-chose d'équivalent sur Nintendo DS ?

Un DMA, c'est un circuit qui va se faire passer pour le CPU sur un bus et ordonner des lectures ou des écritures de données. C'est surtout utile quand on peut effectuer des transfers entre de la mémoire et des des registres hardware. Le processeur peut alors s'occuper d'autre chose. La première fois que j'ai joué avec ça, c'était pour mon modplayer SoundBlaster.

Les consoles Nintendo ont plusieurs 'canaux' DMA, chacun responsables d'un transfert entre une source et une destination. Il y a un mécanisme de priorité fixe entre ces canaux: si deux canaux essaient d'utiliser le bus mémoire simultanément, celui ayant le numéro le plus élevé est mis en pause le temps que celui ayant le numéro le plus faible ait fini. Le processeur, lui, passera après tous ces transfers DMA.

On retrouve dans les registres de contrôle DMAxCNT du GBA un champ 'trigger' qui permet à un canal de faire une pause entre deux écritures, cette pause s'arrêtant quand une certaine condition apparaît sur la machine. Parmi les conditions possibles, la fin d'une image ou la fin d'une ligne (vblank et hblank, respectivement). On y retrouve aussi des champs permettant de dire si les addresses mémoire doivent évoluer après chaque mot transféré. Si on veut par exemple reprogrammer un registre de scrolling à chaque ligne (pour émuler un effet de profondeur), on demandera que la source avance à chaque transfer (pour parcourir un tableau de valeurs) tout en restant à une adresse fixe pour la destination (le registre de scrolling, tiens!).

La nintendo DS reprend pour l'essentiel le mécanisme de DMA du GBA, sauf qu'on a 4 canaux pour l'ARM9 et 4 autres canaux pour l'ARM7. Seul l'ARM9 peut faire du H-DMA. Il peut aussi se synchroniser sur un nouveau type de trigger (j'aurais dû écrire "déclencheur" dès le départ): l'apparition de place dans la file de transfert vers le moteur 3D (le GXFIFO). La DS a aussi 16 canaux DMA supplémentaires pilotés par les registres sonores de l'ARM7, un pour chaque piste audio, mais ils sont totalement dédiés à cette fonction.

Des transferts DMA, j'en ai déjà fait pas mal dans mes homebrews, le plus souvent pour faire un 'memcopy boosté' entre la mémoire principale et la mémoire vidéo. Dans ce cas-là, le bit 'repeat' était à 0, et le canal s'auto-désactivait une fois le transfert terminé (c'est à dire que les N mots sont copiés). Pour notre 'effet de profondeur', on devrait programmer le canal DMA pour qu'il ne transfère qu'un seul mot (la nouvelle valeur de scrolling) au bon moment, mais activer le mode 'repeat', de sorte qu'un nouveau transfert ait lieu après chaque ligne.

Supposons maintenant qu'on veuille reprogrammer plusieurs registres à chaque nouvelle ligne. Les positions de début et fin de fenêtre, par exemple, pour faire un effet de rideau plus dynamique ou une vague d'encre géante. On peut évidemment utiliser un canal DMA pour chacun, mais s'ils ont le bon goût d'être l'un après l'autre en mémoire, on peut utiliser le dernière mode de gestion de la destination: le mystérieux 'avance et recharge'. Ici on passe au registre suivant après chaque mot transféré, mais quand le transfert redémarre (parce qu'on a activer le bit 'repeat'), on repart du registre-destination qui avait été programmé, et pas de sa valeur à la fin du transfert précédent.

edit: ah oui. Bon évidemment, la 'source' du transfert a continué à augmenter tout au long de l'image, ligne après ligne, et si on ne fait rien, il continuera d'augmenter aussi pendant le 'vblank' (équivalent-lignes inactives après le bas de l'image). Il faudra le reprogrammer avec la nouvelle valeur d'origine (ou une autre) au moment d'attaquer la nouvelle image.




Wednesday, January 12, 2022

Slopes Landed.

I think I got it working. There was one major flaw in my earlier design: stating that you can FALLTRHU a slope implied that you could no longer walk on it, as the walking controller tests for solid ground by checking whether it would be possible to fall down from the current location. Oh, not much. Just one pixel is enough to claim that you cannot walk anymore.

But the technique used for terrain collision detection -- cando -- assumes that we only do a move if we can do it over all the tiles covered during the move. That means the slope tiles should both allow us to fall through them (until ground height, at least), and not allow to start falling through them. To get that solved, I had to split the flag, having one bit telling whether we can start falling and one telling whether we can keep falling. Walker controller tests one of these bits, gravity controller tests the other one.

Then I had another issue, not properly computing the ground distance to see whether the move we cando actually remained over the ground. Let Bouli explain that...

We were at old position (ox, oy) and will move our 'hot spot' (the one that is kept in contact with the ground on uneven grounds) to (hx,hy). In order to know whether we're find with slope-landing, we compare hy - oy with the 'ground distance', which is construct with an appropriate sum of tile.groundheight() calls.

But groundheight() gives us a value relative to the bottom of the corresponding tile. -8 means the whole tile is solid. -2 means the first 2 pixels of the tile are solid, the rest is air. 0 means the whole tile is air. That was quite quickly remembered and accounted for. The other part to take into account is that the start of the darkblue 'vertical motion vector' may be anywhere within the first tile. If we're in the 4th pixel of the tile and the last pixel of the tile is solid, then only hy - oy < 3 are uninterrupted moves.


Sunday, January 09, 2022

Land on Slope

There are many things that got fixed over my holidays, and many things that remain to be done before I can claim the 3 rooms "done". I had to pick one for the last week-end ... it seemed wise to pick something that I'd likely not have enough focus to work on during the evenings of a regular week. "Land on slopes" seemed the right one to pick.

So far, only the "walk" (behaviour) controller is aware of slopes. For the rest of the code, the world is all made of square tiles, and the properties of a tiles are homogeneous over that square. The result is that if you try to land from a jump on sloped ground, you're very likely to end up floating over the ground until you start walking.


I gave it a first try yesterday, opening the debugger, seeing what happens when I'm entering such a tile, designing a patch, compiling it, trying it, discover that it wouldn't work, refine it, and repeating the cycle. Over and over.

It wouldn't work. First because the slope tiles couldn't be fallen through. There's no need to try working around it: they *must* be made fall-through. Second because slopes are currently complemented by walk-through-but-don't-fall-through blocks that ensure smooth walk, but interfere with falling. I had that discussed with the Undisbeliever in the past, as it was a difference between our implementations, and the solution will be to replace them with a 'sloped' ground that actually is square.

But the ultimate reason of my failure is that I was trying to provide a solution for 'fall on the sloped ground' as if we'd have the last row of tiles all made of F_SLOPE tiles. The reality is much more diverse: there are so many 'corner' cases that we can hardly call them 'corners' at all.

I have a replacement design sketched, which I'll give a try in the afternoon. Amusingly, it looks a lot like what (I've understood) happens in Sonic the Hedgehog engine: consider the whole column of tiles on top of the desired 'new hot spot position' and figure out the 'ground height' in that column. Then make sure the move planned so far doesn't work past the ground.

Do that every time. If done right, it doesn't matter how many sloped tiles were encountered when checking that we cando() the move.

Well, that was the plan, but for some reason, it is not yet quite working. And for some (possibly other) reason, it managed to break walk-on-slopes despite my care to avoid so.

edit: fixed

Wednesday, January 05, 2022

Les Capris et tutti quanti.

Avec les enfants qui veulent aussi jouer, les niveaux plus longs et une fonction "prendre une vidéo en jouant", je suis moins tenté sur Switch de mettre mon jeu en pause et de commencer à parler/redessiner quelque-chose. Quand je le fais quand-même, c'est souvent pendant que les enfants jouent, et donc des petits schémas techniques griffonnés plutôt que des croquis.

Mais l'an dernier, j'avais quand-même pris le temps de passer en revue mes vidéos de Donkey Kong Tropical Freeze pour voir un peu ce qu'il y avait de particulier comme type de plate-formes mobiles (avec évidemment la Peaks Zone en tête).

C'est aussi vers DKTF que je me suis orienté il y a quelques jours pour essayer de trouver des idées de 'niveau aérien' et c'est en voyant la tempête du niveau 3-3 emporter tout et n'importe quoi que j'ai réalisé que "bah, en fait, j'ai pas besoin de me creuser la tête pour trouver des animaux succeptibles de faire plate-forme volante: il suffit que je dise qu'il y a des courants d'airs et que je trouve des choses assez légères pour se faire emporter. C'était le premier "débloqueur".

Puis en bas de la feuille j'ai commencé à dessiner ces arbres tout tordus et leur branche m'ont donné envie de tendre des cordes entre les deux pour que Bilou puisse passer dessus. C'était l'élément de level design qui m'avait manqué jusque là.

It's been 2 years since I decided to have a 'mountains peaks zone' for Bilou's Dreamland, and even before that, I had ideas to use sheep/goat-like monsters to populate it (plus birds). But none of this led to any monster design or level design post. I just couldn't come up with anything to draw. Hopefully, it changed lately. It all started with a funny tree I draw on a sketch while collecting gameplay ideas from Donkey Kong: Tropical Freeze videos (and other possible videos about 'air world', btw). It had hook-like branches, with no leaves on it. It was appealing for a string bridging from one to another. It felt natural that Bilou would use that string to move from one place to another when there's nothing 'floating' inbetween...

I tried to imagine what could prevent him from doing so. Like a tightrope dancer. I tried to recycle my goat-idea and had fun giving it a Ice-Kirby pose. It seemed to work like magic. It's not an evil opponent, just someone who happens to be dangerous for you, in this case because you happen to have missed that you're on a circus-training area. The idea was working well, so it was time to pick up proper pens, proper paper and start drawing that for real.

Une fois la corde tendue et Bilou accroché dessus se posait la question: qu'est-ce qui pourrait le mettre en danger. J'avais depuis longtemps l'intention de mettre des espèces de bouquetins dans la montagne. Une influence du premier Rayman.

Ça s'est mélangé dans ma tête avec une posture de Kirby-patineur avec son pied en l'air. Ah, ce serait tellement plus facile pour Bilou s'il avait une formation de funambule ...

Mais pour un bouquetin, ça devrait être un jeu d'enfant, non ? Une fois cette idée dessinée, je savais que je tenais le bon bout.

Restait à voir si tout ça est assez "Bilouteux". J'entends par là, est-ce qu'on se sentira sur la planète des chauve-souris-baies et des crayons soldats ? Les rochers troués comme du gruyère sont rigolos, les arbres sont bien quand ils sont nus mais un peu plus classiques avec leur look de palmier quand ils ont encore leurs feuilles.

Probablement que Joke trouverait que tout ça manque de champignon. Alors j'ai repris mon dessin et j'ai gribouillé des chapeaux de champignons par-dessus tous mes feuillages d'arbre. ça marche. c'est même ce que j'ai de plus convainquant pour justifier les "feuilles parasols" servant de plate-formes volantes. Alors allons-y: ce seront des hybrides arbres/champignons dont le chapeau se laisse emporter par le vent pour aller disséminer plus loin une fois qu'il est bien mûr.

So I started drawing all the stuff I had barely sketched so far, leafless trees, ropedancing goats, watching goats, large flying structures brought up by upwards winds ... a bit too big for a single leaf given the trees size. You'll notice that this early sketch also features sorts of 'beaks' within the rock. That's something I had noted to lead to interesting look, but which doesn't seem to work well with the 'cheddar-holes'. And I definitely want to keep cheddar holes :P

Later on, on a walk, I realised that a pal known as 'the BilouMaster' would likely suggest that the scenery needs more mushrooms. So why not claim that those trees have mushroom-like tops instead of leaves ? That would give me free 'floating platforms in upwards winds', free umbrella-like thing to hold while a goat is ropedancing and contribute to the overall 'Bilou, not earth' feeling of the area. I overdrawn my sketch a bit .. it seemed to work. I kept it.

A ce stade, j'ai repris ma liste de plate-formes spéciales dans DKTF. La première, c'était une plate-forme qui se met en mouvement en fonction de la position de DK sur la plateforme: à gauche, elle part à gauche; à droite, elle part à droite.

ça marche impeccablement avec un chapeau de champignon. En fonction de la hauteur des colonnes d'air, de leur intermittence ou non, je peux construire un niveau aussi varié que la traversée en montgolfière de DKC2.

DKTF propose un joyeux nombre de variations sur ce thème, avec de l'électricité ou des plate-formes incomplètes, mais une des plus remarquable, c'est peut-être celle qui la combine avec la mécanique "s'accrocher" introduite dans Donkey Kong Returns.

Ça tombe bien: j'ai justement envie de faire de "Dream Land" le jeu où Bilou peut justement s'accrocher à tout et n'importe quoi. aux branches des arbres, aux racines souterraines, au cous des bestioles qui infestent la pyramide ... Et évidemment aux cordes des ponts de cette nouvelle zone.

Alors du coup, ça nous donne une manière bien plus intéressante d'utiliser la combinaison 'une corde transportée par deux oiseaux: Bilou au centre, les charges sont réparties et la corde s'élève emportée par les deux oiseaux. Si on se décale d'un côté, ça augmente la charge pour l'oiseau correspondant et on dévie de ce côté tout en descendant lentement.

It felt like it was the right time to pick up my never-blogged list of original kind of platforms in Donkey Kong: Tropical Freeze, and see whether I could match them with things that would work in the newly defined Peaks Zone.

A platform that starts moving left or right as you move to its left or right, for instance. That could be a floating mushroom top. Another one where you're hanging instead of landed ? Well, since "I don't see why Bilou wouldn't use the ropes" would work well here too. When there are just 2 birds and one rope, they're just strong enough to lift him if Bilou's weight is equally distributed. Otherwise, you'd dift in one direction (and slightly slide down).

Mais revenons à nos bouquetins. Un autre petit schémas de plate-forme que j'avais dans mon cahier montrait une bascule avec un obstacle à pic passant d'un côté à l'autre.

Alors bon, on ne va pas vraiment commencer à rajouter des boules à picots ici (je n'ai pas les fruits géants de DK pour le justifier), mais dans la catégorie 'obstacle à roulette', je peux profiter de l'idée "font leur cirque pour introduire un autre type d'acrobate.

et le voilà. Irrésistible. Adorable mais redoutable.

Can the new goats also be used in some DK-like platform mechanics ? Sure! There was one about a platform that tilts back and forth and makes a spiky hazard roll left and right along with its movement. We can sure find something that rolls in a circus setting, right ? Just add a happy goat/sheep thing on top of it and voilà.

And while I was telling all that to my brother, I've got a flash-vision of happy goats appearing from the bottom of the screen as if there was a hidden trampoline and you could make your way by carefully bouncing from one goat-back to the next. 

Puis en racontant tout ça à mon frangin hier me vient l'idée d'un passage où on voit tout simplement des bouquetins surgir du fond de l'écran, faire leur petite pose et retomber. On doit passer à dos de 'mouton' pendant ce temps-là.

au moment de le dessiner, vu que je n'ai pas de "fond d'écran" pour masquer ce qui se passe, j'ajoute à nouveau une corde. il rebondissent dessus comme sur un trampoline. Un clin d'oeil à Sleepwalker.

Autant dire que ça aussi, il vaudra mieux que ça n'arrive pas pendant que Bilou est suspendu à la corde.

Of course 'a hidden trampoline' isn't something easy to draw, so I replaced it by a string. A string you should better not try to use because you can't hold to a strumming string. There were more platforms styles in DKTF, of course, like that giant flower that starts bending when you lose its center, but there's already a good deal of things to implement here, isn't it ?

Il en reste, évidemment. Je n'ai pas essayé de convertir les fleurs géantes qui basculent, celles qu'on déplie en se suspendant à un truc qui pendouille ni les tours de plate-formes qui s'enfoncent (et donc se déroulent) quand on marche sur l'une d'elles. Mais bon, je crois qu'on peut dire qu'il y a déjà de quoi voir venir, non ?

Tuesday, January 04, 2022

Puzzles in Rayman Legends

 

*deline (re)jouait à un niveau de Rayman Legends, pour changer un peu. En l'occurence "Encordé". On y joue pas mal sur des cordes à couper à l'aide de la grenouille volante. et sur la manière d'apprendre au joueur d'éviter la précipitation pour faire un meilleur score.

Rayman Legends may not be the game you expect to pick if you're looking for hints about how to put puzzles in your platformer, granted. Yet, watching my daughter playing 'encordé' level made me realize that lots of things that are obvious to me aren't for less trained players. The simple mechanics of cutting ropes has been used to create design patterns where player has to anticipate the outcome of their actions and avoid acting hastingly if they want a high score.

Je trouve intéressant  travers sa manière de jouer le fait qu'une petite action (couper les cordes) capable de transformer le niveau rend certains "puzzles" un peu moins évidents: il faut parvenir à imaginer ce à quoi le niveau ressemblera une fois l'une ou l'autre action exécutée pour pouvoir choisir la meilleure.

C'est une chose que j'aurais eu tendance à sous-estimer sans elle, tant j'ai pris l'habitude de ce genre d'anticipation en jouant à un jeu de plate-forme.

The interesting part of it is of course when cutting the rope transforms the level. Sometimes the outcome of such a transformation is obvious, but it was completely new to her, so I spotted many "oh ? zut. I should not have cut this" or "ah! yeah, if I cut that, I'll get a bridge to there".

On retrouve aussi ce côté-là dans les transformations de niveau de HoB et les rotations de FeZ. FeZ rend une erreur de jugement moins punitive en permettant de défaire n'importe quelle rotation par une contre-rotation (et du coup permettant de construire des puzzles plus complexes à partir de ces actions simples).

HoB, comme Rayman, favorise les actions définitives, mais le plus souvent les actions sont indispensables et agissent comme une clé/porte plutôt que comme un véritable morceau de puzzle.

Thinking about it, there are similar level transformations in e.g. FeZ and Hob, although not quite identically. "Puzzles" here are more or less one-time challenges. If you don't get it and miss to act as needed, your chance is gone. In FeZ, transforming the level typically involves world rotations which can be undone and redone at will, just like sokoban let you roll back last actions at will.

Hob, on the other hand, has once-forever transformations, but won't let you do a 'wrong' one. There is only one option (the good one), and the game waits for you to find it. They are mostly fancy locks, but still they meet their puzzling goal in that what come next was hidden, and you have a chance to guess it before it gets revealed.

It's a nice trait, leading to fun/satisfying 'Eureka' moments, which I'll have to find a way to inject into Bilou as well ... somehow... some day.

Il faudra que je réfléchisse à une manière d'importer ce genre de moment-Eurêka dans Bilou aussi ...

Après tout, même Super Mario pouvait y prétendre avec ses blocs-briques qui peuvent servir de plate-formes mais peuvent être détruites par un joueur trop impatient (ou imprécis).