Friday, December 27, 2019

Leilani slopes

The tweet popped while I was doing mental checks on my revised tiled engine, and especially how it would handle more slopes than the previous one: Ishi(soft) finally decided to introduce slopes in Leilani's Island. And while I was looking for convenient ways to encode more than one array of tile_height[type][offset], I was surprised that his approach wasn't not requiring any such array.

Bon, le tweet est tombé comme un pavé dans la mare pendant que je réfléchissais aux problèmes que le mélange des pentes et des blocs à la physique modifiée risquait de poser: on peut aussi faire des pentes sans avoir pour autant besoin de modifier son moteur de jeu pour y mettre des fonctions du genre "doslopes". C'est ce que nous propose Ishi dans sa prose décrivant le moteur de jeu de Leilani's Island. Et que faire d'autre si on ne veut pas simplement faire un clone de Mario 1? Eh bien par exemple générer à la volée des "ascenseurs" sur lesquels les personnages vont se déplacer et dont la vitesse verticale donne l'illusion qu'on suit bel et bien la pente.

(C) Ishi
Instead, the world-collision engine would detect sloped ground and generate sort of "lift" objects that are tied to a specific X location, but adjust their Y location to the X position of the character that triggered them. It allowed enough flexibility to make me think twice before dismissing the approach. One of the benefit of the approach is that the code running the is-there-ground check still happily believes the character have solid ground all around them:

This fixes the problem with enemies turning around on slopes. When they do their collision check, they find solid ground in front of them - because as far as they're concerned, they're on a flat surface.

There was one major restriction, though: Ishi decided to go for a single type of slope (22.5°) where X-to-Y offsets function can easily be computed by shifts and additions. But I personally want more. More angles and some curved ground as well. We could still have that in Ishi's engine, but it would require picking a tile_height[offset] array according to the slope type and pass it to the "lift" object.


C'est séduisant, c'est sûr. Mais ce n'est pas allé sans mal pour autant, et à la lecture de tous les "corner cases" qu'il a dû prendre en compte, je ne suis pas certain d'avoir envie de jeter mon implémentation actuelle pour suivre son exemple. Entre autres, une des choses qui permet à Ishi d'éviter de devoir utiliser plusieurs types de pentes, c'est qu'il s'est limité à un seul angle (22.5°) pour lequel on peut facilement déduire la position verticale de l'ascenseur à partir de la position horizontale du personnage à l'intérieur du bloc. Mais moi je veux plus de variété. Il faudrait donc du coup plusieurs comportement d'ascenseurs et un code qui produit le bon à partir du type de pente que l'on a rencontré.

And the approach apparently has its own corner cases that need to be addressed, sometimes with special edge-of-slope types. The approach I'm using so far has its own corner cases, which were mostly resolved by using jump-through tiles (which are also walk-through) next to sloped tiles to avoid introducing artificial walls within the slope. That's precisely what needed more thinking when introducing "physics modifiers" tiles.

Well, anyway, don't miss the full post on Ishi's tigsource thread. It's very detailed and informative.

PS: it feels a bit odd to write a post about someone else's work here, but I've kept re-visiting the browser tab with the forum with the hope that I wouldn't forget it if there's anything important to find there ... for one week or so.


 Edit: apparently, there's one thing I understood terribly wrong: there is no 'lift object' generated. Just a collision rectangle returned by a function. A different rectangle every frame, but its lifetime is restricted to the duration of Character::think().

Sauf que ... en réalité il n'y a pas "d'objet-ascenseur" dans l'implémentation. Chaque fois qu'on demande au 'monde' s'il y a collision avec le sol, il nous renvoie un rectangle adapté à notre position. Ce n'est pas un objet-plate-forme qui aurait une durée de vie dynamique, juste une valeur de retour qui nous sert de contexte pour les prochains tests le temps d'un cycle de calcul des mouvements du personnage.

No comments: