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, 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 ) : Component /** * Component for animation playback state. * Contains animation clips and current playback state. */ data class Animator( val clips: Map, 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