Skip to content

Commit 4c02e8c

Browse files
committed
setMaxFPS方法改名setMainLoopSpeed,优化主循环睡眠策略,新增setSleepDurationError方法允许手动设置睡眠/忙等两种策略的平衡
1 parent ee1d35d commit 4c02e8c

3 files changed

Lines changed: 46 additions & 27 deletions

File tree

graphicExtend.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,8 @@ do -- function GC.load(L), GC.execute(t)
760760
local code=list[i]
761761
local cmd=code[1]
762762
if type(cmd)=='string' then
763-
cmd=assert(cmds[cmd],"GC.load(L): No gc command: "..cmd)(unpack(code,2))
763+
if not cmds[cmd] then error("GC.load(L): No gc command: "..cmd) end
764+
cmd=cmds[cmd](unpack(code,2))
764765
elseif type(cmd)=='function' then
765766
cmd(unpack(code,2))
766767
else

init.lua

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@
185185
--- print(AE'r;d;_M'.."reset, delete, magenta "..AE.."and reset manually")
186186
--- ```
187187
---
188-
--- And some useful utility functions like `ZENITHA.setMaxFPS` `ZENITHA.setDebugInfo` `ZENITHA.setVersionText`.
188+
--- And some useful utility functions like `ZENITHA.setMainLoopSpeed` `ZENITHA.setDebugInfo` `ZENITHA.setVersionText`.
189189
---
190190
--- Experimental modules:
191191
--- `WAIT`, `DEBUG`, `SYSFX`, `TEXT`, `VIB`, `WHEELMOV`, `LOADLIB`, `MIDI`
@@ -367,7 +367,8 @@ local discardCanvas=false
367367
local showFPS=true
368368
local updateFreq=100
369369
local drawFreq=100
370-
local sleepInterval=1/60
370+
local mainLoopInterval=1/60
371+
local sleepDurationError=0
371372
local clickDist2=62
372373
local maxErrorCount=3
373374
---@class Zenitha.GlobalEvent
@@ -1252,10 +1253,9 @@ function love.run()
12521253
local timer=ZENITHA.timer.getTime
12531254

12541255
local frameTimeList={}
1255-
local lastLoopTime=timer()
1256-
local lastUpdateTime=lastLoopTime
1257-
local lastDrawTime=lastLoopTime
1258-
local lastScreenCheckTime=lastLoopTime
1256+
local lastUpdateTime=timer()
1257+
local lastDrawTime=lastUpdateTime
1258+
local lastScreenCheckTime=lastUpdateTime
12591259

12601260
-- counters range from 0 to 99, trigger at 100
12611261
-- start at 100 to guarantee trigger both of them at first frame
@@ -1272,12 +1272,10 @@ function love.run()
12721272

12731273
-- Main loop
12741274
return function()
1275-
local time=timer()
1275+
-- Loop start time
1276+
local loopT=timer()
12761277
STEP()
12771278

1278-
-- local loopDT=time-lastLoopTime
1279-
lastLoopTime=time
1280-
12811279
-- EVENT
12821280
if PUMP then
12831281
PUMP()
@@ -1296,8 +1294,8 @@ function love.run()
12961294
if updateCounter>=100 then
12971295
updateCounter=updateCounter-100
12981296

1299-
local updateDT=time-lastUpdateTime
1300-
lastUpdateTime=time
1297+
local updateDT=loopT-lastUpdateTime
1298+
lastUpdateTime=loopT
13011299

13021300
if mouseShow then mouse_update(updateDT) end
13031301
if next(jsState) then gp_update(jsState[1],updateDT) end
@@ -1321,8 +1319,8 @@ function love.run()
13211319
if drawCounter>=100 then
13221320
drawCounter=drawCounter-100
13231321

1324-
local drawDT=time-lastDrawTime
1325-
lastDrawTime=time
1322+
local drawDT=loopT-lastDrawTime
1323+
lastDrawTime=loopT
13261324

13271325
gc_replaceTransform(SCR.origin)
13281326
BG._draw()
@@ -1337,7 +1335,7 @@ function love.run()
13371335
gc_replaceTransform(xOy)
13381336
SYSFX._draw()
13391337
TEXT.draw(TEXT)
1340-
if mouseShow then globalEvent.drawCursor(mx,my,time) end
1338+
if mouseShow then globalEvent.drawCursor(mx,my,loopT) end
13411339
gc_replaceTransform(SCR.xOy_ul)
13421340
globalEvent.drawSysInfo()
13431341
gc_replaceTransform(xOy)
@@ -1402,9 +1400,9 @@ function love.run()
14021400
end
14031401

14041402
-- Check screen size
1405-
if time-lastScreenCheckTime>1.26 and (gc.getWidth()~=SCR.w or gc.getHeight()~=SCR.h) then
1403+
if loopT-lastScreenCheckTime>1 and (gc.getWidth()~=SCR.w or gc.getHeight()~=SCR.h) then
14061404
love.resize(gc.getWidth(),gc.getHeight())
1407-
lastScreenCheckTime=time
1405+
lastScreenCheckTime=loopT
14081406
end
14091407

14101408
-- Slow devmode
@@ -1416,9 +1414,9 @@ function love.run()
14161414
end
14171415
end
14181416

1419-
local curFrameInterval=timer()-lastLoopTime
1420-
if curFrameInterval<sleepInterval*.9626 then SLEEP(sleepInterval*.9626-curFrameInterval) end
1421-
while timer()-lastLoopTime<sleepInterval do end
1417+
local timeRemain=loopT+mainLoopInterval-timer()
1418+
if timeRemain>sleepDurationError then SLEEP(timeRemain-sleepDurationError) end
1419+
while timer()-loopT<mainLoopInterval do end
14221420
end
14231421
end
14241422

@@ -1500,10 +1498,30 @@ function ZENITHA.setCleanCanvas(bool)
15001498
end
15011499

15021500
---Set the max update rate of main loop cycle
1503-
---@param fps number Default to 60
1504-
function ZENITHA.setMaxFPS(fps)
1505-
assert(type(fps)=='number' and fps>0,"ZENITHA.setMaxFPS(fps): Need >0")
1506-
sleepInterval=1/fps
1501+
---@param lps number Loop/sec, default to 60
1502+
function ZENITHA.setMainLoopSpeed(lps)
1503+
assert(type(lps)=='number' and lps>0,"ZENITHA.setMainLoopSpeed(lps): Need >0")
1504+
mainLoopInterval=1/lps
1505+
end
1506+
1507+
---Set the sleep duration error to balance accuracy & performance of main-loop-frequency
1508+
---
1509+
---Recommend value:
1510+
---| Mode \| | Value |
1511+
---| -: | :-: |
1512+
---| Accuracy \| | 🪟1.0, 🐧0.5 |
1513+
---| Normal \| | 0 |
1514+
---| Performance \| | -0.5 |
1515+
---| Power-Saving \| | -1.0 |
1516+
---
1517+
---How this works: Because `love.timer.sleep(t)` is not accurate enough (always a bit more time), so we can sleep `[setting value] LESS`, then busy-wait to obtain the exact time interval.
1518+
---
1519+
---But `sleep()` actually only accept integer microsecond value, so when we need to sleep 1.5ms, doing `sleep(1.5ms)` is same as `sleep(1ms)`, so busy-wait will still work for ~0.5ms.
1520+
---That's why we accept negative number. Setting error to -1ms means we will do `sleep(2.5ms)` when we need 1.5, so busy-wait is guaranteed not to be triggered, saving more resource.
1521+
---@param ms number in [-1,1], default to 0 (ms)
1522+
function ZENITHA.setSleepDurationError(ms)
1523+
assert(type(ms)=='number' and ms>-1 and ms<1,"ZENITHA.setSleepFault(ms): Need in [-1,1]")
1524+
sleepDurationError=ms/1000
15071525
end
15081526

15091527
---Set the updating rate of the application

widget.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,8 +1132,8 @@ function Widgets.slider:reset(init)
11321132
if type(self.valueShow)=='function' then
11331133
self._showFunc=self.valueShow
11341134
elseif type(self.valueShow)=='string' then
1135-
self._showFunc=assert(sliderShowFunc[self.valueShow],"[slider].valueShow need function, or 'int', 'float', or 'percent'")
1136-
end
1135+
self._showFunc=sliderShowFunc[self.valueShow] or error("[slider].valueShow need function, or 'int', 'float', or 'percent'")
1136+
end
11371137
elseif self.valueShow==false then -- Show nothing if false
11381138
self._showFunc=sliderShowFunc.null
11391139
else -- Use default if nil

0 commit comments

Comments
 (0)