Symptomes (zone 104, level A)
-
« Une porte pleine avec chevrons devant le lift » — en arrivant
par le couloir bas (zone 103), le passage vers la cabine etait
bouche par un panneau chevron au lieu d’etre ouvert. -
« Lift va trop haut, pas assez » — quand le joueur monte, le
sol du lift s’arretait àtop=-64Amiga (=+2 JME), mais le sol
de la zone d’arrivee (zone 105) est àfloorH=-8(=+0.25 JME).
Le lift depassait de +1.75 JME (~56 cm) au-dessus du sol couloir.
Le joueur arrivait perché et devait « descendre une marche » pour
sortir.
Diagnostic
Bug 1 — walls couloir<->lift rendus statiquement
Le JSON declare lifts[].walls[].edgeId (500 et 510 pour zone 104) :
ce sont les edges des passages couloir<->cabine. Dans l’ASM original
(newanims.s::LiftRoutine), ces walls sont rendus dynamiquement
(visibles selon position du lift).
Le code Java (session 99) collectait ces edges dans liftWallEdges
mais avait laissé un TODO (« utiliser pour skip dans une session
future »). Resultat : ces walls etaient rendus comme n’importe quel
autre wall, avec leur clipIdx (=5, texture chevron) et leur hauteur
full-height. Visuellement ça faisait un panneau plein chevron à
l’entree du lift.
Bug 2 — yHigh non clampé au sol d’arrivee
Le code calculait yHigh = -top/SCALE directement, sans tenir compte
du sol des zones voisines. L’ASM clamp aussi a top/bottom, mais
l’editeur Amiga avait choisi top=-64 qui depasse intentionnellement
le floorH du couloir d’arrivee — pas naturel en 3D.
Fixes
(1) Skip walls liftWallEdges dans la boucle principale de
LevelSceneBuilder.buildScene (juste après le check
doorEdgesGlobal) :
int wallEidLift = findEdgeIdForSegment(lpi, rpi, pts, edgesFull, z.edgeIds());
if (wallEidLift >= 0 && liftWallEdges.contains(wallEidLift)) {
continue;
}
Resultat : le passage devient visuellement ouvert. Les lift_side_*
de la cabine (crées au build) sont déja skippés sur ces memes edges
(session 102), donc l’interieur du lift reste ouvert lui aussi.
(2) Clamp dynamique de yHigh/yLow aux zones voisines
Dans la boucle de creation des liftNodes, parcours des walls de la
zone-lift dont l’edge est dans liftWallEdges (= passages reels).
Collecte des floorH des otherZone voisines :
for (int[] w : liftWallsZone) {
int oz = w[5];
if (oz <= 0 || oz == zid) continue;
int weid = findEdgeIdForSegment(...);
if (weid < 0 || !liftWallEdges.contains(weid)) continue;
ZD nz = zones.get(oz);
float yNeighborFloor = -nz.floorH() / SCALE;
maxNeighborYFloor = max(maxNeighborYFloor, yNeighborFloor);
minNeighborYFloor = min(minNeighborYFloor, yNeighborFloor);
}
Puis :
– Si lift monte (yHighEdit > yRest) : yHigh = min(yHighEdit, maxNeighborYFloor)
– Si lift descend : yLow = max(yLowEdit, minNeighborYFloor)
Effet pour zone 104 :
– Avant : yHigh = +2 JME (lift dépasse de +1.75 JME)
– Après : yHigh = +0.25 JME (= floorH zone 105) — le lift s’arrete
pile au sol de la zone d’arrivee
Note ASM-fidelite
Le fix #2 dévie volontairement de l’ASM. L’ASM clamp simplement à
top quoi qu’il arrive. Mais en 3D le dépassement est moche — on
préfère l’aligner sur le sol d’arrivee. Si on veut revenir au
comportement ASM, c’est à 1 ligne de retirer.
Le fix #1 est aussi une simplification : l’ASM rend ces walls
dynamiquement (visibles selon position du lift). On fera ca dans une
session future si besoin.
Petit nettoyage
LiftControl.java::controlUpdate avait du code mort :
speed = -openSpeedJ; // ecrit puis...
speed = openSpeedJ; // ...immediatement ecrase
Reduit à une seule affectation speed = openSpeedJ; avec commentaire
clair sur la convention JME (Y vers le haut, donc speed > 0 pour
monter).
Pour tester
./gradlew buildScenes run
(Rebuild necessaire pour fix #1 et #2.)
Observations attendues :
– Le passage du couloir bas (zone 103) vers le lift est vide
visuellement — plus de panneau chevron qui boucherait l’entree.
– Quand le joueur monte sur le lift, le sol s’arrete pile au niveau
du sol de la zone 105 — plus de « marche descendante » à la sortie.
– La cabine elle-meme garde ses 4 « parois » laterales (sauf sur les
edges 500 et 510 = passages, deja skippés session 102).
Limites connues
- L’ASM rend les walls couloir<->lift de manière dynamique (visibles
selon position courante du lift). On les supprime juste pour le
moment. Si on remarque des trous visuels (ex : voir le ciel/vide
par la porte du lift quand il est en mouvement), on devra implémenter
le rendu dynamique. - Le fix #2 dévie de l’ASM. Si un autre niveau a un design où le lift
doit vraiment monter au-dessus du sol voisin, ce fix le clamp à
tort. Pour zone 104 c’est correct.
Fichiers modifiés
tools/LevelSceneBuilder.java:- boucle des walls : skip si l’edge est dans
liftWallEdges - boucle des liftNodes : calcul de
maxNeighborYFloor/
minNeighborYFloorvia lesliftWalls, clamp deyHigh/yLow world/LiftControl.java: nettoyage du dead code (speed =immediatement écrasé).
-openSpeedJ