added a timer for cleaner execution, goodbye resolver!

This commit is contained in:
2021-05-08 18:13:33 +02:00
parent b103140ea1
commit 55f0d2f0da
3 changed files with 268 additions and 15 deletions

View File

@@ -1,7 +1,9 @@
-- Chuchu by Makaron -- Chuchu by Makaron
-- Crates are the main thing so here we go -- Crates are the main thing so here we go
local Timer = require('deps.knife.timer')
local CONST_ITERATIONS_RESOLVE = 1 local CONST_ITERATIONS_RESOLVE = .01
local CONST_TIME_TO_RELOAD = .4
local Crates = { local Crates = {
world = nil, world = nil,
@@ -22,15 +24,16 @@ function Crate.new(world, x, y)
object.attached = false object.attached = false
object.contact = { } object.contact = { }
object.joint = nil object.joint = nil
object.resolver = nil
object.collider:setPresolve(function (shape1, shape2, contact) object.collider:setPresolve(function (shape1, shape2, contact)
print(shape2:getClass())
if shape2:getClass() == 'Player' and object.attached == false then if shape2:getClass() == 'Player' and object.attached == false then
contact:setEnabled(false) contact:setEnabled(false)
object.contact.x, object.contact.y = contact:getPositions() object.contact.x, object.contact.y = contact:getPositions()
object.resolver = CONST_ITERATIONS_RESOLVE
object.attached = true object.attached = true
Timer.after(CONST_ITERATIONS_RESOLVE, function ()
object.joint = Crates.world:addJoint('revolute', Crates.player.collider, object.collider, object.contact.x, object.contact.y, true)
table.insert(Crates.attached, object)
end)
end end
end) end)
@@ -49,23 +52,21 @@ function Crates:spawn(x, y)
end end
function Crates:update(dt) function Crates:update(dt)
for key in pairs(self.list) do Timer.update(dt)
if self.list[key].resolver ~= nil then
self.list[key].resolver = self.list[key].resolver - 1
if self.list[key].resolver <= 0 then
curContact = self.list[key].contact
self.world:addJoint('revolute', self.player.collider, self.list[key].collider, curContact.x, curContact.y, true)
self.list[key].resolver = nil
table.insert(self.attached, self.list[key])
end
end
end
end end
function Crates:getAttached() function Crates:getAttached()
return self.attached return self.attached
end end
function Crates:detach(key)
self.attached[key].joint._joint:destroy()
Timer.after(CONST_TIME_TO_RELOAD, function ()
self.attached[key].attached = false
table.remove(self.attached, key)
end)
end
return setmetatable(Crates, { return setmetatable(Crates, {
__call = function(_, ...) return new(...) end __call = function(_, ...) return new(...) end
}) })

244
deps/knife/timer.lua vendored Normal file
View File

@@ -0,0 +1,244 @@
local Timer = {}
-- group management
local function detach (group, item)
local index = item.index
group[index] = group[#group]
group[index].index = index
group[#group] = nil
item.groupField = nil
end
local function attach (group, item)
if item.groupField then
detach (item.groupField, item)
end
local index = #group + 1
item.index = index
group[index] = item
item.groupField = group
item.lastGroup = group
end
-- instance update methods
local function updateContinuous (self, dt)
local cutoff = self.cutoff
local elapsed = self.elapsed + dt
if self:callback(dt) == false or elapsed >= cutoff then
if self.finishField then
self:finishField(elapsed - cutoff)
end
self:remove()
end
self.elapsed = elapsed
return
end
local function updateIntermittent (self, dt)
local duration = self.delay or self.interval
local elapsed = self.elapsed + dt
while elapsed >= duration do
elapsed = elapsed - duration
if self.limitField then
self.limitField = self.limitField - 1
end
if self:callback(elapsed) == false
or self.delay or self.limitField == 0 then
if self.finishField then
self:finishField(elapsed)
end
self:remove()
return
end
end
self.elapsed = elapsed
end
local function updateTween (self, dt)
local elapsed = self.elapsed + dt
local plan = self.plan
local duration = self.duration
self.elapsed = elapsed
if elapsed >= duration then
for index = 1, #plan do
local task = plan[index]
task.target[task.key] = task.final
end
if self.finishField then
self:finishField(elapsed - duration)
end
self:remove()
return
end
local ease = self.easeField
for index = 1, #plan do
local task = plan[index]
local target, key = task.target, task.key
local initial, change = task.initial, task.change
target[key] = ease(elapsed, initial, change, duration)
end
end
-- shared instance methods
local defaultGroup = {}
local function group (self, group)
if not group then
group = defaultGroup
end
attach(group, self)
return self
end
local function remove (self)
if self.groupField then
detach(self.groupField, self)
end
return self
end
local function register (self)
attach(self.lastGroup, self)
return self
end
local function limit (self, limitField)
self.limitField = limitField
return self
end
local function finish (self, finishField)
self.finishField = finishField
return self
end
local function ease (self, easeField)
self.easeField = easeField
return self
end
-- tweening helper functions
local function planTween (definition)
local plan = {}
for target, values in pairs(definition) do
for key, final in pairs(values) do
local initial = target[key]
plan[#plan + 1] = {
target = target,
key = key,
initial = initial,
final = final,
change = final - initial,
}
end
end
return plan
end
local function easeLinear (elapsed, initial, change, duration)
return change * elapsed / duration + initial
end
-- instance initializer
local function initialize (timer)
timer.elapsed = 0
timer.group = group
timer.remove = remove
timer.register = register
attach(defaultGroup, timer)
return timer
end
-- static api
function Timer.after (delay, callback)
return initialize {
delay = delay,
callback = callback,
update = updateIntermittent,
}
end
function Timer.every (interval, callback)
return initialize {
interval = interval,
callback = callback,
update = updateIntermittent,
limit = limit,
finish = finish,
}
end
function Timer.prior (cutoff, callback)
return initialize {
cutoff = cutoff,
callback = callback,
update = updateContinuous,
finish = finish,
}
end
function Timer.tween (duration, definition)
return initialize {
duration = duration,
plan = planTween(definition),
update = updateTween,
easeField = easeLinear,
ease = ease,
finish = finish,
}
end
function Timer.update (dt, group)
if not group then
group = defaultGroup
end
for index = #group, 1, -1 do
group[index]:update(dt)
end
end
function Timer.clear (group)
if not group then
group = defaultGroup
end
for i = 1, #group do
group[i] = nil
end
end
Timer.defaultGroup = defaultGroup
return Timer

View File

@@ -59,6 +59,7 @@ function love.load()
input:bind(love.keyboard.getKeyFromScancode('d'), 'moveRight') input:bind(love.keyboard.getKeyFromScancode('d'), 'moveRight')
input:bind(love.keyboard.getKeyFromScancode('s'), 'moveDown') input:bind(love.keyboard.getKeyFromScancode('s'), 'moveDown')
input:bind(love.keyboard.getKeyFromScancode('space'), 'switch') input:bind(love.keyboard.getKeyFromScancode('space'), 'switch')
input:bind(love.keyboard.getKeyFromScancode('lshift'), 'detach')
crates:init(world, magnet) crates:init(world, magnet)
crates:spawn(120, 400) crates:spawn(120, 400)
@@ -91,6 +92,13 @@ function love.update(dt)
else else
magnet.side = 'LEFT' magnet.side = 'LEFT'
end end
elseif input:pressed('detach') then
velocity = {0, 0}
local attached = crates:getAttached()
for key in pairs(attached) do
crates:detach(key)
end
else else
if input:down('moveUp') or input:down('moveLeft') or input:down('moveRight') or input:down('moveDown') then if input:down('moveUp') or input:down('moveLeft') or input:down('moveRight') or input:down('moveDown') then
if input:down('moveUp') then velocity[2] = -player.maxSpeed.y if input:down('moveUp') then velocity[2] = -player.maxSpeed.y