Adds Game Jam Ready Templates & ReiLua API Updates
(Most of the code is Copilot Generated LOL)
This commit is contained in:
263
template/lib/animation.lua
Normal file
263
template/lib/animation.lua
Normal file
@@ -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
|
||||
67
template/lib/classic.lua
Normal file
67
template/lib/classic.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
--
|
||||
-- classic
|
||||
--
|
||||
-- Copyright (c) 2014, rxi
|
||||
--
|
||||
-- This module is free software; you can redistribute it and/or modify it under
|
||||
-- the terms of the MIT license. See LICENSE for details.
|
||||
--
|
||||
|
||||
local Object = {}
|
||||
Object.__index = Object
|
||||
|
||||
|
||||
function Object:new()
|
||||
end
|
||||
|
||||
|
||||
function Object:extend()
|
||||
local cls = {}
|
||||
for k, v in pairs(self) do
|
||||
if k:find("__") == 1 then
|
||||
cls[k] = v
|
||||
end
|
||||
end
|
||||
cls.__index = cls
|
||||
cls.super = self
|
||||
setmetatable(cls, self)
|
||||
return cls
|
||||
end
|
||||
|
||||
|
||||
function Object:implement(...)
|
||||
for _, cls in pairs({...}) do
|
||||
for k, v in pairs(cls) do
|
||||
if self[k] == nil and type(v) == "function" then
|
||||
self[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Object:is(T)
|
||||
local mt = getmetatable(self)
|
||||
while mt do
|
||||
if mt == T then
|
||||
return true
|
||||
end
|
||||
mt = getmetatable(mt)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function Object:__tostring()
|
||||
return "Object"
|
||||
end
|
||||
|
||||
|
||||
function Object:__call(...)
|
||||
local obj = setmetatable({}, self)
|
||||
obj:new(...)
|
||||
return obj
|
||||
end
|
||||
|
||||
|
||||
return Object
|
||||
120
template/lib/gamestate.lua
Normal file
120
template/lib/gamestate.lua
Normal file
@@ -0,0 +1,120 @@
|
||||
--[[
|
||||
GameState - State management for ReiLua-Enhanced
|
||||
Inspired by hump.gamestate for Love2D
|
||||
Adapted for ReiLua-Enhanced by providing similar API
|
||||
|
||||
Usage:
|
||||
local GameState = require("lib.gamestate")
|
||||
local menu = {}
|
||||
local game = {}
|
||||
|
||||
function menu:enter() end
|
||||
function menu:update(dt) end
|
||||
function menu:draw() end
|
||||
|
||||
GameState.registerEvents()
|
||||
GameState.switch(menu)
|
||||
]]
|
||||
|
||||
local GameState = {}
|
||||
|
||||
-- Current state
|
||||
local current = nil
|
||||
|
||||
-- Stack of states for push/pop functionality
|
||||
local stack = {}
|
||||
|
||||
-- Helper function to call state function if it exists
|
||||
local function call(state, func, ...)
|
||||
if state and state[func] then
|
||||
return state[func](state, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- Switch to a new state
|
||||
function GameState.switch(to, ...)
|
||||
if current then
|
||||
call(current, 'leave')
|
||||
end
|
||||
|
||||
local pre = current
|
||||
current = to
|
||||
|
||||
return call(current, 'enter', pre, ...)
|
||||
end
|
||||
|
||||
-- Push current state to stack and switch to new state
|
||||
function GameState.push(to, ...)
|
||||
if current then
|
||||
table.insert(stack, current)
|
||||
end
|
||||
return GameState.switch(to, ...)
|
||||
end
|
||||
|
||||
-- Pop state from stack and return to it
|
||||
function GameState.pop(...)
|
||||
if #stack < 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local pre = current
|
||||
current = table.remove(stack)
|
||||
|
||||
if pre then
|
||||
call(pre, 'leave')
|
||||
end
|
||||
|
||||
return call(current, 'resume', pre, ...)
|
||||
end
|
||||
|
||||
-- Get current state
|
||||
function GameState.current()
|
||||
return current
|
||||
end
|
||||
|
||||
-- Register callbacks to RL framework
|
||||
function GameState.registerEvents()
|
||||
-- Override RL callbacks to forward to current state
|
||||
local RL_init = RL.init
|
||||
local RL_update = RL.update
|
||||
local RL_draw = RL.draw
|
||||
local RL_event = RL.event
|
||||
local RL_exit = RL.exit
|
||||
|
||||
RL.init = function()
|
||||
if RL_init then RL_init() end
|
||||
call(current, 'init')
|
||||
end
|
||||
|
||||
RL.update = function(dt)
|
||||
if RL_update then RL_update(dt) end
|
||||
call(current, 'update', dt)
|
||||
end
|
||||
|
||||
RL.draw = function()
|
||||
if RL_draw then RL_draw() end
|
||||
call(current, 'draw')
|
||||
end
|
||||
|
||||
RL.event = function(event)
|
||||
if RL_event then RL_event(event) end
|
||||
call(current, 'event', event)
|
||||
end
|
||||
|
||||
RL.exit = function()
|
||||
if RL_exit then RL_exit() end
|
||||
call(current, 'exit')
|
||||
end
|
||||
end
|
||||
|
||||
-- State callbacks that can be implemented:
|
||||
-- state:enter(previous, ...) - Called when entering state
|
||||
-- state:leave() - Called when leaving state
|
||||
-- state:resume(previous, ...) - Called when returning to state via pop()
|
||||
-- state:init() - Called once at game start if state is initial
|
||||
-- state:update(dt) - Called every frame
|
||||
-- state:draw() - Called every frame for rendering
|
||||
-- state:event(event) - Called on input events
|
||||
-- state:exit() - Called when game exits
|
||||
|
||||
return GameState
|
||||
Reference in New Issue
Block a user