This is a list of small lua libraries that work well for lutro games.
A minimal animation library.
local animation = {}
animation.__index = animation
function NewAnimation(image, width, height, period, speed)
local a = {}
a.image = image
a.timer = 0
a.width = width
a.height = height
a.playing = true
a.speed = speed
a.period = period
a.steps = a.image:getWidth() / a.width
return setmetatable(a, animation)
end
function animation:update(dt)
if not self.playing then return end
self.timer = self.timer + dt * self.speed
if self.timer > self.steps * self.period then
self.timer = 0
end
end
function animation:draw(x, y)
local id = math.floor(self.timer / self.period + 1)
local tw = self.width
local th = self.height
local sw = self.image:getWidth()
local sh = self.image:getHeight()
local q = love.graphics.newQuad(
((id-1)%(sw/tw))*tw,
0,
tw, th,
sw, sh)
love.graphics.draw(
self.image,
q,
math.floor(x), math.floor(y)
)
end
Usage:
require "libs/anim"
function love.load()
local IMG_shizuka_stand_left = love.graphics.newImage("assets/spr/shizuka_stand_left.png")
local anim = NewAnimation(IMG_shizuka_stand_left, 24, 24, 1, 20)
end
function love.update(dt)
anim:update(dt)
end
function love.draw()
anim:draw(16, 32)
end
Simple LÖVE Audio Manager. Makes it easier to play the same audio effect concurrently.
-- Simple LÖVE Audio Manager
--
-- Copyright (c) 2011 Matthias Richter
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- Except as contained in this notice, the name(s) of the above copyright holders
-- shall not be used in advertising or otherwise to promote the sale, use or
-- other dealings in this Software without prior written authorization.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
--
local newInstance = love.audio.newSource
local stop = love.audio.stop
------------------
-- source class --
------------------
local Source = {}
Source.__index = Source
Source.__newindex = function(_,k) error(('Cannot write key %s'):format(tostring(k))) end
function NewSource(target, how)
local s = {
_paused = false,
target = target,
how = how,
instances = {},
looping = false,
pitch = 1,
volume = 1,
}
if how == 'static' and type(target) == 'string' then
s.target = love.sound.newSoundData(target)
end
return setmetatable(s, Source)
end
local function remove_stopped(sources)
local remove = {}
for s in pairs(sources) do
remove[s] = true
end
for s in pairs(remove) do
sources[s] = nil
end
end
local function get_target(target)
if type(target) == 'table' then
return target[math.random(1,#target)]
end
return target
end
local play_instance, stop_instance
function Source:play()
remove_stopped(self.instances)
if self._paused then self:stop() end
local instance = newInstance(get_target(self.target), self.how)
-- overwrite instance:stop() and instance:play()
if not (play_instance and stop_instance) then
play_instance = getmetatable(instance).play
getmetatable(instance).play = error
stop_instance = getmetatable(instance).stop
getmetatable(instance).stop = function(this)
stop_instance(this)
self.instances[this] = nil
end
end
instance:setLooping(self.looping)
instance:setPitch(self.pitch)
instance:setVolume(self.volume)
self.instances[instance] = instance
play_instance(instance)
return instance
end
function Source:stop()
for s in pairs(self.instances) do
s:stop()
end
self._paused = false
self.instances = {}
end
function Source:pause()
if self._paused then return end
for s in pairs(self.instances) do
s:pause()
end
self._paused = true
end
function Source:resume()
if not self._paused then return end
for s in pairs(self.instances) do
s:resume()
end
self._paused = false
end
function Source:isStatic()
return self.how ~= "stream"
end
function Source:isPlaying()
for s in pairs(self.instances) do
return s:isPlaying()
end
end
function Source:tell(what)
for s in pairs(self.instances) do
return s:tell(what)
end
end
function Source:seek(n, what)
for s in pairs(self.instances) do
return s:seek(n, what)
end
end
-- getter/setter for looping, pitch and volume
for _, property in ipairs{'looping', 'pitch', 'volume'} do
local name = property:sub(1,1):upper() .. property:sub(2)
Source['get' .. name] = function(self)
return self[property]
end
Source['set' .. name] = function(self, val)
self[property] = val
for s in pairs(self.instances) do
s['set' .. name](s, val)
end
end
end
Source.isLooping = Source.getLooping
Usage:
require "libs/slam"
function love.load()
SFX_ok = NewSource("assets/sfx/ok.wav", "static")
end
function love.update(dt)
SFX_ok:play()
end