Aller au contenu principal

Session 112 — Ramassage des items au sol (pickups)

Probleme

Les items au sol etaient simplement affiches comme sprites (apres correction
textures de la session 111), mais le joueur pouvait passer a travers sans
rien ramasser. Pas d’inventaire, pas de feedback. Il fallait :

  1. Detecter la collision joueur ↔ item (memes conditions que l’ASM)
  2. Lire les tables {@code GLFT_AmmoGive_l} / {@code GLFT_GunGive_l} pour
    determiner ce que la collecte donne (sante, ammo, arme, etc.)
  3. Appliquer ces deltas a l’inventaire du joueur
  4. Retirer le sprite visuellement
  5. Afficher un feedback (message + indicateur HUD)

Diagnostic ASM

Detection collision (cf. {@code newaliencontrol.s::Plr1_CheckObjectCollide},
ligne ~1700) :

; meme zone ?
move.w  Plr1_Zone_w, d7
cmp.w   ObjT_ZoneID_w(a0), d7
bne     .NotSameZone
; difference Y < ODefT_CollideHeight_w ?
move.l  Plr1_YOff_l, d7
asr.l   #7, d7
sub.w   4(a0), d7
cmp.w   ODefT_CollideHeight_w(a2), d7
bgt     .NotSameZone
; distance XZ < ODefT_CollideRadius_w ?
move.w  ODefT_CollideRadius_w(a2), d2
muls    d2, d2
jsr     CheckHit

Application de la collecte (cf. {@code Plr1_CollectItem}, ligne ~1640) :

lea     GLFT_AmmoGive_l(a2), a1
add.l   #GLFT_GunGive_l, a2
muls    #AmmoGiveLen, d0       ; AmmoGiveLen = 22*2 = 44
muls    #GunGiveLen,  d1       ; GunGiveLen  = 12*2 = 24
add.w   d1, a2
add.w   d0, a1
; a1 -> ammoGive[defIdx]  : [Health, JetpackFuel, Ammo[20]]
; a2 -> gunGive[defIdx]   : [Shield, JetPack,    Weapons[10]]
CALLC   Game_AddToInventory     ; merge dans Plr1_Invetory

Tables d’inventaire (offsets dans {@code test.lnk}, calcules depuis defs.i) :

Offset Table Taille Description
0x5A08 GLFT_ObjectDefs 30×40 ODefT (behaviour, gfxType, colRadius…)
0x5EB8 GLFT_ObjectDefAnims_l 30×120 Anim repos (cf. session 111)
0x6CC8 GLFT_ObjectActAnims_l 30×120 Anim active (computers en pulsation, etc.)
0x7AD8 GLFT_AmmoGive_l 30×44 InvCT par def : Health, JetpackFuel, Ammo[20]
0x7FF8 GLFT_GunGive_l 30×24 InvIT par def : Shield, JetPack, Weapons[10]

Architecture Java (4 fichiers modifies + 2 nouveaux)

Pipeline donnees

  1. LnkParser.java : ajout des constantes
    OFS_OBJECT_ACT_ANIMS=0x6CC8, OFS_AMMO_GIVE=0x7AD8, OFS_GUN_GIVE=0x7FF8
    et des methodes getAmmoGive(defIdx) / getGunGive(defIdx) qui lisent
    les structs InvCT (22 WORDs) et InvIT (12 WORDs).

  2. LevelJsonExporter.java : ajoute ammoGive et gunGive (tableaux
    de 22/12 ints) dans chaque entree de objects[] du definitions.json.

  3. LevelSceneBuilder.addItems : expose colRadius et colHeight en
    userData sur chaque sprite, pour permettre au PickupSystem de tester
    la collision sans avoir a re-lire les definitions.

Runtime gameplay

  1. combat/PlayerHealthState.java (nouveau) : pendant de
    PlayerCombatState, gere les champs PlrT lies a la sante et items :
    health / maxHealth (PlrT_Health_w) – default 200
    jetpackFuel / maxJetpackFuel (PlrT_JetpackFuel_w) – default 200
    shield (PlrT_Shield_w)
    jetpackOwned (PlrT_Jetpack_w)
    keysMask (PlrT_Keys_b, bitmask 8-bit)

  2. world/PickupSystem.java (nouveau) :
    – Charge les definitions d’objets depuis definitions.json (ammoGive +
    gunGive + colRadius/colHeight + sfx).
    update(playerPos) : balaye itemsNode, pour chaque sprite
    COLLECTABLE (typeId=1, behaviour=0) dans la meme zone que le joueur,
    teste la distance XZ et Y. Si OK : applique les deltas et detache.
    – Skip les items deja « max » (= rien a ajouter, comportement ASM-fidele).
    – Marge horizontale PICKUP_RADIUS_MARGIN = 0.3 JME (~10 cm) pour
    faciliter le ramassage en passant.

  3. app/GameAppState.java : wiring complet :
    – Champs healthState, pickupSystem, hudState
    – Initialisation apres combatState dans le try{}
    – Appel pickupSystem.update(playerPos) apres applyZoneLogic dans update()
    – Overlay debug enrichi : ligne HP:200/200 Fuel:N [Jetpack] Picked:5

Comportement actuel

  • Ramassable : Medipac (HP), ShotgunShells (ammo), Plasmaclip (ammo),
    Passkey (keysMask), grenades (ammo), Plasmagun/Shotgun (weapons), etc.
  • Non ramassable : Computer / Generator / Ventfan (behaviour=2 DESTRUCTABLE,
    necessite des tirs), Lamp / decorations (behaviour=3 DECORATION).
  • Non implemente : Activatable (computers via SPACE) – viendra plus tard.

Pour tester

./gradlew convertLevels   # regen definitions.json avec ammoGive/gunGive
./gradlew buildScenes     # regen scenes avec colRadius/colHeight userData
./gradlew run

Avancer sur un Medipac : l’overlay debug doit montrer HP: 200/200 -> +X HP,
le sprite disparait, le compteur Picked:N s’incremente. Les logs montrent :

Collected: Medipac (defIdx=1) +50 HP -> PlayerHealth{HP=200/200 ...}

Limitations / TODO

  • Audio : pas encore d’AudioManager. Le son SFX[4] = « collect » devra
    etre joue via Aud_SampleNum_w = 4 (cf. Plr1_CollectItem ASM).
    TODO en commentaire dans PickupSystem.collect().
  • HUD visuel : HudAppState est cree mais pas attache au stateManager
    (desactive session 75). Les messages « Got Medipac » sont juste loggues.
    Quand on reactivera le HUD ils s’afficheront automatiquement.
  • Activatable objects : computers / switches qui demandent SPACE.
    Necessite la touche SPACE + check distance + animation « activated ».
  • Destructable : computers a detruire (tir + hitPoints). Probablement
    deja partiellement gere par PlayerShootSystem mais a verifier.
  • Affichage messages level : les messages[] du JSON (briefings,
    hints) ne sont pas affiches a la collecte d’objets ayant un
    displayText non-nul (cf. ASM Plr1_CollectItem.notext).

Fichiers modifies / nouveaux

Nouveaux :
combat/PlayerHealthState.java : sante / fuel / shield / jetpack / keys
world/PickupSystem.java : detection collision + application collecte

Modifies :
tools/LnkParser.java : offsets et accesseurs getAmmoGive / getGunGive
tools/LevelJsonExporter.java : ajoute ammoGive / gunGive dans definitions.json
tools/LevelSceneBuilder.java : expose colRadius / colHeight en userData
app/GameAppState.java : wiring + appel pickupSystem.update + overlay HP

Laisser un commentaire

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