Combat Animation Foundation - UQcsse3200/2026-studio-3 GitHub Wiki
When a card is played, a short visual plays on the target based on the resolved effect type. The system is split into two layers:
- Rendering components — reusable "how to draw" logic. Not tied to any specific effect; any teammate's effect can use any of these.
- Registration files — each teammate's own file, where they decide which rendering component to use for which effect type, and with what parameters (colour, size, duration, etc.).
This split means rendering logic is shared and rarely changes, while each person's own design choices live in their own file with no risk of conflicts.
EffectVisualStyle.java
A plain data record describing how one visual looks: icon path (or null for a generated glow), colour, duration, start/end scale, and upward drift. Used by the Icon Scale & Fade rendering component below.
EffectVisualRegistry.java
A lookup table mapping EffectType to its visual style. Each teammate registers their own effect types into this shared registry from their own file. Unregistered types fall back to a default glow instead of crashing.
BattleAnimationCoordinator.java
Listens to the battle system's existing card-effect events. When a card resolves, it looks up each effect's style from the registry, spawns the right visual on the right target (single enemy, all enemies, or the player), staggers multiple effects in time so they don't overlap, and cleans up finished visuals automatically. Already wired into BattleScreen; nothing else needs to touch it.
Each style is its own independent component file. If your effect fits one of these, reuse it (just register your own parameters — colour, size, duration — in your own registration file). Before building a new rendering style, check this table first and post in the group chat — don't build a new one without checking, so we don't end up with two components doing the same thing.
| Style | File | Good for |
|---|---|---|
| Icon Scale & Fade | EffectVisualComponent.java |
A single icon that grows and fades — most status/buff effects (shield for Block, heart for Heal, etc.) |
| Burst / Particles | EffectBurstComponent.java |
Several small particles fly outward and fade — used for Damage (round dots) and Sunder (jagged spinning shards with a downward drop). Shape and gravity are per-effect parameters, not hardcoded — see the owning registration file for how to configure a new combination. |
| Path / Slash | EffectProjectileComponent.java |
A slim shape travels from an offset point, through the target, to another offset point, fading as it goes — used for Pierce. Direction, reach and travel speed are constructor parameters, tuned per-effect in the registration file rather than in this component. |
More styles will be added to this table as they're built — if what you need isn't here yet, that's expected; just check with the group before starting one.
public final class YourEffectVisuals {
public static void registerAll(EffectVisualRegistry registry) {
registry.register(
EffectType.YOUR_TYPE,
new EffectVisualStyle("icon/path.png", Color.YOUR_COLOUR, duration, startScale, endScale, rise));
}
}Then in BattleScreen, add one line calling your registerAll(effectVisualRegistry) next to the existing registration calls — nothing else to change.
| Effect | Style | Look | Demo |
|---|---|---|---|
| Damage | Burst / Particles (EffectBurstComponent, ParticleShape.DOT) |
Round orange-red dots scatter outward and fade | ![]() |
| Pierce | Path / Slash (EffectProjectileComponent) |
A slim white blade slashes through the target, fading as it travels | ![]() |
| Sunder | Burst / Particles (EffectBurstComponent, ParticleShape.SHARD, gravity on) |
Grey jagged shards spin, fly out, then fall like broken armour | ![]() |
| Effect | Style | Look | Demo |
|---|---|---|---|
| Block | Icon (EffectVisualComponent) |
A shield icon grows over the player, drifts slightly upward and fades | ![]() |
| Fortify | Icon (EffectVisualComponent) |
A fortify icon swells larger than Block's, with only a slight upward drift, then fades | ![]() |
| Heal | Icon (EffectVisualComponent) |
A heal icon grows and floats clearly upward as it fades, reading as health rising | ![]() |
| Strength | Icon (EffectVisualComponent) |
A buff icon swells to 1.5× in place with no drift, reading as powering up (placeholder art: enemy buff intent icon) | ![]() |
| Energy Gain | Burst / Particles (EffectBurstComponent, ParticleShape.DOT) |
Yellow sparks scatter outward and shrink away to nothing | ![]() |
| Cleanse | Burst / Particles (EffectBurstComponent, ParticleShape.SHARD, gravity on) |
Purple shards spin off the player and fall away, like debuffs dropping off | ![]() |
| Effect | Style | Look | Demo |
|---|---|---|---|
| Poison | Animated green bubbles and wisps | Bright green bubbles gather around the enemy, expand and break apart in a repeating cycle. | ![]() |
| Vulnerable | Animated cracked shield | A red shield appears over the enemy, develops glowing cracks and breaks into fragments. | ![]() |
| Feeble | Animated downward chevrons and wisps | Stacked purple downward-pointing shapes appear over the enemy, surrounded by curling purple wisps. | ![]() |
| Two active statuses | Two animated effects on an elliptical orbit | The red Vulnerable shield and purple Feeble effect move around the enemy while continuing their individual animations.(Only one of the possible two-status combinations is shown.) | ![]() |
| Three active statuses | Three animated effects on an elliptical orbit | Green Poison bubbles, the red Vulnerable shield and the purple Feeble effect move around the enemy, remaining upright as they animate. | ![]() |
EnemyAnimationController.java moves the enemy forward and back while playing available attack frames. BattleController waits through runAfterAttack() before advancing to the next enemy. Movement does not apply additional damage.
How a card effect becomes an on-screen animation.
classDiagram
class EffectType {
<<enumeration>>
DAMAGE
BLOCK
HEAL
POISON
VULNERABLE
FEEBLE
STRENGTH
SUNDER
ENERGY_GAIN
PIERCE
CLEANSE
FORTIFY
+usesDuration() boolean
}
class EffectVisualStyle {
<<record>>
+String iconPath
+Color color
+float duration
+float startScale
+float endScale
+float rise
}
class EffectVisualRegistry {
-Map~EffectType, EffectVisualStyle~ styles
+register(type, style) void
+lookup(type) EffectVisualStyle
}
class OffensiveEffectVisuals {
<<registrar>>
+registerAll(registry)$ void
}
class PlayerEffectVisuals {
<<registrar>>
+registerAll(registry)$ void
}
class EnemyStatusEffectVisuals {
<<registrar>>
+registerAll(registry)$ void
}
OffensiveEffectVisuals ..> EffectVisualRegistry : register
PlayerEffectVisuals ..> EffectVisualRegistry : register
EnemyStatusEffectVisuals ..> EffectVisualRegistry : register
EffectVisualRegistry ..> EffectVisualStyle : stores
EffectVisualRegistry ..> EffectType : keys by
Each effect type's visual style is registered into a shared lookup table used at runtime.
classDiagram
class BattleAnimationCoordinator {
-BattleController controller
-CardEffectHandler effectHandler
-EffectVisualRegistry registry
+create() void
+update() void
-spawnVisual(type, target, startDelay, playApplication) void
}
class RenderComponent {
<<abstract>>
}
class EffectVisualComponent {
-Texture texture
-float baseSize
-float startDelay
+isExpired() boolean
#draw(batch) void
}
class EffectBurstComponent {
-boolean hasGravity
-ParticleShape shape
+isExpired() boolean
#draw(batch) void
}
class EffectProjectileComponent {
-float travelAngleDeg
-float reach
+isExpired() boolean
#draw(batch) void
}
class EnemyStatusEffectVisualComponent {
-Entity target
-EffectType statusType
-TextureRegion[] frames
~represents(target, type) boolean
~replay(delay) void
+isExpired() boolean
}
BattleAnimationCoordinator ..> EffectVisualComponent : else default
BattleAnimationCoordinator ..> EffectBurstComponent : usesBurst
BattleAnimationCoordinator ..> EffectProjectileComponent : usesProjectile
BattleAnimationCoordinator ..> EnemyStatusEffectVisualComponent : supports
EffectVisualComponent --|> RenderComponent
EffectBurstComponent --|> RenderComponent
EffectProjectileComponent --|> RenderComponent
EnemyStatusEffectVisualComponent --|> RenderComponent
Based on the effect type, dispatches to the matching visual component to play the animation.













