summaryrefslogtreecommitdiff
path: root/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt
diff options
context:
space:
mode:
Diffstat (limited to 'composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt')
-rw-r--r--composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt114
1 files changed, 114 insertions, 0 deletions
diff --git a/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt
new file mode 100644
index 0000000..4289eec
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/coffee/liz/ecs/animation/AnimationComponents.kt
@@ -0,0 +1,114 @@
+package coffee.liz.ecs.animation
+
+import coffee.liz.ecs.Component
+import kotlin.jvm.JvmInline
+
+/**
+ * Loop modes for animation playback.
+ */
+enum class LoopMode {
+ /** Play once and stop on last frame */
+ ONCE,
+ /** Repeat from beginning */
+ LOOP,
+ /** Play forward, then backward, repeat */
+ PING_PONG
+}
+
+/**
+ * Type-safe wrapper for animation names.
+ */
+@JvmInline
+value class AnimationName(val value: String)
+
+/**
+ * Type-safe wrapper for frame names.
+ */
+@JvmInline
+value class FrameName(val value: String)
+
+/**
+ * Represents a rectangle region in a sprite sheet.
+ */
+data class Rect(
+ val x: Int,
+ val y: Int,
+ val width: Int,
+ val height: Int
+)
+
+/**
+ * Defines a single animation clip with frames and playback settings.
+ */
+data class AnimationClip(
+ val frameNames: List<FrameName>,
+ val frameDuration: Float, // seconds per frame
+ val loopMode: LoopMode = LoopMode.LOOP
+)
+
+/**
+ * Component containing sprite sheet data - the image and frame definitions.
+ * This is immutable data that can be shared across entities.
+ */
+data class SpriteSheet(
+ val imagePath: String,
+ val frames: Map<FrameName, Rect>
+) : Component
+
+/**
+ * Component for animation playback state.
+ * Contains animation clips and current playback state.
+ */
+data class Animator(
+ val clips: Map<AnimationName, AnimationClip>,
+ var currentClip: AnimationName,
+ var frameIndex: Int = 0,
+ var elapsed: Float = 0f,
+ var playing: Boolean = true,
+ var direction: Int = 1 // 1 for forward, -1 for backward (used in PING_PONG)
+) : Component {
+
+ /**
+ * Play a specific animation clip by name.
+ * Resets playback state when switching clips.
+ */
+ fun play(clipName: AnimationName, restart: Boolean = true) {
+ if (currentClip != clipName || restart) {
+ currentClip = clipName
+ frameIndex = 0
+ elapsed = 0f
+ direction = 1
+ playing = true
+ }
+ }
+
+ /**
+ * Pause the current animation.
+ */
+ fun pause() {
+ playing = false
+ }
+
+ /**
+ * Resume the current animation.
+ */
+ fun resume() {
+ playing = true
+ }
+
+ /**
+ * Get the current frame name being displayed.
+ */
+ fun getCurrentFrameName(): FrameName? {
+ val clip = clips[currentClip] ?: return null
+ return clip.frameNames.getOrNull(frameIndex)
+ }
+}
+
+/**
+ * Component for entity position in 2D space.
+ */
+data class Position(
+ var x: Float,
+ var y: Float
+) : Component