mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-27 17:19:31 +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;
|
||||
-- you can then call this signal on each game update to update every ubiquitousse module easily.
|
||||
-- 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
|
||||
-- * 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
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
|
||||
return require((...)..".timer")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
--- ubiquitousse.timer
|
||||
-- Depends on a backend.
|
||||
-- Optional dependencies: ubiquitousse.signal (to bind to update signal in signal.event)
|
||||
local loaded, signal = pcall(require, (...):match("^(.-)timer").."signal")
|
||||
if not loaded then signal = nil end
|
||||
|
|
@ -29,15 +28,9 @@ end
|
|||
local registry_mt = {
|
||||
--- Update all the TimedFunctions calls.
|
||||
-- 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
|
||||
update = function(self, dt)
|
||||
local currentTime = timer.get()
|
||||
|
||||
if not dt then
|
||||
dt = currentTime - self.lastTime
|
||||
self.lastTime = currentTime
|
||||
end
|
||||
self.dt = dt
|
||||
|
||||
local done = {} -- functions done running
|
||||
|
|
@ -47,36 +40,50 @@ local registry_mt = {
|
|||
if t and all(t.initWhen, true) then
|
||||
t.initWhen = {}
|
||||
local co = t.coroutine
|
||||
t.after = t.after - dt
|
||||
if t.forceStart or (t.after <= 0 and all(t.startWhen, true)) then
|
||||
-- skip
|
||||
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 = {}
|
||||
d[func] = false -- niling here cause the next pair iteration to error
|
||||
table.insert(done, func)
|
||||
if not co then
|
||||
co = coroutine.create(func)
|
||||
t.coroutine = co
|
||||
t.started = currentTime
|
||||
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
|
||||
-- update
|
||||
assert(coroutine.resume(co, function(delay)
|
||||
t.after = delay or 0
|
||||
t.after = delay - startLag
|
||||
d[func] = t
|
||||
coroutine.yield()
|
||||
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 t.forceStop or coroutine.status(co) == "dead" then
|
||||
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 (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
|
||||
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
|
||||
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)
|
||||
d[func] = t
|
||||
end
|
||||
|
|
@ -95,6 +102,7 @@ local registry_mt = {
|
|||
--- 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.
|
||||
-- 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
|
||||
-- @treturn TimedFunction the object
|
||||
-- @impl ubiquitousse
|
||||
|
|
@ -107,12 +115,11 @@ local registry_mt = {
|
|||
self.delayed[func] = {
|
||||
object = nil,
|
||||
coroutine = nil,
|
||||
started = 0,
|
||||
|
||||
after = -1,
|
||||
every = -1,
|
||||
after = nil,
|
||||
every = nil,
|
||||
times = -1,
|
||||
during = -1,
|
||||
during = nil,
|
||||
|
||||
initWhen = {},
|
||||
startWhen = {},
|
||||
|
|
@ -121,6 +128,7 @@ local registry_mt = {
|
|||
|
||||
forceStart = false,
|
||||
forceStop = false,
|
||||
skip = nil,
|
||||
|
||||
onStart = {},
|
||||
onUpdate = {},
|
||||
|
|
@ -132,21 +140,25 @@ local registry_mt = {
|
|||
r = {
|
||||
--- Timed conditions ---
|
||||
--- Wait time milliseconds before running the function.
|
||||
-- Specify no time to remove condition.
|
||||
after = function(_, time)
|
||||
t.after = time
|
||||
return r
|
||||
end,
|
||||
--- Run the function every time millisecond.
|
||||
-- Specify no time to remove condition.
|
||||
every = function(_, time)
|
||||
t.every = time
|
||||
return r
|
||||
end,
|
||||
--- The function will not execute more than count times.
|
||||
-- Specify no time to remove condition.
|
||||
times = function(_, count)
|
||||
t.times = count
|
||||
t.times = count or -1
|
||||
return r
|
||||
end,
|
||||
--- The TimedFunction will be active for a time duration.
|
||||
-- Specify no time to remove condition.
|
||||
during = function(_, time)
|
||||
t.during = time
|
||||
return r
|
||||
|
|
@ -191,32 +203,40 @@ local registry_mt = {
|
|||
t.forceStop = true
|
||||
return r
|
||||
end,
|
||||
--- Skip some amount of time.
|
||||
skip = function(_, time)
|
||||
t.skip = (t.skip or 0) + time
|
||||
end,
|
||||
|
||||
--- Callbacks functions ---
|
||||
--- Will execute func(self) when the function execution start.
|
||||
--- Will execute func(self, lag) when the function execution start.
|
||||
onStart = function(_, func)
|
||||
table.insert(t.onStart, func)
|
||||
return r
|
||||
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)
|
||||
table.insert(t.onUpdate, func)
|
||||
return r
|
||||
end,
|
||||
--- Will execute func(self) when the function execution end.
|
||||
--- Will execute func(self, lag) when the function execution end.
|
||||
onEnd = function(_, func)
|
||||
table.insert(t.onEnd, func)
|
||||
return r
|
||||
end,
|
||||
|
||||
--- 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.
|
||||
chain = function(_, func)
|
||||
local done = false
|
||||
r:onEnd(function() done = true end)
|
||||
return self:run(func)
|
||||
local fn = self:run(func)
|
||||
:initWhen(function() return done end)
|
||||
r:onEnd(function(self, lag)
|
||||
done = true
|
||||
fn:skip(lag)
|
||||
end)
|
||||
return fn
|
||||
end
|
||||
}
|
||||
t.object = r
|
||||
|
|
@ -284,9 +304,13 @@ local registry_mt = {
|
|||
end
|
||||
|
||||
local done = false
|
||||
r:onEnd(function() done = true end)
|
||||
return self:tween(duration_, tbl_, to_, method_)
|
||||
local fn = self:tween(duration_, tbl_, to_, method_)
|
||||
:initWhen(function() return done end)
|
||||
r:onEnd(function(self, lag)
|
||||
done = true
|
||||
fn:skip(lag)
|
||||
end)
|
||||
return fn
|
||||
end
|
||||
|
||||
return r
|
||||
|
|
@ -314,20 +338,11 @@ timer = {
|
|||
-- This table is for internal use and shouldn't be used from an external script.
|
||||
delayed = {},
|
||||
|
||||
-- Used to calculate the deltatime
|
||||
lastTime = timer.get(),
|
||||
|
||||
--- Time since last timer update (miliseconds).
|
||||
dt = 0
|
||||
}, registry_mt)
|
||||
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).
|
||||
-- @impl ubiquitousse
|
||||
dt = 0,
|
||||
|
|
@ -335,7 +350,6 @@ timer = {
|
|||
--- Global TimerRegistry.
|
||||
-- @impl ubiquitousse
|
||||
delayed = {},
|
||||
lastTime = 0,
|
||||
update = function(...) -- If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
||||
return registry_mt.update(timer, ...)
|
||||
end,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue