Enemy Action and Form Animations Test Plan - UQcsse3200/2026-studio-3 GitHub Wiki
Owner:
@jianghuichen0918ยท Ticket: #438 (Sprint 4) ยท PRs: #463, #485 ยท Last updated: 2026-10-19Feature page: Enemy Action and Form Animations
The work in #438 has three layers, and each is tested where it can actually be checked:
-
Atlas data (region names and frame counts). The
.atlasfiles are plain text, so they are parsed directly without loading textures. This catches a misspelt or missing region, which would otherwise fail silently because the controller falls back to the normal animation. -
Wiring code (
EnemyFactoryregistering the animations and their timings,BattleControllerswitching the Boss silence form). This is pure logic and is covered by JUnit with mocked atlases and real entities. -
What the player sees (the poses, how long they stay, whether they line up with the old frames,
and whether Team 7's effects still fit). Drawing needs a live LibGDX/OpenGL context, so these are
checked manually in a running game using the
F1debug terminal.
The automated tests prioritise:
- every region name agreed with #436, so Tianyu's form code finds the art by name;
- the bestiary's
defaultframe staying where it was; - fallback paths: an atlas without
defend/castmust not crash; - the two timings changed on purpose (non-boss held poses, the enraged slash); and
- the silence form starting and ending with the status, and not affecting other enemies or a defeated Boss.
| # | Acceptance criterion (#438) | Covered by |
|---|---|---|
| 1 | Every enemy plays the matching animation when it defends or applies a debuff, then returns to idle
|
EA01, EA02, EA06, EA07, EX01โEX03; EM01โEM04 |
| 2 | All region names follow the naming convention and are read directly by Tianyu's code | EA01โEA04, EA08; EX03, EX04; EM03, EM04 |
| 3 | Team 7's orbit visuals and attack lunge still work correctly with the new animations | EM06 |
| 4 | Enemy images in the bestiary are unchanged | EA05; EM07 |
Silence-form cases (EA04, EA08, EA10, EM05) and the enraged slash timing (EA09) cover the extra work added in PR #485.
| Component | Behaviour verified |
|---|---|
Enemy atlases (lesser_shade, bone_crawler, dark_acolyte, tomb_guardian, void_knight, boss_knight) |
Every new region exists with the right frame count; default is still the first idle frame at xy: 0, 0
|
EnemyFactory |
defend and cast are registered for every enemy whose atlas has them and skipped when it does not; the Boss registers idle_silence; attack_enraged is held for 0.5 s while attack stays at 0.2 s |
BattleController |
The Boss enters the silence form when the player is silenced and leaves it when the silence is removed; unrelated statuses, a defeated Boss and other enemies are ignored |
EnemyAnimationController (#436, not changed by #438) |
Plays defend / cast when present, returns to idle, and uses the <animation>_<form> region while a form is active with a fallback to the normal one |
| In-game visuals | Poses read clearly, line up with the old frames, stay for the intended time, and work with the status orbit, attack lunge and bestiary |
| ID | Component / test | Why this case exists | Case type | Input or steps | Expected result | Actual result / evidence |
|---|---|---|---|---|---|---|
| EA01 | EnemyAtlasRegionsTest.normalEnemiesHaveADefendPose |
Without a defend region these enemies fall back to idle and look like they stand still. |
Normal | Parse lesser_shade, bone_crawler and dark_acolyte atlases and count regions by name. |
Each has exactly one defend frame. |
Pass โ local run 19 Oct 2026; CI on PR #463. |
| EA02 | EnemyAtlasRegionsTest.tombGuardianHasDefendCastAndTauntingForm |
The Tomb Guardian needs an action pose for both its shield and its taunt, plus the taunting form. | Normal | Parse tomb_guardian.atlas. |
defend ร1, cast ร1, idle_taunt ร2, hurt_taunt ร1. |
Pass โ local run 19 Oct 2026; CI on PR #463. |
| EA03 | EnemyAtlasRegionsTest.rivenKnightHasEnragedForm |
#436 looks the enraged form up by these exact names. | Normal | Parse void_knight.atlas. |
idle_enraged ร2, attack_enraged ร1, hurt_enraged ร1. |
Pass โ local run 19 Oct 2026; CI on PR #463. |
| EA04 | EnemyAtlasRegionsTest.bossHasSilenceForm |
The silence form only exists as two atlas entries; a repack of the Boss sheet could drop them unnoticed. | Normal / regression | Parse boss_knight.atlas. |
idle_silence ร2. |
Pass โ local run 19 Oct 2026; CI on PR #485. |
| EA05 | EnemyAtlasRegionsTest.defaultRegionIsStillTheFirstIdleFrame |
The bestiary (Team 5) shows default; adding frames must not move it. |
Regression | For the five repacked atlases, find default and idle index 0. |
Both exist, default is at xy: 0, 0, and it matches idle frame 0. |
Pass โ local run 19 Oct 2026; CI on PR #463. |
| EA06 | EnemyFactoryTest.nonBossEnemiesRegisterDefendAndCastWhenAtlasHasThem |
EnemyFactory used to register defend/cast for the Boss only. |
Normal | Mock an atlas that returns a frame for every name; create bone_crawler and tomb_guardian. |
Both have defend and cast animations. |
Pass โ local run 19 Oct 2026; CI on PR #463 (test later revised by @xiaojaxon). |
| EA07 | EnemyFactoryTest.enemiesWithoutDefendOrCastRegionsSkipThem |
Registering for every enemy must be safe when an atlas has no such region. | Boundary / invalid | Create lesser_shade with the default test atlas (no defend/cast), then call create(). |
Neither animation is registered and nothing throws. | Pass โ local run 19 Oct 2026; CI on PR #463 (test later revised by @xiaojaxon). |
| EA08 | EnemyFactoryTest.bossRegistersSilenceFormWhenAtlasHasIt |
The silence region in the atlas is useless unless the factory registers it as an animation. | Normal | Mock boss_knight.atlas with an idle_silence frame; create boss_knight. |
The animator has idle_silence. |
Pass โ local run 19 Oct 2026; CI on PR #485. |
| EA09 | EnemyFactoryTest.enragedAttackIsHeldLongerThanNormalAttack |
The red slash is one frame; at 0.2 s it was gone before it could be seen. Only the enraged attack should change. | Normal / regression | Intercept the AnimationRenderComponent built for void_knight and verify its addAnimation calls. |
attack at 0.2 s and attack_enraged at 0.5 s, both NORMAL play mode. |
Pass โ local run 19 Oct 2026; CI on PR #485. |
| EA10 | BattleControllerTest.shouldHoldBossSilenceFormUntilSilenceEnds |
Silence lives on the player, so the Boss must be told when it starts and ends; the switch must not leak to other enemies or a dead Boss. | Normal / boundary / invalid | Battle with a Boss and a Tomb Guardian. Apply Poison; apply then remove Silence; apply Silence again, set the Boss to 0 HP, remove Silence. | Poison causes no form change; the Boss receives silence then normal; nothing is sent to the defeated Boss; the Tomb Guardian receives nothing. |
Pass โ local run 19 Oct 2026; CI on PR #485. |
These were written for #436 and were not changed by #438, but they are the other half of acceptance criteria 1 and 2, so they are run together with the cases above.
| ID | Component / test | What it guarantees for #438 | Actual result / evidence |
|---|---|---|---|
| EX01 | EnemyAnimationControllerTest.shouldPlayDefendWhenAvailable |
enemyDefend plays the defend region added here. |
Pass โ local run 19 Oct 2026. |
| EX02 |
EnemyAnimationControllerTest.shouldPlayCastWhenAvailable, shouldReturnToIdleAfterCastFinishes
|
enemyCast plays cast and then returns to idle. |
Pass โ local run 19 Oct 2026. |
| EX03 | EnemyAnimationControllerTest.shouldHoldTauntIdleAndUseNormalCastWhenTauntCastIsMissing |
The taunting form uses idle_taunt and falls back to normal cast, which is why no cast_taunt art is needed. |
Pass โ local run 19 Oct 2026. |
| EX04 | EnemyAnimationControllerTest.shouldUseEnragedHurtWhenAvailableAndReturnToNormalOnFormExit |
hurt_enraged is used in the enraged form, and leaving the form restores the normal animations. |
Pass โ local run 19 Oct 2026. |
All manual cases run in the desktop game (./gradlew desktop:run). Press F1 to open the debug
terminal. Enemy slots start at 0. forceintent sets the enemy's next intent, so end the turn
to see it act.
| ID | Area | Why this case exists | Steps | Expected result | Actual result / evidence |
|---|---|---|---|---|---|
| EM01 | Normal-enemy defend poses | Pose readability and alignment with the old frames cannot be asserted headlessly. | On the map run goto <floor> combat (start with goto 1 combat). In battle run forceintent <slot> defend for each enemy, then end the turn. Repeat on other combat nodes until the Lesser Shade, Bone Crawler and Dark Acolyte have each been seen. |
Each plays its own pose (purple bubble, curled bone ball, golden ward) for about 0.8 s, then returns to idle. The feet stay on the same line and the body does not jump in size. The bubble and ward are see-through. |
Pending โ record a screenshot of each pose. |
| EM02 | Tomb Guardian defend and taunt | Two different action poses on one enemy must not be swapped. |
goto <floor> elite until a Tomb Guardian appears (debug on on the map shows floors). Run forceintent <slot> defend, end the turn; then forceintent <slot> taunt, end the turn. |
Defend shows the braced shield pose; taunt shows the laughing pose. Each lasts about 0.8 s. | Pending โ record a screenshot of each pose. |
| EM03 | Tomb Guardian taunting form | The form must hold for as long as the taunt is on the player, then end. | Continue from EM02 after the taunt lands. Attack the Tomb Guardian once, then play turns until the taunt icon leaves the player. | While taunted, its idle is the laughing loop and a hit shows hurt_taunt. When the taunt ends it returns to its normal idle. |
Pending โ record a short clip. |
| EM04 | Riven Knight enraged form and slash | The red recolour and the 0.5 s slash are only meaningful on screen. |
goto <floor> elite until a Riven Knight appears. Run setenemyhp <slot> <hp below half its max>, end the turn, and let it attack. Hit it once. |
After its next intent it idles with red cracks instead of cyan. Its attack shows a red slash that stays visible for about half a second. A hit shows the red hurt frame. | Pending โ record a short clip. |
| EM05 | Boss silence form | Checks the whole chain: intent โ status on the player โ BattleController โ Boss form. |
On the map run debug on and read the floor of the final node, then goto <floor> final. Run forceintent <boss slot> silence, end the turn, and play turns until the silence icon leaves the player. |
The Boss casts, then keeps alternating two glowing cast frames for as long as the player is silenced. A hit plays the normal hurt frame and returns to the glow. It goes back to its normal idle when the silence ends. | Pending โ record a short clip. |
| EM06 | Team 7 status orbit and attack lunge | Acceptance criterion 3: the orbit is sized from the current frame, and the new poses change that size. | In a battle with a Lesser Shade, apply a status to it (e.g. Poison from a card), then forceintent <slot> defend and end the turn. Let any enemy attack. |
The orbit stays centred on the enemy and grows slightly around the bubble. The attack lunge moves forward and returns to the starting spot. | Pending โ record a screenshot. |
| EM07 | Bestiary images | Acceptance criterion 4, checked through the real UI. | Main Menu โ Bestiary โ Enemy Library. The library only lists enemies that have been discovered, so run it after EM01โEM05 (or on a save that has met them). Open each of the six enemies. |
Each shows its normal form, same as before #438: no defend pose, red cracks, laughing pose or silence glow. | Pending โ record a screenshot. |
Run the automated tests from source/:
./gradlew core:test \
--tests "*EnemyAtlasRegionsTest" \
--tests "*EnemyFactoryTest" \
--tests "*BattleControllerTest" \
--tests "*EnemyAnimationControllerTest"On Windows, use gradlew.bat in place of ./gradlew. The four classes contain 121 tests in total
(5 + 26 + 60 + 30), including the 10 added for #438; all passed on 19 Oct 2026.
Sufficiency: Every new region name, both deliberate timing changes and the silence switch have a dedicated automated case, and each acceptance criterion maps to at least one case above. The atlas tests read the real asset files, so they also guard against a later repack. Whether a pose looks right, lines up with the old frames and fits Team 7's orbit can only be judged on screen, so those are manual cases. The silence form's behaviour when the Boss is defeated mid-silence is covered by EA10 only, because it is hard to time by hand. Manual rows stay pending until somebody records the real result and evidence; they must not be marked passed based on unit tests alone.
Status: Merged into Feature-1 through PR #463 (16 Oct 2026: defend and cast poses, taunting
and enraged forms, tests EA01โEA03, EA05โEA07) and PR #485 (17 Oct 2026: Boss silence form, 0.5 s
enraged slash, tests EA04, EA08โEA10).
Test files:
source/core/src/test/com/csse3200/game/entities/factories/EnemyAtlasRegionsTest.java
source/core/src/test/com/csse3200/game/entities/factories/EnemyFactoryTest.java
source/core/src/test/com/csse3200/game/components/combat/BattleControllerTest.java
source/core/src/test/com/csse3200/game/components/enemy/EnemyAnimationControllerTest.java