Improve timer, fixing #643 and adding display formatting options.

This commit is contained in:
hispidence 2022-08-08 21:42:04 +01:00
parent 7268b5f8b9
commit 2477c3efcf
2 changed files with 224 additions and 31 deletions

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine Lua API</title> <title>TombEngine 1.0.1 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -89,17 +89,26 @@
<p>Basic timer - after a specified number of seconds, the specified thing happens.</p> <p>Basic timer - after a specified number of seconds, the specified thing happens.</p>
<p> <p>
<p> Usage:</p> <p> Example usage:</p>
<pre> <pre>
<span class="keyword">local</span> Timer = <span class="global">require</span>(<span class="string">"Timer"</span>) <span class="keyword">local</span> Timer = <span class="global">require</span>(<span class="string">"Timer"</span>)
LevelFuncs.FinishTimer = <span class="keyword">function</span>(healthWhenStarted, victoryMessage) <span class="comment">-- This will be called when the timer runs out
DoSomething(healthWhenStarted, victoryMessage) </span>LevelFuncs.FinishTimer = <span class="keyword">function</span>(healthWhenStarted, victoryMessage)
<span class="comment">-- Open a door, display a message, make an explosion... whatever you wish
</span> DoSomething(healthWhenStarted, victoryMessage)
<span class="keyword">end</span> <span class="keyword">end</span>
LevelFuncs.TriggerTimer = <span class="keyword">function</span>(obj) <span class="comment">-- This function triggers the timer
<span class="keyword">local</span> myTimer = Timer.Create(<span class="string">"my_timer"</span>, <span class="number">5.0</span>, <span class="keyword">false</span>, <span class="keyword">true</span>, <span class="string">"FinishTimer"</span>, Lara:GetHP(), <span class="string">"Well done!"</span>) </span>LevelFuncs.TriggerTimer = <span class="keyword">function</span>(obj)
<span class="keyword">local</span> myTimer = Timer.Create(<span class="string">"my_timer"</span>,
<span class="number">5.0</span>,
<span class="keyword">false</span>,
{minutes = <span class="keyword">false</span>, seconds = <span class="keyword">true</span>, deciseconds = <span class="keyword">true</span>},
<span class="string">"FinishTimer"</span>,
Lara:GetHP(),
<span class="string">"Well done!"</span>)
myTimer:Start() myTimer:Start()
<span class="keyword">end</span> <span class="keyword">end</span>
@ -114,7 +123,7 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
<h2><a href="#Functions">Functions</a></h2> <h2><a href="#Functions">Functions</a></h2>
<table class="function_list"> <table class="function_list">
<tr> <tr>
<td class="name" ><a href="#Create">Create(name, totalTime, loop, showString, func, funcArgs)</a></td> <td class="name" ><a href="#Create">Create(name, totalTime, loop, timerFormat, func[, ...])</a></td>
<td class="summary">Create (but do not start) a new timer.</td> <td class="summary">Create (but do not start) a new timer.</td>
</tr> </tr>
<tr> <tr>
@ -138,6 +147,14 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
<td class="summary">Stop the timer.</td> <td class="summary">Stop the timer.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#IsActive">IsActive(t)</a></td>
<td class="summary">Get whether or not the timer is active</td>
</tr>
<tr>
<td class="name" ><a href="#IsPaused">IsPaused(t)</a></td>
<td class="summary">Get whether or not the timer is paused</td>
</tr>
<tr>
<td class="name" ><a href="#GetRemainingTime">GetRemainingTime(t)</a></td> <td class="name" ><a href="#GetRemainingTime">GetRemainingTime(t)</a></td>
<td class="summary">Get the remaining time for a timer.</td> <td class="summary">Get the remaining time for a timer.</td>
</tr> </tr>
@ -172,10 +189,30 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
<dl class="function"> <dl class="function">
<dt> <dt>
<a name = "Create"></a> <a name = "Create"></a>
<strong>Create(name, totalTime, loop, showString, func, funcArgs)</strong> <strong>Create(name, totalTime, loop, timerFormat, func[, ...])</strong>
</dt> </dt>
<dd> <dd>
Create (but do not start) a new timer. Create (but do not start) a new timer. </p>
<p> You have the option of displaying the remaining time on the clock. Timer format details:</p>
<pre><code>-- deciseconds are 1/10th of a second
-- mins:secs
local myTimeFormat1 = {minutes = true, seconds = true, deciseconds = false}
-- also mins:secs
local myTimeFormat2 = {minutes = true, seconds = true}
-- secs:decisecs
local myTimeFormat3 = {seconds = true, deciseconds = true}
-- secs; also what is printed if you pass true instead of a table
local myTimeFormat4 = {seconds = true}
</code></pre>
<p><strong>At any given time, only one timer can show its countdown</strong>.</p>
<p>Use this sparingly; in the classics, timed challenges did not have visible countdowns. For shorter timers, the gameplay benefit from showing the remaining time might not be necessary, and could interfere with the atmosphere of the level.
<h3>Parameters:</h3> <h3>Parameters:</h3>
@ -192,16 +229,17 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
if true, the timer will start again immediately after the time has elapsed if true, the timer will start again immediately after the time has elapsed
</li> </li>
<li><span class="parameter">showString</span> <li><span class="parameter">timerFormat</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">bool</span></span>
if true, the remaining time, rounded up, will show at the bottom of the screen. <strong>At any given time, only one timer can show its remaining time</strong>. If a table is given, the remaining time will be shown as a string, formatted according to the values in the table. If true, the remaining seconds, rounded up, will show at the bottom of the screen. If false, the remaining time will not be shown on screen.
</li> </li>
<li><span class="parameter">func</span> <li><span class="parameter">func</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span> <span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The name of the LevelFunc member to call when the time is up The name of the LevelFunc member to call when the time is upssss
</li> </li>
<li><span class="parameter">funcArgs</span> <li><span class="parameter">...</span>
the arguments with which the above function will be called a variable number of arguments with which the above function will be called
(<em>optional</em>)
</li> </li>
</ul> </ul>
@ -327,6 +365,56 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
</dd>
<dt>
<a name = "IsActive"></a>
<strong>IsActive(t)</strong>
</dt>
<dd>
Get whether or not the timer is active
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
the timer in question
</li>
</ul>
<h3>Returns:</h3>
<ol>
true if the timer is active, false if otherwise
</ol>
</dd>
<dt>
<a name = "IsPaused"></a>
<strong>IsPaused(t)</strong>
</dt>
<dd>
Get whether or not the timer is paused
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
the timer in question
</li>
</ul>
<h3>Returns:</h3>
<ol>
true if the timer is paused, false if otherwise
</ol>
</dd> </dd>
<dt> <dt>
<a name = "GetRemainingTime"></a> <a name = "GetRemainingTime"></a>
@ -479,8 +567,8 @@ LevelFuncs.OnControlPhase = <span class="keyword">function</span>(dt)
</div> <!-- id="content" --> </div> <!-- id="content" -->
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.0.1</a></i>
<i style="float:right;">Last updated 2022-08-01 20:38:26 </i> <i style="float:right;">Last updated 2022-08-08 21:38:19 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -1,14 +1,23 @@
----- -----
--- Basic timer - after a specified number of seconds, the specified thing happens. --- Basic timer - after a specified number of seconds, the specified thing happens.
-- Usage: -- Example usage:
-- local Timer = require("Timer") -- local Timer = require("Timer")
-- --
-- -- This will be called when the timer runs out
-- LevelFuncs.FinishTimer = function(healthWhenStarted, victoryMessage) -- LevelFuncs.FinishTimer = function(healthWhenStarted, victoryMessage)
-- -- Open a door, display a message, make an explosion... whatever you wish
-- DoSomething(healthWhenStarted, victoryMessage) -- DoSomething(healthWhenStarted, victoryMessage)
-- end -- end
-- --
-- -- This function triggers the timer
-- LevelFuncs.TriggerTimer = function(obj) -- LevelFuncs.TriggerTimer = function(obj)
-- local myTimer = Timer.Create("my_timer", 5.0, false, true, "FinishTimer", Lara:GetHP(), "Well done!") -- local myTimer = Timer.Create("my_timer",
-- 5.0,
-- false,
-- {minutes = false, seconds = true, deciseconds = true},
-- "FinishTimer",
-- Lara:GetHP(),
-- "Well done!")
-- myTimer:Start() -- myTimer:Start()
-- end -- end
-- --
@ -22,20 +31,41 @@ LevelVars.__TEN_timer = {timers = {}}
local Timer local Timer
local unpausedColor = Color(255, 255, 255) local unpausedColor = TEN.Color(255, 255, 255)
local pausedColor = Color(255, 255, 0) local pausedColor = TEN.Color(255, 255, 0)
local str = TEN.Strings.DisplayString("TIMER", 0, 0, unpausedColor, false, {TEN.Strings.DisplayStringOption.CENTER, TEN.Strings.DisplayStringOption.SHADOW} ) local str = TEN.Strings.DisplayString("TIMER", 0, 0, unpausedColor, false, {TEN.Strings.DisplayStringOption.CENTER, TEN.Strings.DisplayStringOption.SHADOW} )
Timer = { Timer = {
--- Create (but do not start) a new timer. --- Create (but do not start) a new timer.
--
-- You have the option of displaying the remaining time on the clock. Timer format details:
-- -- deciseconds are 1/10th of a second
--
-- -- mins:secs
-- local myTimeFormat1 = {minutes = true, seconds = true, deciseconds = false}
--
-- -- also mins:secs
-- local myTimeFormat2 = {minutes = true, seconds = true}
--
-- -- secs:decisecs
-- local myTimeFormat3 = {seconds = true, deciseconds = true}
--
-- -- secs; also what is printed if you pass true instead of a table
-- local myTimeFormat4 = {seconds = true}
--
--__At any given time, only one timer can show its countdown__.
--
--Use this sparingly; in the classics, timed challenges did not have visible countdowns. For shorter timers, the gameplay benefit from showing the remaining time might not be necessary, and could interfere with the atmosphere of the level.
--
-- @string name A label to give this timer; used to retrieve the timer later -- @string name A label to give this timer; used to retrieve the timer later
-- @number totalTime The duration of the timer, in seconds -- @number totalTime The duration of the timer, in seconds
-- @bool loop if true, the timer will start again immediately after the time has elapsed -- @bool loop if true, the timer will start again immediately after the time has elapsed
-- @bool showString if true, the remaining time, rounded up, will show at the bottom of the screen. __At any given time, only one timer can show its remaining time__. -- @tparam ?table|bool timerFormat If a table is given, the remaining time will be shown as a string, formatted according to the values in the table. If true, the remaining seconds, rounded up, will show at the bottom of the screen. If false, the remaining time will not be shown on screen.
-- @string func The name of the LevelFunc member to call when the time is up -- @string func The name of the LevelFunc member to call when the time is upssss
-- @param funcArgs the arguments with which the above function will be called -- @param[opt] ... a variable number of arguments with which the above function will be called
-- @return The timer in its paused state -- @return The timer in its paused state
Create = function(name, totalTime, loop, showString, func, ...) --
Create = function(name, totalTime, loop, timerFormat, func, ...)
local obj = {} local obj = {}
local mt = {} local mt = {}
mt.__index = Timer mt.__index = Timer
@ -45,7 +75,6 @@ Timer = {
LevelVars.__TEN_timer.timers[name] ={} LevelVars.__TEN_timer.timers[name] ={}
local thisTimer = LevelVars.__TEN_timer.timers[name] local thisTimer = LevelVars.__TEN_timer.timers[name]
thisTimer.name = name thisTimer.name = name
thisTimer.showString = showString
thisTimer.totalTime = totalTime thisTimer.totalTime = totalTime
thisTimer.remainingTime = totalTime thisTimer.remainingTime = totalTime
thisTimer.func = func thisTimer.func = func
@ -53,6 +82,11 @@ Timer = {
thisTimer.loop = loop thisTimer.loop = loop
thisTimer.active = false thisTimer.active = false
thisTimer.paused = true thisTimer.paused = true
if type(timerFormat) == "table" then
thisTimer.timerFormat = timerFormat
elseif timerFormat then
thisTimer.timerFormat = {seconds = true}
end
return obj return obj
end; end;
@ -89,9 +123,9 @@ Timer = {
thisTimer.active = true thisTimer.active = true
end end
LevelVars.__TEN_timer.timers[t.name].paused = false thisTimer.paused = false
if thisTimer.showString then if thisTimer.timerFormat then
str:SetColor(unpausedColor) str:SetColor(unpausedColor)
end end
end; end;
@ -101,7 +135,7 @@ Timer = {
Pause = function(t) Pause = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name] local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.paused = true thisTimer.paused = true
if thisTimer.showString then if thisTimer.timerFormat then
str:SetColor(pausedColor) str:SetColor(pausedColor)
end end
end, end,
@ -112,6 +146,20 @@ Timer = {
LevelVars.__TEN_timer.timers[t.name].active = false LevelVars.__TEN_timer.timers[t.name].active = false
end, end,
--- Get whether or not the timer is active
-- @param t the timer in question
-- @return true if the timer is active, false if otherwise
IsActive = function(t)
return LevelVars.__TEN_timer.timers[t.name].active
end,
--- Get whether or not the timer is paused
-- @param t the timer in question
-- @return true if the timer is paused, false if otherwise
IsPaused = function(t)
return LevelVars.__TEN_timer.timers[t.name].paused
end,
--- Get the remaining time for a timer. --- Get the remaining time for a timer.
-- @param t the timer in question -- @param t the timer in question
-- @return the time in seconds remaining on the clock -- @return the time in seconds remaining on the clock
@ -173,11 +221,68 @@ Timer = {
end end
end end
if t.showString then if t.timerFormat then
TEN.Strings.HideString(str) TEN.Strings.HideString(str)
str:SetKey(tostring(math.ceil(t.remainingTime)))
local fmt = ""
local remaining = math.max(t.remainingTime, 0)
local round = math.floor
local subSecond = remaining - math.floor(remaining)
local fmtBefore = false
-- deciseconds
if t.timerFormat.deciseconds then
fmt = math.floor(10*subSecond)
fmtBefore = true
end
-- seconds
if t.timerFormat.seconds then
if not fmtBefore then
round = math.ceil
else
round = math.floor
fmt = ":" .. fmt
end
local roundedSeconds = round(remaining)
local toBeDisplayed = roundedSeconds
if t.timerFormat.minutes then
toBeDisplayed = roundedSeconds % 60
end
fmt = string.format("%02d", toBeDisplayed) .. fmt
remaining = roundedSeconds
fmtBefore = true
end
-- minutes
if t.timerFormat.minutes then
if not fmtBefore then
round = math.ceil
else
round = math.floor
fmt = ":" .. fmt
end
local roundedMinutes = round(remaining/60)
local toBeDisplayed = roundedMinutes
fmt = string.format("%02d", toBeDisplayed) .. fmt
fmtBefore = true
end
str:SetKey(fmt)
local myX, myY = PercentToScreen(50, 90) local myX, myY = PercentToScreen(50, 90)
str:SetPosition(myX, myY) str:SetPosition(myX, myY)
-- Do this again in case the player has loaded while the timer was paused already
-- Need a better solution for this
if t.paused then
str:SetColor(pausedColor)
end
TEN.Strings.ShowString(str, 1) TEN.Strings.ShowString(str, 1)
end end