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.
]]--
require 'vector'
local setmetatable, require, love = setmetatable, require, love
module(...)
local vector = require(_PACKAGE..'vector')
local 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 zoom = zoom or 1
local rot = rot or 0
@ -42,6 +45,7 @@ end
function camera:translate(t)
self.pos = self.pos + t
end
camera.move = camera.translate
function camera:predraw()
local center = vector(love.graphics.getWidth(), love.graphics.getHeight()) / (self.zoom * 2)
@ -77,3 +81,10 @@ end
function camera:mousepos()
return self:toWorldCoords(vector(love.mouse.getPosition()))
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.
]]--
local setmetatable, getmetatable = setmetatable, getmetatable
local type, assert, pairs = type, assert, pairs
local tostring, string_format = tostring, string.format
module(...)
local function __NULL__() end
function Class(constructor)
function new(constructor)
-- check name and constructor
local name = '<unnamed class>'
if type(constructor) == "table" then
@ -33,16 +38,16 @@ function Class(constructor)
constructor = constructor[1]
end
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
local 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.inherit = Inherit
c.Inherit = Inherit
c.inherit = inherit
c.Inherit = inherit
local meta = {
__call = function(self, ...)
@ -56,7 +61,7 @@ function Class(constructor)
return setmetatable(c, meta)
end
function Inherit(class, interface, ...)
function inherit(class, interface, ...)
if not interface then return end
-- __index and construct are not overwritten as for them class[name] is defined
@ -66,5 +71,12 @@ function Inherit(class, interface, ...)
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

View File

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

View File

@ -24,10 +24,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--
local setmetatable, getmetatable, table = setmetatable, getmetatable, table
module(...)
local ringbuffer = {}
ringbuffer.__index = ringbuffer
function Ringbuffer(...)
function new(...)
local rb = {}
rb.items = {...}
rb.current = 1
@ -77,10 +79,7 @@ function ringbuffer:size()
end
function ringbuffer:next()
self.current = self.current + 1
if self.current > #self.items then
self.current = 1
end
self.current = (self.current % #self.items) + 1
return self:get()
end
@ -90,3 +89,10 @@ function ringbuffer:prev()
self.current = #self.items
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.
]]--
Timer = {}
Timer.functions = {}
function Timer.update(dt)
local assert, type = assert, type
local pairs, ipairs = pairs, ipairs
local min = math.min
module(...)
functions = {}
function update(dt)
local to_remove = {}
for func, delay in pairs(Timer.functions) do
for func, delay in pairs(functions) do
delay = delay - dt
if delay <= 0 then
to_remove[#to_remove+1] = func
else
Timer.functions[func] = delay
functions[func] = delay
end
end
for _,func in ipairs(to_remove) do
Timer.functions[func] = nil
functions[func] = nil
func(func)
end
end
function Timer.add(delay, func)
function add(delay, func)
assert(type(func) == "function", "second argument needs to be a function")
Timer.functions[func] = delay
functions[func] = delay
end
function Timer.addPeriodic(delay, func, count)
function addPeriodic(delay, func, count)
assert(type(func) == "function", "second argument needs to be a function")
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
Timer.add(delay, function(f) func(func) Timer.add(delay, f) end)
add(delay, function(f) func(func) add(delay, f) end)
end
end
function Timer.clear()
Timer.functions = {}
function clear()
functions = {}
end
function Interpolator(length, func)
@ -65,7 +69,7 @@ function Interpolator(length, func)
local t = 0
return function(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

View File

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