summaryrefslogtreecommitdiff
path: root/template/lib/animation.lua
diff options
context:
space:
mode:
Diffstat (limited to 'template/lib/animation.lua')
-rw-r--r--template/lib/animation.lua263
1 files changed, 263 insertions, 0 deletions
diff --git a/template/lib/animation.lua b/template/lib/animation.lua
new file mode 100644
index 0000000..6939bb1
--- /dev/null
+++ b/template/lib/animation.lua
@@ -0,0 +1,263 @@
+--[[
+Animation - Sprite sheet animation system for ReiLua-Enhanced
+
+Features:
+- Grid-based sprite sheet animation
+- Multiple animation tracks per spritesheet
+- Configurable FPS and looping
+- Callbacks on animation complete
+- Pause/resume/reset functionality
+
+Usage:
+ local Animation = require("lib.animation")
+
+ -- Create animation from sprite sheet
+ local playerAnim = Animation.new(
+ playerTexture, -- RL.LoadTexture("player.png")
+ 32, 32, -- Frame width, height
+ {
+ idle = {frames = {1, 2, 3, 4}, fps = 8, loop = true},
+ walk = {frames = {5, 6, 7, 8, 9, 10}, fps = 12, loop = true},
+ jump = {frames = {11, 12, 13}, fps = 10, loop = false}
+ }
+ )
+
+ playerAnim:play("idle")
+
+ -- In update:
+ playerAnim:update(dt)
+
+ -- In draw:
+ playerAnim:draw(x, y)
+]]
+
+local Animation = {}
+Animation.__index = Animation
+
+-- Create new animation from sprite sheet
+function Animation.new(texture, frameWidth, frameHeight, animations)
+ local self = setmetatable({}, Animation)
+
+ self.texture = texture
+ self.frameWidth = frameWidth
+ self.frameHeight = frameHeight
+
+ -- Calculate grid dimensions
+ local texSize = RL.GetTextureSize(texture)
+ self.columns = math.floor(texSize[1] / frameWidth)
+ self.rows = math.floor(texSize[2] / frameHeight)
+
+ -- Animation tracks
+ self.animations = animations or {}
+
+ -- Current state
+ self.currentAnim = nil
+ self.currentFrame = 1
+ self.frameTimer = 0
+ self.playing = false
+ self.paused = false
+ self.onComplete = nil
+
+ -- Default tint and scale
+ self.tint = RL.WHITE
+ self.flipX = false
+ self.flipY = false
+ self.rotation = 0
+ self.scale = {1, 1}
+ self.origin = {frameWidth / 2, frameHeight / 2}
+
+ return self
+end
+
+-- Add animation track
+function Animation:addAnimation(name, frames, fps, loop)
+ self.animations[name] = {
+ frames = frames,
+ fps = fps or 10,
+ loop = loop ~= false -- Default true
+ }
+end
+
+-- Play animation
+function Animation:play(name, onComplete)
+ if not self.animations[name] then
+ print("Warning: Animation '" .. name .. "' not found")
+ return
+ end
+
+ -- Don't restart if already playing
+ if self.currentAnim == name and self.playing then
+ return
+ end
+
+ self.currentAnim = name
+ self.currentFrame = 1
+ self.frameTimer = 0
+ self.playing = true
+ self.paused = false
+ self.onComplete = onComplete
+end
+
+-- Stop animation
+function Animation:stop()
+ self.playing = false
+ self.currentFrame = 1
+ self.frameTimer = 0
+end
+
+-- Pause animation
+function Animation:pause()
+ self.paused = true
+end
+
+-- Resume animation
+function Animation:resume()
+ self.paused = false
+end
+
+-- Reset to first frame
+function Animation:reset()
+ self.currentFrame = 1
+ self.frameTimer = 0
+end
+
+-- Update animation
+function Animation:update(dt)
+ if not self.playing or self.paused or not self.currentAnim then
+ return
+ end
+
+ local anim = self.animations[self.currentAnim]
+ if not anim then return end
+
+ self.frameTimer = self.frameTimer + dt
+ local frameDuration = 1.0 / anim.fps
+
+ -- Advance frames
+ while self.frameTimer >= frameDuration do
+ self.frameTimer = self.frameTimer - frameDuration
+ self.currentFrame = self.currentFrame + 1
+
+ -- Check if animation completed
+ if self.currentFrame > #anim.frames then
+ if anim.loop then
+ self.currentFrame = 1
+ else
+ self.currentFrame = #anim.frames
+ self.playing = false
+
+ -- Call completion callback
+ if self.onComplete then
+ self.onComplete()
+ self.onComplete = nil
+ end
+ end
+ end
+ end
+end
+
+-- Get source rectangle for current frame
+function Animation:getFrameRect()
+ if not self.currentAnim then
+ return {0, 0, self.frameWidth, self.frameHeight}
+ end
+
+ local anim = self.animations[self.currentAnim]
+ if not anim then
+ return {0, 0, self.frameWidth, self.frameHeight}
+ end
+
+ -- Get frame index from animation
+ local frameIndex = anim.frames[self.currentFrame] or 1
+
+ -- Convert to grid position (0-indexed for calculation)
+ local gridX = (frameIndex - 1) % self.columns
+ local gridY = math.floor((frameIndex - 1) / self.columns)
+
+ -- Calculate source rectangle
+ local x = gridX * self.frameWidth
+ local y = gridY * self.frameHeight
+ local w = self.frameWidth
+ local h = self.frameHeight
+
+ -- Apply flip
+ if self.flipX then
+ w = -w
+ end
+ if self.flipY then
+ h = -h
+ end
+
+ return {x, y, w, h}
+end
+
+-- Draw animation at position
+function Animation:draw(x, y, rotation, scale, origin, tint)
+ if not self.texture then return end
+
+ local source = self:getFrameRect()
+ local dest = {
+ x,
+ y,
+ math.abs(source[3]) * (scale and scale[1] or self.scale[1]),
+ math.abs(source[4]) * (scale and scale[2] or self.scale[2])
+ }
+
+ RL.DrawTexturePro(
+ self.texture,
+ source,
+ dest,
+ origin or self.origin,
+ rotation or self.rotation,
+ tint or self.tint
+ )
+end
+
+-- Draw animation with simple position
+function Animation:drawSimple(x, y)
+ if not self.texture then return end
+
+ local source = self:getFrameRect()
+ RL.DrawTextureRec(self.texture, source, {x, y}, self.tint)
+end
+
+-- Set tint color
+function Animation:setTint(color)
+ self.tint = color
+end
+
+-- Set flip
+function Animation:setFlip(flipX, flipY)
+ self.flipX = flipX
+ self.flipY = flipY
+end
+
+-- Set scale
+function Animation:setScale(sx, sy)
+ self.scale = {sx, sy or sx}
+end
+
+-- Set origin (rotation/scale point)
+function Animation:setOrigin(ox, oy)
+ self.origin = {ox, oy}
+end
+
+-- Check if animation is playing
+function Animation:isPlaying(name)
+ if name then
+ return self.currentAnim == name and self.playing
+ end
+ return self.playing
+end
+
+-- Get current animation name
+function Animation:getCurrentAnimation()
+ return self.currentAnim
+end
+
+-- Get current frame number
+function Animation:getCurrentFrame()
+ return self.currentFrame
+end
+
+return Animation