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 F_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.

Là, je pense que je le tiens. Il y avait un défaut majeur dans mes premiers essais: considérer qu'on peut tomber à travers une pente en lui donnant la propriété "F_FALLTHRU" implique automatiquement qu'on ne peut plus marcher dessus: le contrôleur "walker" s'assure que le sol est solide en testant s'il serait possible de tomber à travers ... pas beaucoup: juste quelques pixels, mais si ça marche, ça suffit pour indiquer que marcher n'est plus possible.

Mais la technique utilisée pour les collision avec le sol (le "cando()") part du principe que on ne peut faire un déplacement que si l'entièreté de la zone concernée permet ce type de déplacement. On ne peut nager qu'entièrement dans F_WATER, on ne peut grimper qu'entièrement sur F_LADDER, etc. Mais donc un tile de type "pente" doit à la fois nous permettre de tomber à travers lui (au moins jusqu'à atteindre l'altitude du sol) et nous empêcher de commencer à tomber. Le seul moyen de réconcilier les deux, c'est de dédoubler le flag: avoir un bit indiquant "autorise le début de chute" (F_START_FALLING) et un autre "autorise de continuer à tomber" (F_FALLTHRU). Un pour le contrôleur de marche (walker), l'autre pour le contrôleur de gravité. 

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 (F_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.

Mais ce n'est pas de ça que Bouli veut vous parler. Une fois le problème des propriétés réglé, il reste à calculer correctement la distance jusqu'au sol. Supposons qu'on parte d'une position (ox, oy) et qu'on veut déplacer le "hotspot" (le point qui doit rester en contact avec le sol dans une pente) en (hx, hy). Déterminer si on a atterri sur une pente, c'est comparer la distance hy - oy avec la distance jusqu'au sol, à partir des résultats de tile.groundheight().

Seulement, ce nous donne une altitude par rapport au bas du tile. -8 pour un tile entièrement solide, -2 pour indiquer que les 2 pixels du bas sont solides et qu'il y a ensuite de l'air, 0 pour un tile constitué uniquement d'air. Une fois qu'on a relu un peu sa doc, c'est vite traité. Par contre, le début du vecteur-mouvement (en bleu foncé sur le schéma) peut se trouver n'importe où dans le tile de départ. Si on est au 4eme pixel d'un tile dont seul le dernier pixel est solide alors seuls les mouvements tels que hy - oy < 3 pourront se faire entièrement.

No comments: