Aller au contenu principal

Session 132duodecimus (suite 13) — Phase C : refonte ASM-fidele des portes

Bugs portes adresses

L’utilisateur a remonte 4 bugs sur les portes (et des bugs similaires sur
les lifts, traites separement). Plutot que des patchs ponctuels, refonte
complete du modele d’animation et de collision en s’alignant sur le
fonctionnement ASM exact ({@code newanims.s::DoorRoutine}).

Bug observe Cause racine Solution Phase C
UV mal mappe (textures qui glissent) V-shift par segment, modele state[0..1] UV statique (jamais touche), regen positions seulement
On peut traverser la porte fermee Collision liee au state, pas au plafond reel Collision directement liee a {@code currentRoofY}
Espaces entre textures (gaps biais) {@code DOOR_OFFSET=0.08f} + 2 faces par edge {@code DOOR_OFFSET} retire, dedoublonnage par edgeId
Alien bloque l’ouverture (pas porte) Aucune notion de doorLocks Lecture des items.doorLocks + hp + typeId==0

Refonte du modele

Avant : etat porte = {@code state ∈ [0,1]} (pourcentage d’ouverture),
animation par UV-shift + translation Y des panneaux. Collision liee a un
seuil de state.

Apres (ASM-fidele) : etat porte = {@code currentRoofY} (Y JME courant
du plafond zone-porte, evolue entre {@code closedRoofY} et {@code openRoofY}).
C’est exactement ce que fait l’ASM avec {@code ZoneT_Roof_l} (cf. ligne
1660 de {@code newanims.s} : {@code muls #256,d3 ; move.l d3,6(a1)}).

La geometrie est regeneree chaque frame :
– Sommet du panneau fixe a {@code corridorRoofY} (plafond couloir)
– Bas du panneau = {@code currentRoofY}
– Quand ferme : bas = sol couloir -> panneau plein
– Quand ouvert : bas = plafond couloir -> panneau de hauteur 0 (cull)

Le plafond polygonal mobile suit par {@code setLocalTranslation(0,
currentRoofY – closedRoofY, 0)}.

Aucune manipulation d’UV : les textures restent figees, ce qui elimine
tout glissement texture pendant l’animation.

Suppression de DOOR_OFFSET

La session 103 avait introduit {@code DOOR_OFFSET=0.08f} pour decaler les
2 faces d’un edge (1 face par couloir voisin) afin de leur donner une
epaisseur visible. Probleme : ces 2 faces decalees creent un gap visible
quand on regarde la porte de biais (effet « double mur » avec un trou au
milieu).

La solution ASM-fidele est de ne rendre qu’une seule face par edge, et
de laisser le materiau cull-off afficher les 2 cotes naturellement. Le
dedoublonnage est fait dans {@code DoorAccum.hasEdge(eid)} : la 2eme
occurrence du meme edge dans une zone voisine est ignoree.

Conditions ASM door0..door5

Reference ASM : {@code newanims.s::tstdoortoopen} (lignes 1700-1750) +
{@code defs.i::DR_*}. Implementation des 6 cas dans
{@code DoorControl.shouldOpen} :

  • door0 (DR_Plr_SPC) : ouverture si touche action enfoncee. Implementation :
    flag {@code DoorControl.PLAYER_USE} alimente par {@code GameAppState}
    via {@code A_USE} (touche E).
  • door1 (DR_Plr) : ouverture des qu’on est proche (pas de touche).
  • door2 (DR_Bul) : tir requis. Non implemente, fallback comme door1.
  • door3 (DR_Alien) : alien declencheur. Non implemente, fallback comme door1.
  • door4 (DR_Timeout) : ouverture inconditionnelle (porte automatique).
  • door5 (DR_Never) : ne s’ouvre jamais.

doorLocks aliens

Les items {@code typeId=0} (aliens) ont un UserData {@code doorLocks}
(bitfield 32-bit, ASM {@code EntT_DoorsAndLiftsHeld_l}) qui indique les
portes verrouillees par cet alien. Si au moins un alien-garde vivant
({@code hp > 0}) avec {@code doorLocks != 0} est present dans la scene,
{@code DoorControl.isLockedByAlien()} retourne true et la porte refuse de
s’ouvrir.

Implementation pragmatique : on ne match pas le bit precis dans
{@code Anim_DoorAndLiftLocks_l} (qui necessiterait un index global de
porte). Tout alien-garde vivant verrouille TOUTES les portes a doorLocks.
Proxy raisonnable car en pratique chaque garde tient au plus 1-2 portes
proches. Plus precis qu’avant (aucune notion d’aliens-bloqueurs).

Nouveaux UserData LevelSceneBuilder

Sur les Nodes {@code door_*} :
– {@code closedRoofY} : Y JME du plafond zone-porte ferme (= {@code -floorH/Y_SCALE})
– {@code openRoofY} : Y JME du plafond zone-porte ouvert (= {@code -roofH/Y_SCALE})
– {@code corridorRoofY} : Y JME du plafond couloir (sommet panneaux)
– {@code corridorFloorY} : Y JME du sol couloir
– {@code doorZoneId} : ID zone-porte (deja present)

Retires : {@code yTop}, {@code yBot}, {@code animDist} (ancien modele
pourcentage).

Sur les Geometry seg : ajout de {@code edgeId} pour identification
unique. Retire : {@code animDist}.

Touche action E

Ajout d’un {@code A_USE} dans {@code GameAppState} mappe sur la touche
E. Equivalent du SPACE Amiga d’origine pour l’action (le SPACE JME
est deja pris pour le saut). Tant que E est tenue, {@code DoorControl.PLAYER_USE = true}.

Limitations connues

  • {@code WallCollision} n’a pas de {@code removeSegment} — pour l’instant
    on ajoute des segments de collision quand la porte est fermee, mais on
    ne peut pas « defaire » cet ajout proprement. {@code addSegment} est
    idempotent (les doublons sont toleres par l’algo de collision), donc
    c’est OK pour la 1ere passe. Si bug residuelle observee, faudra
    ajouter un mecanisme on/off par segment ou remettre {@code clear()}
    centralise + reconstruction par {@code DoorControl} chaque frame.
  • door2 (BULLET trigger) et door3 (ALIEN trigger) sont rabattues sur
    door1 (PLAYER_TOUCH). Compromis pragmatique pour ne pas bloquer le
    niveau A (premiere porte zone 5, raiseCondition=1 = door1, donc OK).
  • Conversion vitesse {@code openSpeedJ = animDistJ * (zlOpenSpd*25) / hEditor}
    : le 25 est le tick rate Amiga. Pas calibre finement. A revoir si
    l’animation est trop rapide/lente.

Fichiers modifies

  • {@code LevelSceneBuilder.java} : refonte boucle ZDoorWall + DoorAccum
  • boucle generation portes + plafond mobile.
  • {@code DoorControl.java} : reecriture complete (modele
    {@code currentRoofY}, conditions ASM, doorLocks aliens).
  • {@code GameAppState.java} : ajout {@code A_USE} (touche E) ->
    {@code DoorControl.PLAYER_USE}.

Tests prevus

  • {@code ./gradlew buildScenes} doit passer sans erreur.
  • Niveau A : la premiere porte (zone 5) doit s’ouvrir au contact
    (raiseCondition=1 = door1).
  • Validation visuelle : pas de gap entre les pans, panneau plein du sol
    au plafond, ouverture qui revele la zone interieure proprement, pas
    d’UV qui glissent.
  • Validation collision : mur plein quand ferme, passage libre quand ouvert.
  • Si une porte raiseCondition=0 (door0) est rencontree : confirmer que
    l’ouverture necessite la touche E.

Lifts (Phase C suite)

Les lifts ont des bugs analogues (sol qui ne pousse pas le joueur
correctement, etc.) mais sont traites separement apres validation des
portes. La logique sera similaire : modele {@code currentFloorY} au lieu
de {@code state}, conditions ASM lift0..lift3, plus de « sol qui flotte ».

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *