Repository navigation
Animations
The Player Animation System selects sprite clips in response to movement, combat and input events. PlayerAnimationController drives AnimationRenderComponent; combat damage stays in the combat components. Death-animation completion also signals the screen to finish the player-loss transition.
This page describes the Sprint 3 player animation implementation in PR #229, together with the regression coverage in PR #196 and bow-charge fixes in PR #211.
flowchart LR
Input["Input / ItemUseComponent"] --> Controller["PlayerAnimationController"]
Actions["PlayerActions"] --> Controller
Stats["CombatStatsComponent"] --> Controller
Controller -->|select clip and facing| Renderer["AnimationRenderComponent"]
Factory["PlayerFactory / atlas"] -->|register clips| Renderer
Controller -->|deathAnimationFinished| Screen["Game screen"]
The factory registers idle, walk and sprint loops; takeoff, fall and landing clips; hurt and death clips; and a sleep loop. Horizontal movement flips the sprite. The controller resolves ordinary locomotion using:
String desired = moving ? (sprinting ? "sprint" : "walk") : "idle";The merged factory also registers melee, dash, air_dash, bow_draw, bow_hold and bow_shoot. Its actual state flags include moving, sprinting, jumping, dashing, hurt, attacking, dead, charging, drawingIn and bowActive; the older drawingBow/holdingBow/releasingBow API on this page belongs to a different branch.
The older PR #84 design described an entity-wide 1.15× bow scale pulse. That is not the reviewed PR #145 implementation. Instead, the renderer supports per-animation pixel anchors so larger melee/dash/bow canvases align with the player. Left-facing rendering mirrors the horizontal anchor.
Shared pixel scaling, UV-based flipping and per-animation anchors are merged. The renderer also makes isFinished() return false for looping playback modes, preventing a hold loop from being mistaken for a completed one-shot. Playback time advances only while the entity service is unpaused.
Jump presentation follows the physics state supplied by PlayerActions.
| Gameplay transition | Clip | Behaviour |
|---|---|---|
| Accepted ground jump | jump_takeoff |
Play takeoff and hold the ascent pose |
| Descent begins | jump_fall |
Loop while falling |
| Landing | jump_land |
Play landing recovery |
Walking off a ledge enters falling without takeoff. After an airborne hurt or dash animation, the controller returns to the appropriate airborne presentation rather than always returning to idle.
Q requests the instrument animation. An accepted request plays instrument_draw, followed by instrument_hold. Instrument audio starts in step with the draw animation and pauses gameplay music. Another action or pausing puts the instrument away and coordinates audio cleanup.
GrappleHoldRenderComponent draws the hanging pose along the rope while attached. Hurt feedback can still appear while swinging.
Bow charges started during other animations are preserved so the draw, hold and release sequence can continue correctly.
Death starts the death clip and suppresses normal action presentation. Completion emits deathAnimationFinished, allowing the screen to complete the player-loss transition.
Airborne recovery follows the movement state after hurt or dash. Bow charging retains its state across other animations. Instrument presentation is interrupted by other actions or pausing. Animation selection does not itself grant damage immunity or determine whether an attack hits.
-
chargeStartstarts one-shotbow_draw, records the aimed facing and enters the bow state. - Draw completion enters looping
bow_hold. -
chargeReleasestarts one-shotbow_shoot, including release before the draw clip finishes. - Shoot completion clears the attack/bow state and returns to locomotion.
- Death overrides the sequence and the bow component cancels its pending projectile.
The current implementation uses chargeStart and chargeRelease, not the former page's attackChargeStart and attackCancelled. The bow still emits attackAnimation on firing, but that event does not drive this current draw/hold/shoot controller path. E fires instantly and should not be described as automatically playing the full charged sequence.
| Event | Source | Animation response |
|---|---|---|
walk / walkStop
|
Keyboard input | Locomotion state/facing |
sprint / sprintStop
|
Keyboard input | Sprint state |
jumpStart |
PlayerActions | Takeoff and ascent pose |
fallStart |
PlayerActions | Looping fall |
landed |
PlayerActions | Landing recovery |
instrumentStart |
Keyboard input | Instrument draw and hold |
hurt |
Accepted combat damage | Hurt clip, subject to priority guards |
death |
Health reaches zero | Death clip |
deathAnimationFinished |
Animation controller | Screen handles player removal/loss |
meleeSwing |
MeleeComponent | Accepted swing animation, with facing direction |
dashStart / airDashStart
|
PlayerActions | Both currently select air_dash
|
chargeStart / chargeRelease
|
ItemUseComponent | Bow draw/hold/shoot |
sprintEnd |
PlayerActions | End sprint animation state after grace period |
Clip timing is registered in PlayerFactory. Frame duration is not total clip length; total length also depends on the number of atlas frames.
Sprint 3 retunes melee playback and slows the instrument draw/hold clips, keeping the instrument audio start aligned with its draw animation. The merged implementation retains the previous idle, walk, sprint, hurt, death, sleep, dash and bow timings; it does not apply a blanket slowdown to all player animations. When changing instrument timing, keep the controller’s audio-start timing consistent with the registered draw frame duration. Melee presentation also follows the timing constants in MeleeComponent.
These are presentation values, not damage or invulnerability timings.
PlayerAnimationControllerTest and PlayerAtlasTest cover animation states and required atlas regions. GrappleHoldRenderComponentTest checks hanging-pose rendering.
| Manual check | Expected result |
|---|---|
| Jump, fall and land | Consistent sprite alignment throughout the sequence |
| Take damage or air-dash while falling | Falling presentation resumes afterwards |
| Start and interrupt the instrument | Audio starts with the draw and stops on interruption |
| Pause during instrument playback | Instrument stops without incorrectly resuming gameplay music |
| Attach and release the grapple | Hanging pose follows the rope and clears on release |
| Begin charging during another animation | Charge state is retained |
Component tests verify selected transitions and rendering behaviour rather than every visual combination. Sprite alignment, interruption timing and readability during overlapping actions require gameplay checks.
- Player sprite/animation PR #67
- Merged animation update PR #134
- Historical alternative animation work PR #84
- Merged combined mechanics PR #145
- Sprint 2 controller source
| PR | Work |
|---|---|
| #196 | Regression coverage, collision fixes, maintainability and Sonar coverage reporting |
| #211 | Charged grapple, rope physics, flight wrapping and corner climbing |
| #229 | Movement, melee and animation overhaul |
The instrument sprite sheet player_instrument.png was generated using GPT Image 2, as confirmed by Team 5 for the Sprint 3 AI declaration. It is used by the instrument draw/hold animations introduced in PR #229.
Tristan Sheedy (TristanUniCoding) developed/refined the base player sprites, movement/death animation integration and newer charged-bow sequence. Josiah Enns (Jjmenns) contributed hurt and earlier bow animation work, then melee/dash/air-dash assets and anchor integration. PR #84 remains credited as historical work, not silently presented as PR #145's API.
Darcy Franklin implemented the movement/grapple systems that supply related gameplay behaviour. The earlier blanket attribution of the original player sprite/controller work to Darcy is corrected here to reflect commit authorship. Shared renderer and cross-team contributions retain their repository history.
Sprint 3 adds Tristan Sheedy and Josiah Enns’s movement, melee and presentation overhaul, Rohan Shirkhedkar’s bow-charge transition fix, and Dhiren Malik’s animation-transition regression coverage.
Entities and Components
Input Handling
Arrow Selection Wheel Arrow Selection Wheel — Sprint 3