mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-27 09:09:30 +00:00
uqt.timer: now account for update lag, use only dt for calculations
This commit is contained in:
parent
6dc939bd16
commit
f22e0bef26
5 changed files with 57 additions and 69 deletions
|
|
@ -99,7 +99,7 @@ let signal = {
|
||||||
-- For example, every ubiquitousse module with a "update" function will bind it to the "update" signal in the registry;
|
-- For example, every ubiquitousse module with a "update" function will bind it to the "update" signal in the registry;
|
||||||
-- you can then call this signal on each game update to update every ubiquitousse module easily.
|
-- you can then call this signal on each game update to update every ubiquitousse module easily.
|
||||||
-- Provided signals:
|
-- Provided signals:
|
||||||
-- * update, should be called on every game update
|
-- * update(dt), should be called on every game update
|
||||||
-- * draw, should be called on every game draw
|
-- * draw, should be called on every game draw
|
||||||
-- * for LÖVE, there are callbacks for every LÖVE callback function that need to be called on their corresponding LÖVE callback
|
-- * for LÖVE, there are callbacks for every LÖVE callback function that need to be called on their corresponding LÖVE callback
|
||||||
-- @impl mixed
|
-- @impl mixed
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
local timer = require((...):match("^(.-%.)backend").."timer")
|
|
||||||
local ctr = require("ctr")
|
|
||||||
|
|
||||||
timer.get = ctr.time
|
|
||||||
|
|
||||||
return timer
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
local timer = require((...):match("^(.-%.)backend").."timer")
|
|
||||||
|
|
||||||
timer.get = function()
|
|
||||||
return love.timer.getTime() * 1000
|
|
||||||
end
|
|
||||||
|
|
||||||
return timer
|
|
||||||
|
|
@ -1,14 +1 @@
|
||||||
local time
|
return require((...)..".timer")
|
||||||
|
|
||||||
local p = ...
|
|
||||||
if love then
|
|
||||||
time = require(p..".backend.love")
|
|
||||||
elseif package.loaded["ctr"] then
|
|
||||||
time = require(p..".backend.ctrulua")
|
|
||||||
elseif package.loaded["libretro"] then
|
|
||||||
error("NYI")
|
|
||||||
else
|
|
||||||
error("no backend for ubiquitousse.timer")
|
|
||||||
end
|
|
||||||
|
|
||||||
return time
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
--- ubiquitousse.timer
|
--- ubiquitousse.timer
|
||||||
-- Depends on a backend.
|
|
||||||
-- Optional dependencies: ubiquitousse.signal (to bind to update signal in signal.event)
|
-- Optional dependencies: ubiquitousse.signal (to bind to update signal in signal.event)
|
||||||
local loaded, signal = pcall(require, (...):match("^(.-)timer").."signal")
|
local loaded, signal = pcall(require, (...):match("^(.-)timer").."signal")
|
||||||
if not loaded then signal = nil end
|
if not loaded then signal = nil end
|
||||||
|
|
@ -29,15 +28,9 @@ end
|
||||||
local registry_mt = {
|
local registry_mt = {
|
||||||
--- Update all the TimedFunctions calls.
|
--- Update all the TimedFunctions calls.
|
||||||
-- Should be called at every game update; called by ubiquitousse.update.
|
-- Should be called at every game update; called by ubiquitousse.update.
|
||||||
-- @tparam[opt=calculate here] number dt the delta-time (time spent since last time the function was called) (miliseconds)
|
-- @tparam number dt the delta-time (time spent since last time the function was called) (miliseconds)
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
update = function(self, dt)
|
update = function(self, dt)
|
||||||
local currentTime = timer.get()
|
|
||||||
|
|
||||||
if not dt then
|
|
||||||
dt = currentTime - self.lastTime
|
|
||||||
self.lastTime = currentTime
|
|
||||||
end
|
|
||||||
self.dt = dt
|
self.dt = dt
|
||||||
|
|
||||||
local done = {} -- functions done running
|
local done = {} -- functions done running
|
||||||
|
|
@ -47,36 +40,50 @@ local registry_mt = {
|
||||||
if t and all(t.initWhen, true) then
|
if t and all(t.initWhen, true) then
|
||||||
t.initWhen = {}
|
t.initWhen = {}
|
||||||
local co = t.coroutine
|
local co = t.coroutine
|
||||||
t.after = t.after - dt
|
-- skip
|
||||||
if t.forceStart or (t.after <= 0 and all(t.startWhen, true)) then
|
dt = self.dt
|
||||||
|
if t.skip then dt = dt + t.skip end
|
||||||
|
-- start
|
||||||
|
if t.after then t.after = t.after - dt end
|
||||||
|
if t.forceStart or ((not t.after or t.after <= 0) and all(t.startWhen, true)) then
|
||||||
|
local startLag = 0
|
||||||
|
if t.after then
|
||||||
|
startLag = -t.after
|
||||||
|
elseif t.skip then
|
||||||
|
startLag = t.skip
|
||||||
|
end
|
||||||
|
t.after, t.skip = nil, nil
|
||||||
t.startWhen = {}
|
t.startWhen = {}
|
||||||
d[func] = false -- niling here cause the next pair iteration to error
|
d[func] = false -- niling here cause the next pair iteration to error
|
||||||
table.insert(done, func)
|
table.insert(done, func)
|
||||||
if not co then
|
if not co then
|
||||||
co = coroutine.create(func)
|
co = coroutine.create(func)
|
||||||
t.coroutine = co
|
t.coroutine = co
|
||||||
t.started = currentTime
|
|
||||||
if t.times > 0 then t.times = t.times - 1 end
|
if t.times > 0 then t.times = t.times - 1 end
|
||||||
for _, f in ipairs(t.onStart) do f(t.object) end
|
for _, f in ipairs(t.onStart) do f(t.object, startLag) end
|
||||||
end
|
end
|
||||||
|
-- update
|
||||||
assert(coroutine.resume(co, function(delay)
|
assert(coroutine.resume(co, function(delay)
|
||||||
t.after = delay or 0
|
t.after = delay - startLag
|
||||||
d[func] = t
|
d[func] = t
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end, dt))
|
end, dt))
|
||||||
for _, f in ipairs(t.onUpdate) do f(t.object) end
|
for _, f in ipairs(t.onUpdate) do f(t.object, startLag) end
|
||||||
|
if t.during then t.during = t.during - startLag - dt end
|
||||||
|
-- stopping / repeat
|
||||||
if all(t.stopWhen, false) then t.forceStop = true end
|
if all(t.stopWhen, false) then t.forceStop = true end
|
||||||
if t.forceStop or coroutine.status(co) == "dead" then
|
if t.forceStop or coroutine.status(co) == "dead" then
|
||||||
if t.forceStop
|
if t.forceStop
|
||||||
or (t.during >= 0 and t.started + t.during < currentTime)
|
or (t.during and t.during <= 0)
|
||||||
or (t.times == 0)
|
or (t.times == 0)
|
||||||
or (not all(t.repeatWhile, true))
|
or (not all(t.repeatWhile, true))
|
||||||
or (t.every == -1 and t.times == -1 and t.during == -1 and #t.repeatWhile == 0) -- no repeat
|
or (t.every == nil and t.times == -1 and t.during == nil and #t.repeatWhile == 0) -- no repeat
|
||||||
then
|
then
|
||||||
for _, f in ipairs(t.onEnd) do f(t.object) end
|
local endLag = t.during and -t.during or 0
|
||||||
|
for _, f in ipairs(t.onEnd) do f(t.object, endLag) end
|
||||||
else
|
else
|
||||||
if t.times > 0 then t.times = t.times - 1 end
|
if t.times > 0 then t.times = t.times - 1 end
|
||||||
t.after = t.every
|
if t.every then t.after = t.every - startLag end
|
||||||
t.coroutine = coroutine.create(func)
|
t.coroutine = coroutine.create(func)
|
||||||
d[func] = t
|
d[func] = t
|
||||||
end
|
end
|
||||||
|
|
@ -95,6 +102,7 @@ local registry_mt = {
|
||||||
--- Schedule a function to run.
|
--- Schedule a function to run.
|
||||||
-- The function will receive as first parameter the wait(time) function, which will pause the function execution for time miliseconds.
|
-- The function will receive as first parameter the wait(time) function, which will pause the function execution for time miliseconds.
|
||||||
-- As a second parameter, the function will receive the delta time (dt).
|
-- As a second parameter, the function will receive the delta time (dt).
|
||||||
|
-- As a third parameter, the function will receive the lag time (difference between the time when the function was run and when it should have been run).
|
||||||
-- @tparam[opt] function func the function to schedule
|
-- @tparam[opt] function func the function to schedule
|
||||||
-- @treturn TimedFunction the object
|
-- @treturn TimedFunction the object
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
|
|
@ -107,12 +115,11 @@ local registry_mt = {
|
||||||
self.delayed[func] = {
|
self.delayed[func] = {
|
||||||
object = nil,
|
object = nil,
|
||||||
coroutine = nil,
|
coroutine = nil,
|
||||||
started = 0,
|
|
||||||
|
|
||||||
after = -1,
|
after = nil,
|
||||||
every = -1,
|
every = nil,
|
||||||
times = -1,
|
times = -1,
|
||||||
during = -1,
|
during = nil,
|
||||||
|
|
||||||
initWhen = {},
|
initWhen = {},
|
||||||
startWhen = {},
|
startWhen = {},
|
||||||
|
|
@ -121,6 +128,7 @@ local registry_mt = {
|
||||||
|
|
||||||
forceStart = false,
|
forceStart = false,
|
||||||
forceStop = false,
|
forceStop = false,
|
||||||
|
skip = nil,
|
||||||
|
|
||||||
onStart = {},
|
onStart = {},
|
||||||
onUpdate = {},
|
onUpdate = {},
|
||||||
|
|
@ -132,21 +140,25 @@ local registry_mt = {
|
||||||
r = {
|
r = {
|
||||||
--- Timed conditions ---
|
--- Timed conditions ---
|
||||||
--- Wait time milliseconds before running the function.
|
--- Wait time milliseconds before running the function.
|
||||||
|
-- Specify no time to remove condition.
|
||||||
after = function(_, time)
|
after = function(_, time)
|
||||||
t.after = time
|
t.after = time
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
--- Run the function every time millisecond.
|
--- Run the function every time millisecond.
|
||||||
|
-- Specify no time to remove condition.
|
||||||
every = function(_, time)
|
every = function(_, time)
|
||||||
t.every = time
|
t.every = time
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
--- The function will not execute more than count times.
|
--- The function will not execute more than count times.
|
||||||
|
-- Specify no time to remove condition.
|
||||||
times = function(_, count)
|
times = function(_, count)
|
||||||
t.times = count
|
t.times = count or -1
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
--- The TimedFunction will be active for a time duration.
|
--- The TimedFunction will be active for a time duration.
|
||||||
|
-- Specify no time to remove condition.
|
||||||
during = function(_, time)
|
during = function(_, time)
|
||||||
t.during = time
|
t.during = time
|
||||||
return r
|
return r
|
||||||
|
|
@ -191,32 +203,40 @@ local registry_mt = {
|
||||||
t.forceStop = true
|
t.forceStop = true
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
|
--- Skip some amount of time.
|
||||||
|
skip = function(_, time)
|
||||||
|
t.skip = (t.skip or 0) + time
|
||||||
|
end,
|
||||||
|
|
||||||
--- Callbacks functions ---
|
--- Callbacks functions ---
|
||||||
--- Will execute func(self) when the function execution start.
|
--- Will execute func(self, lag) when the function execution start.
|
||||||
onStart = function(_, func)
|
onStart = function(_, func)
|
||||||
table.insert(t.onStart, func)
|
table.insert(t.onStart, func)
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
--- Will execute func(self) each frame the main function is run.
|
--- Will execute func(self, lag) each frame the main function is run.
|
||||||
onUpdate = function(_, func)
|
onUpdate = function(_, func)
|
||||||
table.insert(t.onUpdate, func)
|
table.insert(t.onUpdate, func)
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
--- Will execute func(self) when the function execution end.
|
--- Will execute func(self, lag) when the function execution end.
|
||||||
onEnd = function(_, func)
|
onEnd = function(_, func)
|
||||||
table.insert(t.onEnd, func)
|
table.insert(t.onEnd, func)
|
||||||
return r
|
return r
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Chaining ---
|
--- Chaining ---
|
||||||
--- Creates another TimedFunction which will be initialized when the current one ends.
|
--- Creates another TimedFunction which will be initialized immediately when the current one ends.
|
||||||
-- Returns the new TimedFunction.
|
-- Returns the new TimedFunction.
|
||||||
chain = function(_, func)
|
chain = function(_, func)
|
||||||
local done = false
|
local done = false
|
||||||
r:onEnd(function() done = true end)
|
local fn = self:run(func)
|
||||||
return self:run(func)
|
|
||||||
:initWhen(function() return done end)
|
:initWhen(function() return done end)
|
||||||
|
r:onEnd(function(self, lag)
|
||||||
|
done = true
|
||||||
|
fn:skip(lag)
|
||||||
|
end)
|
||||||
|
return fn
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
t.object = r
|
t.object = r
|
||||||
|
|
@ -284,9 +304,13 @@ local registry_mt = {
|
||||||
end
|
end
|
||||||
|
|
||||||
local done = false
|
local done = false
|
||||||
r:onEnd(function() done = true end)
|
local fn = self:tween(duration_, tbl_, to_, method_)
|
||||||
return self:tween(duration_, tbl_, to_, method_)
|
|
||||||
:initWhen(function() return done end)
|
:initWhen(function() return done end)
|
||||||
|
r:onEnd(function(self, lag)
|
||||||
|
done = true
|
||||||
|
fn:skip(lag)
|
||||||
|
end)
|
||||||
|
return fn
|
||||||
end
|
end
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
@ -314,20 +338,11 @@ timer = {
|
||||||
-- This table is for internal use and shouldn't be used from an external script.
|
-- This table is for internal use and shouldn't be used from an external script.
|
||||||
delayed = {},
|
delayed = {},
|
||||||
|
|
||||||
-- Used to calculate the deltatime
|
|
||||||
lastTime = timer.get(),
|
|
||||||
|
|
||||||
--- Time since last timer update (miliseconds).
|
--- Time since last timer update (miliseconds).
|
||||||
dt = 0
|
dt = 0
|
||||||
}, registry_mt)
|
}, registry_mt)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Returns the number of miliseconds elapsed since some point in time.
|
|
||||||
-- This point is fixed but undetermined, so this function should only be used to calculate durations.
|
|
||||||
-- Should at least have millisecond-precision, but can be more precise if available.
|
|
||||||
-- @impl backend
|
|
||||||
get = function() end,
|
|
||||||
|
|
||||||
--- Time since last update (miliseconds).
|
--- Time since last update (miliseconds).
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
dt = 0,
|
dt = 0,
|
||||||
|
|
@ -335,7 +350,6 @@ timer = {
|
||||||
--- Global TimerRegistry.
|
--- Global TimerRegistry.
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
delayed = {},
|
delayed = {},
|
||||||
lastTime = 0,
|
|
||||||
update = function(...) -- If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
update = function(...) -- If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
||||||
return registry_mt.update(timer, ...)
|
return registry_mt.update(timer, ...)
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue