summaryrefslogtreecommitdiff
path: root/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt
diff options
context:
space:
mode:
Diffstat (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt')
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt41
1 files changed, 14 insertions, 27 deletions
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt
index 7ae405e..7968250 100644
--- a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationSystem.kt
@@ -1,35 +1,27 @@
package coffee.liz.ecs.animation
-import coffee.liz.ecs.System
+import coffee.liz.ecs.TickedSystem
import coffee.liz.ecs.World
+import kotlin.time.Duration
/**
- * System that updates animation playback state for all entities with an Animator component.
- *
- * This system:
- * - Updates elapsed time for playing animations
- * - Advances frame indices based on frame duration
- * - Handles loop modes (ONCE, LOOP, PING_PONG)
- * - Stops animations when they complete (for ONCE mode)
+ * Updates animation playback state for all [Animator] components in [World].
*/
-class AnimationSystem : System {
- override fun update(world: World, deltaTime: Float) {
- // Query all entities that have both Animator and SpriteSheet
- world.query(Animator::class, SpriteSheet::class).forEach { entity ->
- val animator = entity.get(Animator::class) ?: return@forEach
-
- // Skip if animation is not playing
+class AnimationSystem(animationTickRate: Duration) : TickedSystem(animationTickRate) {
+ override fun update(world: World, ticks: Int) {
+ world.query(Animator::class).forEach { entity ->
+ val animator = entity.get(Animator::class)
if (!animator.playing) return@forEach
// Get the current animation clip
val clip = animator.clips[animator.currentClip] ?: return@forEach
// Accumulate elapsed time
- animator.elapsed += deltaTime
+ animator.elapsedTicks += ticks
// Advance frames while we have enough elapsed time
- while (animator.elapsed >= clip.frameDuration) {
- animator.elapsed -= clip.frameDuration
+ while (animator.elapsedTicks >= clip.frameTicks) {
+ animator.elapsedTicks -= clip.frameTicks
advanceFrame(animator, clip)
}
}
@@ -39,11 +31,10 @@ class AnimationSystem : System {
* Advances the animation to the next frame based on loop mode.
*/
private fun advanceFrame(animator: Animator, clip: AnimationClip) {
- animator.frameIndex += animator.direction
+ animator.frameIndex += animator.direction.step
when (clip.loopMode) {
LoopMode.ONCE -> {
- // Play once and stop on last frame
if (animator.frameIndex >= clip.frameNames.size) {
animator.frameIndex = clip.frameNames.size - 1
animator.playing = false
@@ -51,25 +42,21 @@ class AnimationSystem : System {
}
LoopMode.LOOP -> {
- // Loop back to beginning
if (animator.frameIndex >= clip.frameNames.size) {
animator.frameIndex = 0
} else if (animator.frameIndex < 0) {
- // Handle negative wrap (shouldn't happen in LOOP but be safe)
animator.frameIndex = clip.frameNames.size - 1
}
}
LoopMode.PING_PONG -> {
- // Bounce back and forth
+ // Go to (endFrame - 1) or (beginFrame + 1) ping ponging
if (animator.frameIndex >= clip.frameNames.size) {
- // Hit the end, reverse direction
animator.frameIndex = (clip.frameNames.size - 2).coerceAtLeast(0)
- animator.direction = -1
+ animator.direction = AnimationDirection.BACKWARD
} else if (animator.frameIndex < 0) {
- // Hit the beginning, reverse direction
animator.frameIndex = 1.coerceAtMost(clip.frameNames.size - 1)
- animator.direction = 1
+ animator.direction = AnimationDirection.FORWARD
}
}
}