blob: 7968250811bfdeb99cf7ff07ab6e076811ceb00b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package coffee.liz.ecs.animation
import coffee.liz.ecs.TickedSystem
import coffee.liz.ecs.World
import kotlin.time.Duration
/**
* Updates animation playback state for all [Animator] components in [World].
*/
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.elapsedTicks += ticks
// Advance frames while we have enough elapsed time
while (animator.elapsedTicks >= clip.frameTicks) {
animator.elapsedTicks -= clip.frameTicks
advanceFrame(animator, clip)
}
}
}
/**
* Advances the animation to the next frame based on loop mode.
*/
private fun advanceFrame(animator: Animator, clip: AnimationClip) {
animator.frameIndex += animator.direction.step
when (clip.loopMode) {
LoopMode.ONCE -> {
if (animator.frameIndex >= clip.frameNames.size) {
animator.frameIndex = clip.frameNames.size - 1
animator.playing = false
}
}
LoopMode.LOOP -> {
if (animator.frameIndex >= clip.frameNames.size) {
animator.frameIndex = 0
} else if (animator.frameIndex < 0) {
animator.frameIndex = clip.frameNames.size - 1
}
}
LoopMode.PING_PONG -> {
// Go to (endFrame - 1) or (beginFrame + 1) ping ponging
if (animator.frameIndex >= clip.frameNames.size) {
animator.frameIndex = (clip.frameNames.size - 2).coerceAtLeast(0)
animator.direction = AnimationDirection.BACKWARD
} else if (animator.frameIndex < 0) {
animator.frameIndex = 1.coerceAtMost(clip.frameNames.size - 1)
animator.direction = AnimationDirection.FORWARD
}
}
}
}
}
|