Player Animations - UQcsse3200/2026-studio-4 GitHub Wiki
Player Animations
Author: @YCQinBob (Bob)
Task #86. Do not replace this page wholesale; file an issue for corrections.
| Author | @YCQinBob |
| Feature | Core Player Actions (#5) |
| Tasks | #84 idle/walk · #85 melee clips · #86 this wiki · #87 JUnit |
| Branch | core-player-features |
| Repo draft | source/docs/player-animations.md |
Scope
How the player sprite plays idle, walk, and melee slash clips.
Movement, dash, and weaponAttack already exist in PlayerActions (#5). This work only plays atlas clips so facing matches walk and swing.
Not this page: hitboxes, sword damage, Charm pickup, inventory, stats HUD, the engine Animations tutorial.
Intended flow
- Load
images/idle_down.atlas(idle_down.png, page 768×1280). PlayerFactoryregisters loopingidle_*/walk_*and one-shotattack_*.- Spawn in
idle_down. - WASD →
walkDown/walkLeft/walkRight/walkUp. - Release →
idle*for the last walk direction. - J →
attack, thenweaponAttackwith last facing (default down). PlayerAnimationControllerplaysattack_*once, ignores idle/walk until the clip ends, then restores the last locomotion clip.
Diagonal facing: vertical wins (same as walk).
Controls
After Start, click the game window. Use an English layout. Do not focus the F1 terminal.
| Input | Events | Animation |
|---|---|---|
| W / A / S / D | walk then walkUp / walkLeft / walkDown / walkRight |
loop walk_* |
| Release WASD | walkStop then idle* |
loop last-facing idle_* |
| J | attack → weaponAttack + Vector2 |
one-shot attack_*, then idle/walk |
| Space | dash |
movement only; no dash clip |
| K | specialAttack |
sound only; no clip; does not fire weaponAttack |
Desktop default is the keyboard factory. Arrows / touch-down attack are TouchPlayerInputComponent.
Clip map
Events are camelCase; atlas names are snake_case.
| Event | Atlas clip |
|---|---|
idleDown idleLeft idleRight idleUp |
idle_down idle_left idle_right idle_up |
walkDown walkLeft walkRight walkUp |
walk_down walk_left walk_right walk_up |
weaponAttack + facing |
attack_down attack_left attack_right attack_up |
Attack facing (animateAttack: y first, then x):
| Vector | Clip |
|---|---|
y < 0 |
attack_down |
y > 0 |
attack_up |
y == 0 and x < 0 |
attack_left |
y == 0 and x > 0 |
attack_right |
(0, 0) |
attack_down |
Example: down-right walk → walk_down; J → attack_down.
Timing (PlayerFactory)
| Clips | Frame time | Mode |
|---|---|---|
idle_* walk_* |
0.1s | LOOP |
attack_* |
0.06s | NORMAL (8 frames ≈ 0.48s; sword cooldown 0.5s) |
A second J while attacking is ignored. All names must be addAnimation’d before startAnimation("idle_down").
Component contract
PlayerAnimationController listens on the player only. It does not spawn hitboxes.
- While
attacking, idle/walk only store the next clip name. - When
AnimationRenderComponent.isFinished(), locomotion resumes. - Does not listen to
dashorspecialAttack.
See (do not overwrite): PlayerActions · PlayerAnimationController · Animations
Code
| File | |
|---|---|
| Controller | PlayerAnimationController.java |
| Registration | PlayerFactory.java |
| Events (existing; tests added) | PlayerActions.java |
| Atlas | source/core/assets/images/idle_down.atlas, idle_down.png |
Tests for this work (not inventory/Charm): PlayerAnimationControllerTest, PlayerActionsTest, extra WASD/J/K/Space on KeyboardPlayerInputComponentTest (E was already on the branch), TouchPlayerInputComponentTest.
Automated verification
Run from source with JDK 21:
./gradlew :core:test --tests com.csse3200.game.components.player.PlayerAnimationControllerTest --tests com.csse3200.game.components.player.PlayerActionsTest --tests com.csse3200.game.components.player.KeyboardPlayerInputComponentTest --tests com.csse3200.game.components.player.TouchPlayerInputComponentTest