Objectif
Implementer le spawn de projectiles visibles (plr1_FireProjectile ASM) et
leur mouvement physique chaque frame (ItsABullet ASM, partie mouvement).
Pas encore de collision murs/ennemis (Phases 1.D / 1.E).
Nouveaux composants
PlayerShot : instance d’un projectile en vol. Correspondance stricte
avec ShotT + entete ObjT de defs.i :
– Position (posX/Y/Z), velocite (velX/Y/Z) en unites JME
– bulletType (= ShotT_Size_b, index dans BulletDefs)
– power (= ShotT_Power_w), gravity, bounceFlags
– lifetime accumule en frames Amiga
– status (0=en vol, 1=pop), animFrame
– zoneId (-1 = slot libre, conforme a la convention ASM ObjT_ZoneID_w < 0)
– geometry (reference au placeholder JME)
PlayerShotPool : pool fixe de 20 slots (= NUM_PLR_SHOT_DATA ASM).
– allocate() : cherche le premier slot libre, null si pool plein
– releaseAll() : utilise au cleanup
– Comportement : si le pool est plein, le tir est abandonne silencieusement
(comme l’ASM fait rts sans rien faire dans .findonefree).
PlayerAimProvider : interface permettant au ShootSystem de connaitre
la position/direction de tir du joueur sans couplage dur avec GameAppState.
Equivalent des snapshots tempxoff/tempzoff/tempyoff/tempangpos de l’ASM.
BulletUpdateSystem (AppState) : implemente ItsABullet (newanims.s).
Chaque frame :
1. Pour chaque bullet active : pos += vel * tpf
2. Si gravity != 0 : velY -= gravity * tpf^2 * factor
3. Incremente lifetime. Si >= BulT_Lifetime_l, timeout -> libere le slot
4. Pour lifetime = -1 (infini ASM) : fallback a 500 frames Amiga (~20s)
pendant la phase 1.C car pas encore de collision mur pour tuer la bullet.
En phase 1.D, les bullets infinies seront tuees par impact mural.
5. Update la position de la Geometry JME associee (sphere placeholder coloree
par bulletType : bleu=plasma, jaune=machine gun, orange=rocket, etc.)
6. Les bullets avec graphicType=2 (glare/additive : plasma, lazer, mega)
utilisent BlendMode.Additive pour un rendu « energie »
Modifications
PlayerShootSystem : ajout du spawn de projectiles :
– Remplace le log « FIRE! » par un appel a fireProjectile() pour les bullets
non-hitscan (hitscan laisse en log, sera implemente en phase 1.D)
– Calcul du spread angulaire conformement a l’ASM :
– startYaw = playerYaw - (count-1)*SPREAD_PER_BULLET/2
– SPREAD_PER_BULLET = TWO_PI/16 (= 22.5°, equivalent des 256 unites de
table sin/cos ASM qui couvre 4096 entrees pour 360°)
– Conversion vitesse : velJme = 2^BulT_Speed * TICKS_PER_SECOND / AMIGA_SCALE
– Exemple : Plasma Bolt speed=5 -> 32 * 25/128 = 6.25 unites JME/s
– Chaque bullet reçoit sa direction avec offset pour le spread (shotgun 2
bullets auront +/-11.25° autour du centre)
CombatBootstrap : 20 ammo par type (au lieu de 1) pour permettre de
tester les rafales et voir plusieurs bullets en vol simultanement.
GameAppState : integration de BulletUpdateSystem + PlayerShotPool.
– PlayerAimProvider implemente en anonymous class qui lit la camera a chaque
appel (pas de snapshot fige)
Test attendu
./gradlew run
- Lancer un niveau, appuyer sur touche 4 (Assault Rifle, 2 frames cooldown)
- Maintenir clic gauche : rafale de bullets jaune pales qui partent de la
camera dans la direction de visee - Les bullets volent 20 secondes puis disparaissent (fallback timeout)
- Appuyer sur touche 1 (Shotgun) : 2 bullets par tir avec spread 22.5°
- Appuyer sur touche 2 (Plasma Gun) : bullets bleues additives, lentes
(speed=5) - Appuyer sur touche 3 (Grenade Launcher) : bullet verte avec gravite,
retombe en arc, disparait au bout de 150 frames Amiga (~6 secondes) - Appuyer sur touche 6 (Rocket Launcher) : bullet orange rapide (speed=6)
- Les bullets traversent les murs pour l’instant (pas encore de collision)
Fichiers crees/modifies
src/main/java/com/ab3d2/combat/PlayerShot.java(NEW)src/main/java/com/ab3d2/combat/PlayerShotPool.java(NEW)src/main/java/com/ab3d2/combat/PlayerAimProvider.java(NEW)src/main/java/com/ab3d2/combat/BulletUpdateSystem.java(NEW)src/main/java/com/ab3d2/combat/PlayerShootSystem.java(MODIFIED : spawn)src/main/java/com/ab3d2/combat/CombatBootstrap.java(20 ammo par type)src/main/java/com/ab3d2/app/GameAppState.java(integration)
Prochaine etape (Phase 1.D)
- Collision mur / sol / plafond : equivalent
MoveObjectASM + test
hitwall pour tuer/rebondir les bullets - Hitscan bullets :
plr1_HitscanSucceded/plr1_HitscanFailed - Evaluation si on passe aux sprites 2D pour les bullets avant ou apres
les collisions