Make proper modules

This commit is contained in:
Matthias Richter 2011-01-18 17:44:38 +01:00
parent 0dc9eacc57
commit d1d6dbb056
6 changed files with 146 additions and 100 deletions

View File

@ -24,11 +24,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
require 'vector' local setmetatable, require, love = setmetatable, require, love
module(...)
local vector = require(_PACKAGE..'vector')
local camera = {} local camera = {}
camera.__index = camera camera.__index = camera
function Camera(pos, zoom, rot)
function new(pos, zoom, rot)
local pos = pos or vector(love.graphics.getWidth(), love.graphics.getHeight()) / 2 local pos = pos or vector(love.graphics.getWidth(), love.graphics.getHeight()) / 2
local zoom = zoom or 1 local zoom = zoom or 1
local rot = rot or 0 local rot = rot or 0
@ -42,6 +45,7 @@ end
function camera:translate(t) function camera:translate(t)
self.pos = self.pos + t self.pos = self.pos + t
end end
camera.move = camera.translate
function camera:predraw() function camera:predraw()
local center = vector(love.graphics.getWidth(), love.graphics.getHeight()) / (self.zoom * 2) local center = vector(love.graphics.getWidth(), love.graphics.getHeight()) / (self.zoom * 2)
@ -77,3 +81,10 @@ end
function camera:mousepos() function camera:mousepos()
return self:toWorldCoords(vector(love.mouse.getPosition())) return self:toWorldCoords(vector(love.mouse.getPosition()))
end end
-- camera() as a shortcut to new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -24,8 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local type, assert, pairs = type, assert, pairs
local tostring, string_format = tostring, string.format
module(...)
local function __NULL__() end local function __NULL__() end
function Class(constructor) function new(constructor)
-- check name and constructor -- check name and constructor
local name = '<unnamed class>' local name = '<unnamed class>'
if type(constructor) == "table" then if type(constructor) == "table" then
@ -33,16 +38,16 @@ function Class(constructor)
constructor = constructor[1] constructor = constructor[1]
end end
assert(not constructor or type(constructor) == "function", assert(not constructor or type(constructor) == "function",
string.format('%s: constructor has to be nil or a function', name)) string_format('%s: constructor has to be nil or a function', name))
-- build class -- build class
local c = {} local c = {}
c.__index = c c.__index = c
c.__tostring = function() return string.format("<instance of %s>", name) end c.__tostring = function() return string_format("<instance of %s>", name) end
c.construct = constructor or __NULL__ c.construct = constructor or __NULL__
c.Construct = constructor or __NULL__ c.Construct = constructor or __NULL__
c.inherit = Inherit c.inherit = inherit
c.Inherit = Inherit c.Inherit = inherit
local meta = { local meta = {
__call = function(self, ...) __call = function(self, ...)
@ -56,7 +61,7 @@ function Class(constructor)
return setmetatable(c, meta) return setmetatable(c, meta)
end end
function Inherit(class, interface, ...) function inherit(class, interface, ...)
if not interface then return end if not interface then return end
-- __index and construct are not overwritten as for them class[name] is defined -- __index and construct are not overwritten as for them class[name] is defined
@ -66,5 +71,12 @@ function Inherit(class, interface, ...)
end end
end end
Inherit(class, ...) inherit(class, ...)
end
-- class() as shortcut to class.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end end

View File

@ -24,12 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
Gamestate = {} local error, assert, love = error, assert, love
module(...)
local function __NULL__() end local function __NULL__() end
-- default gamestate produces error on every callback -- default gamestate produces error on every callback
local function __ERROR__() error("Gamestate not initialized. Use Gamestate.switch()") end local function __ERROR__() error("Gamestate not initialized. Use Gamestate.switch()") end
Gamestate.current = { current = {
enter = __ERROR__, enter = __ERROR__,
leave = __NULL__, leave = __NULL__,
update = __ERROR__, update = __ERROR__,
@ -42,7 +43,7 @@ Gamestate.current = {
joystickreleased = __ERROR__, joystickreleased = __ERROR__,
} }
function Gamestate.new() function new()
return { return {
enter = __NULL__, enter = __NULL__,
leave = __NULL__, leave = __NULL__,
@ -57,77 +58,77 @@ function Gamestate.new()
} }
end end
function Gamestate.switch(to, ...) function switch(to, ...)
assert(to, "Missing argument: Gamestate to switch to") assert(to, "Missing argument: Gamestate to switch to")
Gamestate.current:leave() current:leave()
local pre = Gamestate.current local pre = current
Gamestate.current = to current = to
Gamestate.current:enter(pre, ...) current:enter(pre, ...)
end end
local _update local _update
function Gamestate.update(...) function update(...)
if _update then _update(...) end if _update then _update(...) end
Gamestate.current:update(...) current:update(...)
end end
local _draw local _draw
function Gamestate.draw(...) function draw(...)
if _draw then _draw(...) end if _draw then _draw(...) end
Gamestate.current:draw(...) current:draw(...)
end end
local _keypressed local _keypressed
function Gamestate.keypressed(...) function keypressed(...)
if _keypressed then _keypressed(...) end if _keypressed then _keypressed(...) end
Gamestate.current:keypressed(...) current:keypressed(...)
end end
local _keyreleased local _keyreleased
function Gamestate.keyreleased(...) function keyreleased(...)
if _keyreleased then _keyreleased(...) end if _keyreleased then _keyreleased(...) end
Gamestate.current:keyreleased(...) current:keyreleased(...)
end end
local _mousepressed local _mousepressed
function Gamestate.mousepressed(...) function mousepressed(...)
if _mousereleased then _mousepressed(...) end if _mousereleased then _mousepressed(...) end
Gamestate.current:mousepressed(...) current:mousepressed(...)
end end
local _mousereleased local _mousereleased
function Gamestate.mousereleased(...) function mousereleased(...)
if _mousereleased then _mousereleased(...) end if _mousereleased then _mousereleased(...) end
Gamestate.current:mousereleased(...) current:mousereleased(...)
end end
local _joystickpressed local _joystickpressed
function Gamestate.joystickpressed(...) function joystickpressed(...)
if _joystickpressed then _joystickpressed(...) end if _joystickpressed then _joystickpressed(...) end
Gamestate.current:joystickpressed(...) current:joystickpressed(...)
end end
local _joystickreleased local _joystickreleased
function Gamestate.joystickreleased(...) function joystickreleased(...)
if _joystickreleased then _joystickreleased(...) end if _joystickreleased then _joystickreleased(...) end
Gamestate.current:joystickreleased(...) current:joystickreleased(...)
end end
function Gamestate.registerEvents() function registerEvents()
_update = love.update _update = love.update
love.update = Gamestate.update love.update = update
_draw = love.draw _draw = love.draw
love.draw = Gamestate.draw love.draw = draw
_keypressed = love.keypressed _keypressed = love.keypressed
love.keypressed = Gamestate.keypressed love.keypressed = keypressed
_keyreleased = love.keyreleased _keyreleased = love.keyreleased
love.keyreleased = Gamestate.keyreleased love.keyreleased = keyreleased
_mousepressed = love.mousepressed _mousepressed = love.mousepressed
love.mousepressed = Gamestate.mousepressed love.mousepressed = mousepressed
_mousereleased = love.mousereleased _mousereleased = love.mousereleased
love.mousereleased = Gamestate.mousereleased love.mousereleased = mousereleased
_joystickpressed = love.joystickpressed _joystickpressed = love.joystickpressed
love.joystickpressed = Gamestate.joystickpressed love.joystickpressed = joystickpressed
_joystickreleased = love.joystickreleased _joystickreleased = love.joystickreleased
love.joystickreleased = Gamestate.joystickreleased love.joystickreleased = joystickreleased
end end

View File

@ -24,10 +24,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
local setmetatable, getmetatable, table = setmetatable, getmetatable, table
module(...)
local ringbuffer = {} local ringbuffer = {}
ringbuffer.__index = ringbuffer ringbuffer.__index = ringbuffer
function Ringbuffer(...) function new(...)
local rb = {} local rb = {}
rb.items = {...} rb.items = {...}
rb.current = 1 rb.current = 1
@ -77,10 +79,7 @@ function ringbuffer:size()
end end
function ringbuffer:next() function ringbuffer:next()
self.current = self.current + 1 self.current = (self.current % #self.items) + 1
if self.current > #self.items then
self.current = 1
end
return self:get() return self:get()
end end
@ -90,3 +89,10 @@ function ringbuffer:prev()
self.current = #self.items self.current = #self.items
end end
end end
-- Ringbuffer() as a shortcut to Ringbuffer.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end

View File

@ -24,40 +24,44 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
Timer = {} local assert, type = assert, type
Timer.functions = {} local pairs, ipairs = pairs, ipairs
function Timer.update(dt) local min = math.min
module(...)
functions = {}
function update(dt)
local to_remove = {} local to_remove = {}
for func, delay in pairs(Timer.functions) do for func, delay in pairs(functions) do
delay = delay - dt delay = delay - dt
if delay <= 0 then if delay <= 0 then
to_remove[#to_remove+1] = func to_remove[#to_remove+1] = func
else else
Timer.functions[func] = delay functions[func] = delay
end end
end end
for _,func in ipairs(to_remove) do for _,func in ipairs(to_remove) do
Timer.functions[func] = nil functions[func] = nil
func(func) func(func)
end end
end end
function Timer.add(delay, func) function add(delay, func)
assert(type(func) == "function", "second argument needs to be a function") assert(type(func) == "function", "second argument needs to be a function")
Timer.functions[func] = delay functions[func] = delay
end end
function Timer.addPeriodic(delay, func, count) function addPeriodic(delay, func, count)
assert(type(func) == "function", "second argument needs to be a function") assert(type(func) == "function", "second argument needs to be a function")
if count then if count then
Timer.add(delay, function(f) func(func) count = count - 1 if count > 0 then Timer.add(delay, f) end end) add(delay, function(f) func(func) count = count - 1 if count > 0 then add(delay, f) end end)
else else
Timer.add(delay, function(f) func(func) Timer.add(delay, f) end) add(delay, function(f) func(func) add(delay, f) end)
end end
end end
function Timer.clear() function clear()
Timer.functions = {} functions = {}
end end
function Interpolator(length, func) function Interpolator(length, func)
@ -65,7 +69,7 @@ function Interpolator(length, func)
local t = 0 local t = 0
return function(dt, ...) return function(dt, ...)
t = t + dt t = t + dt
return t <= length or nil, func(math.min(1, (t-dt)/length), ...) return t <= length or nil, func(min(1, (t-dt)/length), ...)
end end
end end

View File

@ -24,121 +24,133 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
local Vector = {} local setmetatable, getmetatable = setmetatable, getmetatable
Vector.__index = Vector local assert, type, tonumber = assert, type, tonumber
local sqrt, cos, sin = math.sqrt, math.cos, math.sin
module(...)
function vector(x,y) local vector = {}
vector.__index = vector
function new(x,y)
local v = {x = x or 0, y = y or 0} local v = {x = x or 0, y = y or 0}
setmetatable(v, Vector) setmetatable(v, vector)
return v return v
end end
function isvector(v) function isvector(v)
return getmetatable(v) == Vector return getmetatable(v) == vector
end end
function Vector:clone() function vector:clone()
return vector(self.x, self.y) return new(self.x, self.y)
end end
function Vector:unpack() function vector:unpack()
return self.x, self.y return self.x, self.y
end end
function Vector:__tostring() function vector:__tostring()
return "("..tonumber(self.x)..","..tonumber(self.y)..")" return "("..tonumber(self.x)..","..tonumber(self.y)..")"
end end
function Vector.__unm(a) function vector.__unm(a)
return vector(-a.x, -a.y) return new(-a.x, -a.y)
end end
function Vector.__add(a,b) function vector.__add(a,b)
assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)") assert(isvector(a) and isvector(b), "Add: wrong argument types (<vector> expected)")
return vector(a.x+b.x, a.y+b.y) return new(a.x+b.x, a.y+b.y)
end end
function Vector.__sub(a,b) function vector.__sub(a,b)
assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)") assert(isvector(a) and isvector(b), "Sub: wrong argument types (<vector> expected)")
return vector(a.x-b.x, a.y-b.y) return new(a.x-b.x, a.y-b.y)
end end
function Vector.__mul(a,b) function vector.__mul(a,b)
if type(a) == "number" then if type(a) == "number" then
return vector(a*b.x, a*b.y) return new(a*b.x, a*b.y)
elseif type(b) == "number" then elseif type(b) == "number" then
return vector(b*a.x, b*a.y) return new(b*a.x, b*a.y)
else else
assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)") assert(isvector(a) and isvector(b), "Mul: wrong argument types (<vector> or <number> expected)")
return a.x*b.x + a.y*b.y return a.x*b.x + a.y*b.y
end end
end end
function Vector.__div(a,b) function vector.__div(a,b)
assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)") assert(isvector(a) and type(b) == "number", "wrong argument types (expected <vector> / <number>)")
return vector(a.x / b, a.y / b) return new(a.x / b, a.y / b)
end end
function Vector.__eq(a,b) function vector.__eq(a,b)
return a.x == b.x and a.y == b.y return a.x == b.x and a.y == b.y
end end
function Vector.__lt(a,b) function vector.__lt(a,b)
return a.x < b.x or (a.x == b.x and a.y < b.y) return a.x < b.x or (a.x == b.x and a.y < b.y)
end end
function Vector.__le(a,b) function vector.__le(a,b)
return a.x <= b.x and a.y <= b.y return a.x <= b.x and a.y <= b.y
end end
function Vector.permul(a,b) function vector.permul(a,b)
assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)") assert(isvector(a) and isvector(b), "permul: wrong argument types (<vector> expected)")
return vector(a.x*b.x, a.y*b.y) return new(a.x*b.x, a.y*b.y)
end end
function Vector:len2() function vector:len2()
return self * self return self * self
end end
function Vector:len() function vector:len()
return math.sqrt(self*self) return sqrt(self*self)
end end
function Vector.dist(a, b) function vector.dist(a, b)
assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)") assert(isvector(a) and isvector(b), "dist: wrong argument types (<vector> expected)")
return (b-a):len() return (b-a):len()
end end
function Vector:normalize_inplace() function vector:normalize_inplace()
local l = self:len() local l = self:len()
self.x, self.y = self.x / l, self.y / l self.x, self.y = self.x / l, self.y / l
return self return self
end end
function Vector:normalized() function vector:normalized()
return self / self:len() return self / self:len()
end end
function Vector:rotate_inplace(phi) function vector:rotate_inplace(phi)
local c, s = math.cos(phi), math.sin(phi) local c, s = cos(phi), sin(phi)
self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y
return self return self
end end
function Vector:rotated(phi) function vector:rotated(phi)
return self:clone():rotate_inplace(phi) return self:clone():rotate_inplace(phi)
end end
function Vector:perpendicular() function vector:perpendicular()
return vector(-self.y, self.x) return new(-self.y, self.x)
end end
function Vector:projectOn(v) function vector:projectOn(v)
assert(isvector(v), "invalid argument: cannot project onto anything other than a vector.") assert(isvector(v), "invalid argument: cannot project onto anything other than a new.")
return (self * v) * v / v:len2() return (self * v) * v / v:len2()
end end
function Vector:cross(other) function vector:cross(other)
assert(isvector(other), "cross: wrong argument types (<vector> expected)") assert(isvector(other), "cross: wrong argument types (<vector> expected)")
return self.x * other.y - self.y * other.x return self.x * other.y - self.y * other.x
end end
-- vector() as shortcut to vector.new()
do
local m = {}
m.__call = function(_, ...) return new(...) end
setmetatable(_M, m)
end