Changed indentation to the one true style
This commit is contained in:
parent
b914b5217c
commit
b377c9805d
6 changed files with 353 additions and 353 deletions
|
@ -31,87 +31,87 @@ local camera = {}
|
||||||
camera.__index = camera
|
camera.__index = camera
|
||||||
|
|
||||||
local function new(x,y, zoom, rot)
|
local function new(x,y, zoom, rot)
|
||||||
x,y = x or love.graphics.getWidth()/2, y or love.graphics.getHeight()/2
|
x,y = x or love.graphics.getWidth()/2, y or love.graphics.getHeight()/2
|
||||||
zoom = zoom or 1
|
zoom = zoom or 1
|
||||||
rot = rot or 0
|
rot = rot or 0
|
||||||
return setmetatable({x = x, y = y, scale = zoom, rot = rot}, camera)
|
return setmetatable({x = x, y = y, scale = zoom, rot = rot}, camera)
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:lookAt(x,y)
|
function camera:lookAt(x,y)
|
||||||
self.x, self.y = x,y
|
self.x, self.y = x,y
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:move(x,y)
|
function camera:move(x,y)
|
||||||
self.x, self.y = self.x + x, self.y + y
|
self.x, self.y = self.x + x, self.y + y
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:pos()
|
function camera:pos()
|
||||||
return self.x, self.y
|
return self.x, self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:rotate(phi)
|
function camera:rotate(phi)
|
||||||
self.rot = self.rot + phi
|
self.rot = self.rot + phi
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:rotateTo(phi)
|
function camera:rotateTo(phi)
|
||||||
self.rot = phi
|
self.rot = phi
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:zoom(mul)
|
function camera:zoom(mul)
|
||||||
self.scale = self.scale * mul
|
self.scale = self.scale * mul
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:zoomTo(zoom)
|
function camera:zoomTo(zoom)
|
||||||
self.scale = zoom
|
self.scale = zoom
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:attach()
|
function camera:attach()
|
||||||
local cx,cy = love.graphics.getWidth()/(2*self.scale), love.graphics.getHeight()/(2*self.scale)
|
local cx,cy = love.graphics.getWidth()/(2*self.scale), love.graphics.getHeight()/(2*self.scale)
|
||||||
love.graphics.push()
|
love.graphics.push()
|
||||||
love.graphics.scale(self.scale)
|
love.graphics.scale(self.scale)
|
||||||
love.graphics.translate(cx, cy)
|
love.graphics.translate(cx, cy)
|
||||||
love.graphics.rotate(self.rot)
|
love.graphics.rotate(self.rot)
|
||||||
love.graphics.translate(-self.x, -self.y)
|
love.graphics.translate(-self.x, -self.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:detach()
|
function camera:detach()
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:draw(func)
|
function camera:draw(func)
|
||||||
self:attach()
|
self:attach()
|
||||||
func()
|
func()
|
||||||
self:detach()
|
self:detach()
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:cameraCoords(x,y)
|
function camera:cameraCoords(x,y)
|
||||||
-- x,y = ((x,y) - (self.x, self.y)):rotated(self.rot) * self.scale + center
|
-- x,y = ((x,y) - (self.x, self.y)):rotated(self.rot) * self.scale + center
|
||||||
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
|
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
|
||||||
local c,s = cos(self.rot), sin(self.rot)
|
local c,s = cos(self.rot), sin(self.rot)
|
||||||
x,y = x - self.x, y - self.y
|
x,y = x - self.x, y - self.y
|
||||||
x,y = c*x - s*y, s*x + c*y
|
x,y = c*x - s*y, s*x + c*y
|
||||||
return x*self.scale + w/2, y*self.scale + h/2
|
return x*self.scale + w/2, y*self.scale + h/2
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:worldCoords(x,y)
|
function camera:worldCoords(x,y)
|
||||||
-- x,y = (((x,y) - center) / self.scale):rotated(-self.rot) + (self.x,self.y)
|
-- x,y = (((x,y) - center) / self.scale):rotated(-self.rot) + (self.x,self.y)
|
||||||
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
|
local w,h = love.graphics.getWidth(), love.graphics.getHeight()
|
||||||
local c,s = cos(-self.rot), sin(-self.rot)
|
local c,s = cos(-self.rot), sin(-self.rot)
|
||||||
x,y = (x - w/2) / self.scale, (y - h/2) / self.scale
|
x,y = (x - w/2) / self.scale, (y - h/2) / self.scale
|
||||||
x,y = c*x - s*y, s*x + c*y
|
x,y = c*x - s*y, s*x + c*y
|
||||||
return x+self.x, y+self.y
|
return x+self.x, y+self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
function camera:mousepos()
|
function camera:mousepos()
|
||||||
return self:worldCoords(love.mouse.getPosition())
|
return self:worldCoords(love.mouse.getPosition())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- the module
|
-- the module
|
||||||
return setmetatable({new = new},
|
return setmetatable({new = new},
|
||||||
{__call = function(_, ...) return new(...) end})
|
{__call = function(_, ...) return new(...) end})
|
||||||
|
|
|
@ -28,70 +28,70 @@ local function __NULL__() end
|
||||||
|
|
||||||
-- default gamestate produces error on every callback
|
-- default gamestate produces error on every callback
|
||||||
local state_init = setmetatable({leave = __NULL__},
|
local state_init = setmetatable({leave = __NULL__},
|
||||||
{__index = function() error("Gamestate not initialized. Use Gamestate.switch()") end})
|
{__index = function() error("Gamestate not initialized. Use Gamestate.switch()") end})
|
||||||
local stack = {state_init}
|
local stack = {state_init}
|
||||||
|
|
||||||
local GS = {}
|
local GS = {}
|
||||||
function GS.new(t) return t or {} end -- constructor - deprecated!
|
function GS.new(t) return t or {} end -- constructor - deprecated!
|
||||||
|
|
||||||
function GS.switch(to, ...)
|
function GS.switch(to, ...)
|
||||||
assert(to, "Missing argument: Gamestate to switch to")
|
assert(to, "Missing argument: Gamestate to switch to")
|
||||||
assert(to ~= GS, "Can't call switch with colon operator")
|
assert(to ~= GS, "Can't call switch with colon operator")
|
||||||
local pre = stack[#stack]
|
local pre = stack[#stack]
|
||||||
;(pre.leave or __NULL__)(pre)
|
;(pre.leave or __NULL__)(pre)
|
||||||
;(to.init or __NULL__)(to)
|
;(to.init or __NULL__)(to)
|
||||||
to.init = nil
|
to.init = nil
|
||||||
stack[#stack] = to
|
stack[#stack] = to
|
||||||
return (to.enter or __NULL__)(to, pre, ...)
|
return (to.enter or __NULL__)(to, pre, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GS.push(to, ...)
|
function GS.push(to, ...)
|
||||||
assert(to, "Missing argument: Gamestate to switch to")
|
assert(to, "Missing argument: Gamestate to switch to")
|
||||||
assert(to ~= GS, "Can't call push with colon operator")
|
assert(to ~= GS, "Can't call push with colon operator")
|
||||||
local pre = stack[#stack]
|
local pre = stack[#stack]
|
||||||
;(to.init or __NULL__)(to)
|
;(to.init or __NULL__)(to)
|
||||||
to.init = nil
|
to.init = nil
|
||||||
stack[#stack+1] = to
|
stack[#stack+1] = to
|
||||||
return (to.enter or __NULL__)(to, pre, ...)
|
return (to.enter or __NULL__)(to, pre, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GS.pop(...)
|
function GS.pop(...)
|
||||||
assert(#stack > 1, "No more states to pop!")
|
assert(#stack > 1, "No more states to pop!")
|
||||||
local pre = stack[#stack]
|
local pre = stack[#stack]
|
||||||
stack[#stack] = nil
|
stack[#stack] = nil
|
||||||
;(pre.leave or __NULL__)(pre)
|
;(pre.leave or __NULL__)(pre)
|
||||||
return (stack[#stack].resume or __NULL__)(pre, ...)
|
return (stack[#stack].resume or __NULL__)(pre, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GS.current()
|
function GS.current()
|
||||||
return stack[#stack]
|
return stack[#stack]
|
||||||
end
|
end
|
||||||
|
|
||||||
local all_callbacks = {
|
local all_callbacks = {
|
||||||
'draw', 'errhand', 'focus', 'keypressed', 'keyreleased', 'mousefocus',
|
'draw', 'errhand', 'focus', 'keypressed', 'keyreleased', 'mousefocus',
|
||||||
'mousepressed', 'mousereleased', 'quit', 'resize', 'textinput',
|
'mousepressed', 'mousereleased', 'quit', 'resize', 'textinput',
|
||||||
'threaderror', 'update', 'visible', 'gamepadaxis', 'gamepadpressed',
|
'threaderror', 'update', 'visible', 'gamepadaxis', 'gamepadpressed',
|
||||||
'gamepadreleased', 'joystickadded', 'joystickaxis', 'joystickhat',
|
'gamepadreleased', 'joystickadded', 'joystickaxis', 'joystickhat',
|
||||||
'joystickpressed', 'joystickreleased', 'joystickremoved'
|
'joystickpressed', 'joystickreleased', 'joystickremoved'
|
||||||
}
|
}
|
||||||
|
|
||||||
function GS.registerEvents(callbacks)
|
function GS.registerEvents(callbacks)
|
||||||
local registry = {}
|
local registry = {}
|
||||||
callbacks = callbacks or all_callbacks
|
callbacks = callbacks or all_callbacks
|
||||||
for _, f in ipairs(callbacks) do
|
for _, f in ipairs(callbacks) do
|
||||||
registry[f] = love[f] or __NULL__
|
registry[f] = love[f] or __NULL__
|
||||||
love[f] = function(...)
|
love[f] = function(...)
|
||||||
registry[f](...)
|
registry[f](...)
|
||||||
return GS[f](...)
|
return GS[f](...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- forward any undefined functions
|
-- forward any undefined functions
|
||||||
setmetatable(GS, {__index = function(_, func)
|
setmetatable(GS, {__index = function(_, func)
|
||||||
return function(...)
|
return function(...)
|
||||||
return (stack[#stack][func] or __NULL__)(stack[#stack], ...)
|
return (stack[#stack][func] or __NULL__)(stack[#stack], ...)
|
||||||
end
|
end
|
||||||
end})
|
end})
|
||||||
|
|
||||||
return GS
|
return GS
|
||||||
|
|
|
@ -26,68 +26,68 @@ THE SOFTWARE.
|
||||||
|
|
||||||
local Registry = {}
|
local Registry = {}
|
||||||
Registry.__index = function(self, key)
|
Registry.__index = function(self, key)
|
||||||
return Registry[key] or (function()
|
return Registry[key] or (function()
|
||||||
local t = {}
|
local t = {}
|
||||||
rawset(self, key, t)
|
rawset(self, key, t)
|
||||||
return t
|
return t
|
||||||
end)()
|
end)()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:register(s, f)
|
function Registry:register(s, f)
|
||||||
self[s][f] = f
|
self[s][f] = f
|
||||||
return f
|
return f
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:emit(s, ...)
|
function Registry:emit(s, ...)
|
||||||
for f in pairs(self[s]) do
|
for f in pairs(self[s]) do
|
||||||
f(...)
|
f(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:remove(s, ...)
|
function Registry:remove(s, ...)
|
||||||
local f = {...}
|
local f = {...}
|
||||||
for i = 1,select('#', ...) do
|
for i = 1,select('#', ...) do
|
||||||
self[s][f[i]] = nil
|
self[s][f[i]] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:clear(...)
|
function Registry:clear(...)
|
||||||
local s = {...}
|
local s = {...}
|
||||||
for i = 1,select('#', ...) do
|
for i = 1,select('#', ...) do
|
||||||
self[s[i]] = {}
|
self[s[i]] = {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:emit_pattern(p, ...)
|
function Registry:emit_pattern(p, ...)
|
||||||
for s in pairs(self) do
|
for s in pairs(self) do
|
||||||
if s:match(p) then self:emit(s, ...) end
|
if s:match(p) then self:emit(s, ...) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:remove_pattern(p, ...)
|
function Registry:remove_pattern(p, ...)
|
||||||
for s in pairs(self) do
|
for s in pairs(self) do
|
||||||
if s:match(p) then self:remove(s, ...) end
|
if s:match(p) then self:remove(s, ...) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Registry:clear_pattern(p)
|
function Registry:clear_pattern(p)
|
||||||
for s in pairs(self) do
|
for s in pairs(self) do
|
||||||
if s:match(p) then self[s] = {} end
|
if s:match(p) then self[s] = {} end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function new()
|
local function new()
|
||||||
return setmetatable({}, Registry)
|
return setmetatable({}, Registry)
|
||||||
end
|
end
|
||||||
local default = new()
|
local default = new()
|
||||||
|
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
new = new,
|
new = new,
|
||||||
register = function(...) return default:register(...) end,
|
register = function(...) return default:register(...) end,
|
||||||
emit = function(...) default:emit(...) end,
|
emit = function(...) default:emit(...) end,
|
||||||
remove = function(...) default:remove(...) end,
|
remove = function(...) default:remove(...) end,
|
||||||
clear = function(...) default:clear(...) end,
|
clear = function(...) default:clear(...) end,
|
||||||
emit_pattern = function(...) default:emit_pattern(...) end,
|
emit_pattern = function(...) default:emit_pattern(...) end,
|
||||||
remove_pattern = function(...) default:remove_pattern(...) end,
|
remove_pattern = function(...) default:remove_pattern(...) end,
|
||||||
clear_pattern = function(...) default:clear_pattern(...) end,
|
clear_pattern = function(...) default:clear_pattern(...) end,
|
||||||
}, {__call = new})
|
}, {__call = new})
|
||||||
|
|
222
hump/timer.lua
222
hump/timer.lua
|
@ -30,144 +30,144 @@ Timer.__index = Timer
|
||||||
local function _nothing_() end
|
local function _nothing_() end
|
||||||
|
|
||||||
local function new()
|
local function new()
|
||||||
return setmetatable({functions = {}, tween = Timer.tween}, Timer)
|
return setmetatable({functions = {}, tween = Timer.tween}, Timer)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:update(dt)
|
function Timer:update(dt)
|
||||||
local to_remove = {}
|
local to_remove = {}
|
||||||
for handle, delay in pairs(self.functions) do
|
for handle, delay in pairs(self.functions) do
|
||||||
delay = delay - dt
|
delay = delay - dt
|
||||||
if delay <= 0 then
|
if delay <= 0 then
|
||||||
to_remove[#to_remove+1] = handle
|
to_remove[#to_remove+1] = handle
|
||||||
end
|
end
|
||||||
self.functions[handle] = delay
|
self.functions[handle] = delay
|
||||||
handle.func(dt, delay)
|
handle.func(dt, delay)
|
||||||
end
|
end
|
||||||
for _,handle in ipairs(to_remove) do
|
for _,handle in ipairs(to_remove) do
|
||||||
self.functions[handle] = nil
|
self.functions[handle] = nil
|
||||||
handle.after(handle.after)
|
handle.after(handle.after)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:do_for(delay, func, after)
|
function Timer:do_for(delay, func, after)
|
||||||
local handle = {func = func, after = after or _nothing_}
|
local handle = {func = func, after = after or _nothing_}
|
||||||
self.functions[handle] = delay
|
self.functions[handle] = delay
|
||||||
return handle
|
return handle
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:add(delay, func)
|
function Timer:add(delay, func)
|
||||||
return self:do_for(delay, _nothing_, func)
|
return self:do_for(delay, _nothing_, func)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:addPeriodic(delay, func, count)
|
function Timer:addPeriodic(delay, func, count)
|
||||||
local count, handle = count or math.huge -- exploit below: math.huge - 1 = math.huge
|
local count, handle = count or math.huge -- exploit below: math.huge - 1 = math.huge
|
||||||
|
|
||||||
handle = self:add(delay, function(f)
|
handle = self:add(delay, function(f)
|
||||||
if func(func) == false then return end
|
if func(func) == false then return end
|
||||||
count = count - 1
|
count = count - 1
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
self.functions[handle] = delay
|
self.functions[handle] = delay
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
return handle
|
return handle
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:cancel(handle)
|
function Timer:cancel(handle)
|
||||||
self.functions[handle] = nil
|
self.functions[handle] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Timer:clear()
|
function Timer:clear()
|
||||||
self.functions = {}
|
self.functions = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
Timer.tween = setmetatable({
|
Timer.tween = setmetatable({
|
||||||
-- helper functions
|
-- helper functions
|
||||||
out = function(f) -- 'rotates' a function
|
out = function(f) -- 'rotates' a function
|
||||||
return function(s, ...) return 1 - f(1-s, ...) end
|
return function(s, ...) return 1 - f(1-s, ...) end
|
||||||
end,
|
end,
|
||||||
chain = function(f1, f2) -- concatenates two functions
|
chain = function(f1, f2) -- concatenates two functions
|
||||||
return function(s, ...) return (s < .5 and f1(2*s, ...) or 1 + f2(2*s-1, ...)) * .5 end
|
return function(s, ...) return (s < .5 and f1(2*s, ...) or 1 + f2(2*s-1, ...)) * .5 end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- useful tweening functions
|
-- useful tweening functions
|
||||||
linear = function(s) return s end,
|
linear = function(s) return s end,
|
||||||
quad = function(s) return s*s end,
|
quad = function(s) return s*s end,
|
||||||
cubic = function(s) return s*s*s end,
|
cubic = function(s) return s*s*s end,
|
||||||
quart = function(s) return s*s*s*s end,
|
quart = function(s) return s*s*s*s end,
|
||||||
quint = function(s) return s*s*s*s*s end,
|
quint = function(s) return s*s*s*s*s end,
|
||||||
sine = function(s) return 1-math.cos(s*math.pi/2) end,
|
sine = function(s) return 1-math.cos(s*math.pi/2) end,
|
||||||
expo = function(s) return 2^(10*(s-1)) end,
|
expo = function(s) return 2^(10*(s-1)) end,
|
||||||
circ = function(s) return 1 - math.sqrt(1-s*s) end,
|
circ = function(s) return 1 - math.sqrt(1-s*s) end,
|
||||||
|
|
||||||
back = function(s,bounciness)
|
back = function(s,bounciness)
|
||||||
bounciness = bounciness or 1.70158
|
bounciness = bounciness or 1.70158
|
||||||
return s*s*((bounciness+1)*s - bounciness)
|
return s*s*((bounciness+1)*s - bounciness)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
bounce = function(s) -- magic numbers ahead
|
bounce = function(s) -- magic numbers ahead
|
||||||
local a,b = 7.5625, 1/2.75
|
local a,b = 7.5625, 1/2.75
|
||||||
return math.min(a*s^2, a*(s-1.5*b)^2 + .75, a*(s-2.25*b)^2 + .9375, a*(s-2.625*b)^2 + .984375)
|
return math.min(a*s^2, a*(s-1.5*b)^2 + .75, a*(s-2.25*b)^2 + .9375, a*(s-2.625*b)^2 + .984375)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
elastic = function(s, amp, period)
|
elastic = function(s, amp, period)
|
||||||
amp, period = amp and math.max(1, amp) or 1, period or .3
|
amp, period = amp and math.max(1, amp) or 1, period or .3
|
||||||
return (-amp * math.sin(2*math.pi/period * (s-1) - math.asin(1/amp))) * 2^(10*(s-1))
|
return (-amp * math.sin(2*math.pi/period * (s-1) - math.asin(1/amp))) * 2^(10*(s-1))
|
||||||
end,
|
end,
|
||||||
}, {
|
}, {
|
||||||
|
|
||||||
-- register new tween
|
-- register new tween
|
||||||
__call = function(tween, self, len, subject, target, method, after, ...)
|
__call = function(tween, self, len, subject, target, method, after, ...)
|
||||||
-- recursively collects fields that are defined in both subject and target into a flat list
|
-- recursively collects fields that are defined in both subject and target into a flat list
|
||||||
local function tween_collect_payload(subject, target, out)
|
local function tween_collect_payload(subject, target, out)
|
||||||
for k,v in pairs(target) do
|
for k,v in pairs(target) do
|
||||||
local ref = subject[k]
|
local ref = subject[k]
|
||||||
assert(type(v) == type(ref), 'Type mismatch in field "'..k..'".')
|
assert(type(v) == type(ref), 'Type mismatch in field "'..k..'".')
|
||||||
if type(v) == 'table' then
|
if type(v) == 'table' then
|
||||||
tween_collect_payload(ref, v, out)
|
tween_collect_payload(ref, v, out)
|
||||||
else
|
else
|
||||||
local ok, delta = pcall(function() return (v-ref)*1 end)
|
local ok, delta = pcall(function() return (v-ref)*1 end)
|
||||||
assert(ok, 'Field "'..k..'" does not support arithmetic operations')
|
assert(ok, 'Field "'..k..'" does not support arithmetic operations')
|
||||||
out[#out+1] = {subject, k, delta}
|
out[#out+1] = {subject, k, delta}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
method = tween[method or 'linear'] -- see __index
|
method = tween[method or 'linear'] -- see __index
|
||||||
local payload, t, args = tween_collect_payload(subject, target, {}), 0, {...}
|
local payload, t, args = tween_collect_payload(subject, target, {}), 0, {...}
|
||||||
|
|
||||||
local last_s = 0
|
local last_s = 0
|
||||||
return self:do_for(len, function(dt)
|
return self:do_for(len, function(dt)
|
||||||
t = t + dt
|
t = t + dt
|
||||||
local s = method(math.min(1, t/len), unpack(args))
|
local s = method(math.min(1, t/len), unpack(args))
|
||||||
local ds = s - last_s
|
local ds = s - last_s
|
||||||
last_s = s
|
last_s = s
|
||||||
for _, info in ipairs(payload) do
|
for _, info in ipairs(payload) do
|
||||||
local ref, key, delta = unpack(info)
|
local ref, key, delta = unpack(info)
|
||||||
ref[key] = ref[key] + delta * ds
|
ref[key] = ref[key] + delta * ds
|
||||||
end
|
end
|
||||||
end, after)
|
end, after)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- fetches function and generated compositions for method `key`
|
-- fetches function and generated compositions for method `key`
|
||||||
__index = function(tweens, key)
|
__index = function(tweens, key)
|
||||||
if type(key) == 'function' then return key end
|
if type(key) == 'function' then return key end
|
||||||
|
|
||||||
assert(type(key) == 'string', 'Method must be function or string.')
|
assert(type(key) == 'string', 'Method must be function or string.')
|
||||||
if rawget(tweens, key) then return rawget(tweens, key) end
|
if rawget(tweens, key) then return rawget(tweens, key) end
|
||||||
|
|
||||||
local function construct(pattern, f)
|
local function construct(pattern, f)
|
||||||
local method = rawget(tweens, key:match(pattern))
|
local method = rawget(tweens, key:match(pattern))
|
||||||
if method then return f(method) end
|
if method then return f(method) end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local out, chain = rawget(tweens,'out'), rawget(tweens,'chain')
|
local out, chain = rawget(tweens,'out'), rawget(tweens,'chain')
|
||||||
return construct('^in%-([^-]+)$', function(...) return ... end)
|
return construct('^in%-([^-]+)$', function(...) return ... end)
|
||||||
or construct('^out%-([^-]+)$', out)
|
or construct('^out%-([^-]+)$', out)
|
||||||
or construct('^in%-out%-([^-]+)$', function(f) return chain(f, out(f)) end)
|
or construct('^in%-out%-([^-]+)$', function(f) return chain(f, out(f)) end)
|
||||||
or construct('^out%-in%-([^-]+)$', function(f) return chain(out(f), f) end)
|
or construct('^out%-in%-([^-]+)$', function(f) return chain(out(f), f) end)
|
||||||
or error('Unknown interpolation method: ' .. key)
|
or error('Unknown interpolation method: ' .. key)
|
||||||
end})
|
end})
|
||||||
|
|
||||||
-- default timer
|
-- default timer
|
||||||
|
@ -175,16 +175,16 @@ local default = new()
|
||||||
|
|
||||||
-- the module
|
-- the module
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
new = new,
|
new = new,
|
||||||
update = function(...) return default:update(...) end,
|
update = function(...) return default:update(...) end,
|
||||||
do_for = function(...) return default:do_for(...) end,
|
do_for = function(...) return default:do_for(...) end,
|
||||||
add = function(...) return default:add(...) end,
|
add = function(...) return default:add(...) end,
|
||||||
addPeriodic = function(...) return default:addPeriodic(...) end,
|
addPeriodic = function(...) return default:addPeriodic(...) end,
|
||||||
cancel = function(...) return default:cancel(...) end,
|
cancel = function(...) return default:cancel(...) end,
|
||||||
clear = function(...) return default:clear(...) end,
|
clear = function(...) return default:clear(...) end,
|
||||||
tween = setmetatable({}, {
|
tween = setmetatable({}, {
|
||||||
__index = Timer.tween,
|
__index = Timer.tween,
|
||||||
__newindex = function(_,k,v) Timer.tween[k] = v end,
|
__newindex = function(_,k,v) Timer.tween[k] = v end,
|
||||||
__call = function(t,...) return default:tween(...) end,
|
__call = function(t,...) return default:tween(...) end,
|
||||||
})
|
})
|
||||||
}, {__call = new})
|
}, {__call = new})
|
||||||
|
|
|
@ -27,135 +27,135 @@ THE SOFTWARE.
|
||||||
local sqrt, cos, sin, atan2 = math.sqrt, math.cos, math.sin, math.atan2
|
local sqrt, cos, sin, atan2 = math.sqrt, math.cos, math.sin, math.atan2
|
||||||
|
|
||||||
local function str(x,y)
|
local function str(x,y)
|
||||||
return "("..tonumber(x)..","..tonumber(y)..")"
|
return "("..tonumber(x)..","..tonumber(y)..")"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function mul(s, x,y)
|
local function mul(s, x,y)
|
||||||
return s*x, s*y
|
return s*x, s*y
|
||||||
end
|
end
|
||||||
|
|
||||||
local function div(s, x,y)
|
local function div(s, x,y)
|
||||||
return x/s, y/s
|
return x/s, y/s
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add(x1,y1, x2,y2)
|
local function add(x1,y1, x2,y2)
|
||||||
return x1+x2, y1+y2
|
return x1+x2, y1+y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function sub(x1,y1, x2,y2)
|
local function sub(x1,y1, x2,y2)
|
||||||
return x1-x2, y1-y2
|
return x1-x2, y1-y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function permul(x1,y1, x2,y2)
|
local function permul(x1,y1, x2,y2)
|
||||||
return x1*x2, y1*y2
|
return x1*x2, y1*y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dot(x1,y1, x2,y2)
|
local function dot(x1,y1, x2,y2)
|
||||||
return x1*x2 + y1*y2
|
return x1*x2 + y1*y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function det(x1,y1, x2,y2)
|
local function det(x1,y1, x2,y2)
|
||||||
return x1*y2 - y1*x2
|
return x1*y2 - y1*x2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function eq(x1,y1, x2,y2)
|
local function eq(x1,y1, x2,y2)
|
||||||
return x1 == x2 and y1 == y2
|
return x1 == x2 and y1 == y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function lt(x1,y1, x2,y2)
|
local function lt(x1,y1, x2,y2)
|
||||||
return x1 < x2 or (x1 == x2 and y1 < y2)
|
return x1 < x2 or (x1 == x2 and y1 < y2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function le(x1,y1, x2,y2)
|
local function le(x1,y1, x2,y2)
|
||||||
return x1 <= x2 and y1 <= y2
|
return x1 <= x2 and y1 <= y2
|
||||||
end
|
end
|
||||||
|
|
||||||
local function len2(x,y)
|
local function len2(x,y)
|
||||||
return x*x + y*y
|
return x*x + y*y
|
||||||
end
|
end
|
||||||
|
|
||||||
local function len(x,y)
|
local function len(x,y)
|
||||||
return sqrt(x*x + y*y)
|
return sqrt(x*x + y*y)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dist2(x1,y1, x2,y2)
|
local function dist2(x1,y1, x2,y2)
|
||||||
return len2(x1-x2, y1-y2)
|
return len2(x1-x2, y1-y2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dist(x1,y1, x2,y2)
|
local function dist(x1,y1, x2,y2)
|
||||||
return len(x1-x2, y1-y2)
|
return len(x1-x2, y1-y2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function normalize(x,y)
|
local function normalize(x,y)
|
||||||
local l = len(x,y)
|
local l = len(x,y)
|
||||||
if l > 0 then
|
if l > 0 then
|
||||||
return x/l, y/l
|
return x/l, y/l
|
||||||
end
|
end
|
||||||
return x,y
|
return x,y
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rotate(phi, x,y)
|
local function rotate(phi, x,y)
|
||||||
local c, s = cos(phi), sin(phi)
|
local c, s = cos(phi), sin(phi)
|
||||||
return c*x - s*y, s*x + c*y
|
return c*x - s*y, s*x + c*y
|
||||||
end
|
end
|
||||||
|
|
||||||
local function perpendicular(x,y)
|
local function perpendicular(x,y)
|
||||||
return -y, x
|
return -y, x
|
||||||
end
|
end
|
||||||
|
|
||||||
local function project(x,y, u,v)
|
local function project(x,y, u,v)
|
||||||
local s = (x*u + y*v) / (u*u + v*v)
|
local s = (x*u + y*v) / (u*u + v*v)
|
||||||
return s*u, s*v
|
return s*u, s*v
|
||||||
end
|
end
|
||||||
|
|
||||||
local function mirror(x,y, u,v)
|
local function mirror(x,y, u,v)
|
||||||
local s = 2 * (x*u + y*v) / (u*u + v*v)
|
local s = 2 * (x*u + y*v) / (u*u + v*v)
|
||||||
return s*u - x, s*v - y
|
return s*u - x, s*v - y
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ref.: http://blog.signalsondisplay.com/?p=336
|
-- ref.: http://blog.signalsondisplay.com/?p=336
|
||||||
local function trim(maxLen, x, y)
|
local function trim(maxLen, x, y)
|
||||||
local s = maxLen * maxLen / len2(x, y)
|
local s = maxLen * maxLen / len2(x, y)
|
||||||
s = s > 1 and 1 or math.sqrt(s)
|
s = s > 1 and 1 or math.sqrt(s)
|
||||||
return x * s, y * s
|
return x * s, y * s
|
||||||
end
|
end
|
||||||
|
|
||||||
local function angleTo(x,y, u,v)
|
local function angleTo(x,y, u,v)
|
||||||
if u and v then
|
if u and v then
|
||||||
return atan2(y, x) - atan2(v, u)
|
return atan2(y, x) - atan2(v, u)
|
||||||
end
|
end
|
||||||
return atan2(y, x)
|
return atan2(y, x)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- the module
|
-- the module
|
||||||
return {
|
return {
|
||||||
str = str,
|
str = str,
|
||||||
|
|
||||||
-- arithmetic
|
-- arithmetic
|
||||||
mul = mul,
|
mul = mul,
|
||||||
div = div,
|
div = div,
|
||||||
add = add,
|
add = add,
|
||||||
sub = sub,
|
sub = sub,
|
||||||
permul = permul,
|
permul = permul,
|
||||||
dot = dot,
|
dot = dot,
|
||||||
det = det,
|
det = det,
|
||||||
cross = det,
|
cross = det,
|
||||||
|
|
||||||
-- relation
|
-- relation
|
||||||
eq = eq,
|
eq = eq,
|
||||||
lt = lt,
|
lt = lt,
|
||||||
le = le,
|
le = le,
|
||||||
|
|
||||||
-- misc operations
|
-- misc operations
|
||||||
len2 = len2,
|
len2 = len2,
|
||||||
len = len,
|
len = len,
|
||||||
dist2 = dist2,
|
dist2 = dist2,
|
||||||
dist = dist,
|
dist = dist,
|
||||||
normalize = normalize,
|
normalize = normalize,
|
||||||
rotate = rotate,
|
rotate = rotate,
|
||||||
perpendicular = perpendicular,
|
perpendicular = perpendicular,
|
||||||
project = project,
|
project = project,
|
||||||
mirror = mirror,
|
mirror = mirror,
|
||||||
trim = trim,
|
trim = trim,
|
||||||
angleTo = angleTo,
|
angleTo = angleTo,
|
||||||
}
|
}
|
||||||
|
|
132
hump/vector.lua
132
hump/vector.lua
|
@ -31,158 +31,158 @@ local vector = {}
|
||||||
vector.__index = vector
|
vector.__index = vector
|
||||||
|
|
||||||
local function new(x,y)
|
local function new(x,y)
|
||||||
return setmetatable({x = x or 0, y = y or 0}, vector)
|
return setmetatable({x = x or 0, y = y or 0}, vector)
|
||||||
end
|
end
|
||||||
local zero = new(0,0)
|
local zero = new(0,0)
|
||||||
|
|
||||||
local function isvector(v)
|
local function isvector(v)
|
||||||
return type(v) == 'table' and type(v.x) == 'number' and type(v.y) == 'number'
|
return type(v) == 'table' and type(v.x) == 'number' and type(v.y) == 'number'
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:clone()
|
function vector:clone()
|
||||||
return new(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 new(-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 new(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 new(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 new(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 new(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 new(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 new(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.x * self.x + self.y * self.y
|
return self.x * self.x + self.y * self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:len()
|
function vector:len()
|
||||||
return sqrt(self.x * self.x + self.y * self.y)
|
return sqrt(self.x * self.x + self.y * self.y)
|
||||||
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)")
|
||||||
local dx = a.x - b.x
|
local dx = a.x - b.x
|
||||||
local dy = a.y - b.y
|
local dy = a.y - b.y
|
||||||
return sqrt(dx * dx + dy * dy)
|
return sqrt(dx * dx + dy * dy)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector.dist2(a, b)
|
function vector.dist2(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)")
|
||||||
local dx = a.x - b.x
|
local dx = a.x - b.x
|
||||||
local dy = a.y - b.y
|
local dy = a.y - b.y
|
||||||
return (dx * dx + dy * dy)
|
return (dx * dx + dy * dy)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:normalize_inplace()
|
function vector:normalize_inplace()
|
||||||
local l = self:len()
|
local l = self:len()
|
||||||
if l > 0 then
|
if l > 0 then
|
||||||
self.x, self.y = self.x / l, self.y / l
|
self.x, self.y = self.x / l, self.y / l
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:normalized()
|
function vector:normalized()
|
||||||
return self:clone():normalize_inplace()
|
return self:clone():normalize_inplace()
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:rotate_inplace(phi)
|
function vector:rotate_inplace(phi)
|
||||||
local c, s = cos(phi), 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)
|
||||||
local c, s = cos(phi), sin(phi)
|
local c, s = cos(phi), sin(phi)
|
||||||
return new(c * self.x - s * self.y, s * self.x + c * self.y)
|
return new(c * self.x - s * self.y, s * self.x + c * self.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:perpendicular()
|
function vector:perpendicular()
|
||||||
return new(-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 vector on " .. type(v))
|
assert(isvector(v), "invalid argument: cannot project vector on " .. type(v))
|
||||||
-- (self * v) * v / v:len2()
|
-- (self * v) * v / v:len2()
|
||||||
local s = (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y)
|
local s = (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y)
|
||||||
return new(s * v.x, s * v.y)
|
return new(s * v.x, s * v.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:mirrorOn(v)
|
function vector:mirrorOn(v)
|
||||||
assert(isvector(v), "invalid argument: cannot mirror vector on " .. type(v))
|
assert(isvector(v), "invalid argument: cannot mirror vector on " .. type(v))
|
||||||
-- 2 * self:projectOn(v) - self
|
-- 2 * self:projectOn(v) - self
|
||||||
local s = 2 * (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y)
|
local s = 2 * (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y)
|
||||||
return new(s * v.x - self.x, s * v.y - self.y)
|
return new(s * v.x - self.x, s * v.y - self.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:cross(v)
|
function vector:cross(v)
|
||||||
assert(isvector(v), "cross: wrong argument types (<vector> expected)")
|
assert(isvector(v), "cross: wrong argument types (<vector> expected)")
|
||||||
return self.x * v.y - self.y * v.x
|
return self.x * v.y - self.y * v.x
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ref.: http://blog.signalsondisplay.com/?p=336
|
-- ref.: http://blog.signalsondisplay.com/?p=336
|
||||||
function vector:trim_inplace(maxLen)
|
function vector:trim_inplace(maxLen)
|
||||||
local s = maxLen * maxLen / self:len2()
|
local s = maxLen * maxLen / self:len2()
|
||||||
s = (s > 1 and 1) or math.sqrt(s)
|
s = (s > 1 and 1) or math.sqrt(s)
|
||||||
self.x, self.y = self.x * s, self.y * s
|
self.x, self.y = self.x * s, self.y * s
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:angleTo(other)
|
function vector:angleTo(other)
|
||||||
if other then
|
if other then
|
||||||
return atan2(self.y, self.x) - atan2(other.y, other.x)
|
return atan2(self.y, self.x) - atan2(other.y, other.x)
|
||||||
end
|
end
|
||||||
return atan2(self.y, self.x)
|
return atan2(self.y, self.x)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vector:trimmed(maxLen)
|
function vector:trimmed(maxLen)
|
||||||
return self:clone():trim_inplace(maxLen)
|
return self:clone():trim_inplace(maxLen)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue