I'm trying to make a timer that goes on repeat a certain number of times, but it just comes out as an infinite loop. In the following code, only s is ever printed never a, so the program isn't even entering the timer. Any help would be really appreciated
k = 10
sec = 10
i = 0
it = 3
while (i < it) do
text.text = sec
print("s")
timer.performWithDelay( 1000, function ()
print("a")
sec = sec - 1
text.text = sec
if (sec == 0) then
i = i + 1
sec = k
end
end, k)
end
Related
I'm trying to make a part of a program that's a timer through two loops. The timer will repeat a certain number of times (the it variable) hence the first loop. The second loop is the actual timer. For a certain number of seconds, every second it updates the text of a text object. The problem I face is that when I print the text of the text object to the console, it updates, but the text won't change on the screen itself until all the loops are done. Any help with explanation or anything to help guide me in the right direction would be very much appreciated.
Here is the code, don't worry about the unused parameters:
local function sleep(s)
local ntime = os.clock() + s/10
repeat until os.clock() > ntime
end
local function watch(mode, it, text, texty, para)
local text = display.newText(scene.view, "",
display.contentCenterX, 200, nativeSystemFont, 60)
text:setFillColor(0,0,256)
local i = 0
local sec = 0
local goal = 20
text.text = sec
while (i < it) do
sec = 0
while (sec < goal) do
sec = sec + 1
print(text.text)
text.text = sec
sleep(10)
end
i = i + 1
end
end
Sorry for my bad English.
I make a countdown timer using CE GUI with custom progress bar using CE Panel width.
For countdown timer is not a problem, with this function below it work properly.
function performWithDelay(delay,onFinish,onTick,onTickInterval)
if type(delay)~='number' -- mandatory
then error('delay is not a number') end
if type(onFinish)~='function' -- mandatory
then error('onFinish is not a function') end
if onTick and type(onTick)~='function' -- optional
then error('onTick is not a function') end
if onTickInterval and type(onTickInterval)~='number' -- optional, default 1 second
then error('onTickInterval is not a number') end
onTickInterval = onTickInterval or 1000 -- default 1 second
local f = function (t) -- thread function start
local getTickCount = getTickCount
local startTick = getTickCount()
local endTick = startTick + delay
local nextOnTick = startTick + onTickInterval
local ticks
if onTick then
while true do
ticks=getTickCount()
if nextOnTick<ticks then
nextOnTick=ticks+onTickInterval
synchronize(onTick,endTick-ticks)
end
if endTick<ticks then break end
sleep(1)
end
else
while true do
ticks=getTickCount()
if endTick<ticks then break end
sleep(1)
end
end
if onFinish then synchronize(onFinish) end
end -- thread function end
local t = createNativeThreadSuspended(f)
t.name = 'performWithDelay thread'
t.resume()
end
function showTimeLeft(millisecondsLeft)
local totalSeconds = millisecondsLeft // 1000
local deciseconds = (millisecondsLeft % 1000) // 100
LabelTimer.Caption = os.date("!%M:%S",totalSeconds)..'.'..deciseconds
end
function whenFinished()
LabelTimer.Caption = "00:00.0"
-- do something
ButtonTimer.Enabled = true
end
function startCountDown()
-- do something
performWithDelay(20000,whenFinished,showTimeLeft,10)
--- 20000 = 20 seconds
ButtonTimer.Enabled = false
end
ButtonTimer.onClick = startCountDown
Now, for custom progress bar, I have create a timer and variables has known:
progressbar.width = 0 -- at start
progessbar max. width = 208 -- at the end
time = 20 seconds
timer interval = 100 (1/10 seconds)
progess bar step = ??
How to calculating progress bar width to reach maximum width when countdown timer = 0
using pure Lua script?.
Solved:
function start()
st = edtSpTimer.Text --- input how many seconds from user
if tonumber(st) == nil then return nil end -- accept only number
sec = tonumber(st) -- convert text to number
pnPBar.Width = 208 -- set panel width as maximum progrees bar value
step = 208 / sec -- set step by value
tmr.Enabled = true -- triggering a timer
performWithDelay(st*1000,whenFinished,showTimeLeft,10)
end
function bar()
sec = sec - 1 -- counter down the seconds value
pnPBar.width = pnPBar.width - step -- decrease progress bar width
end
tmr = createTimer() -- a timer
tmr.interval = 1000 -- set interval to 1000 = 1 second
tmr.enabled = false
tmr.OnTimer = bar
I am writing a simple script in lua. If the LED is on, it will increment the counter by 1. If the led is off for more than 1 seconds, it reset the counter.
So how exactly do we time event like that in lua ?
This is what i have and been testing multiple ways so far.
function ReadADC1()
local adc_voltage_value = 0
adc_voltage_value = tonumber(adc.readadc()) * 2 -- 0.10 --get dec number out of this -- need to know where package adc come from
--convert to voltage
adc_voltage_value = adc_voltage_value *0.000537109375 --get V
adc_voltage_value = math.floor(adc_voltage_value *1000 +0.5) --since number is base off resolution
--print (adc_voltage_value)
return adc_voltage_value
end
-- end of readADC1() TESTED
function interval()
local counter1 =0
ledValue = ReadADC1()
if (ledValue >= OnThreshHold) then
ledStatus = 1
t1=os.time()
else
ledStatus = 0
t2 = os.time()
end
--counter1 =0
for i=1,20 do
if (ledStatus == 1) then -- if led is off for more than 1 second, reset counter = 0
counter1 = counter1 + 1
elseif ((ledStatus ==0 and ((os.difftime(os.time(),t2)/100000) > 1000))) then -- increment counter when led is on
counter1 = 0
end
end
print (counter1)
end
I know for sure the logic for interval is wrong since os.time return a huge number (i assume it in psecond instead of second).
Any suggest or solution is welcome. I tried vmstarttimer and vmstoptimmer before this but not sure how it work.
EDIT:
function counter()
local ledValue = ReadADC1()
local t1 = os.clock()
while true do
local t2 = os.clock()
local dt = t2 - t1
t1 = t2
if ((ledValue < OnThreshHold) and (dt < 1)) then -- if led is off for less than 1 second
ledCounter = ledCounter + 1
elseif ((ledValue < OnThreshHold) and (dt > 1)) then-- if led is off for more than 1 second
ledCounter = 0;
else
ledCounter = ledCounter
end
print (ledCounter)
end
end
Ultimately, it will be return ledCounter instead of print counter since I will plug the value of counter to another function that will print a message correspond to the number of counter
You could use os.clock which returns your programs runtime since start in seconds.
Returns an approximation of the amount in seconds of CPU time used by the program.
Source
This function could be used in this way.
local t1 = os.clock() -- begin
local t2 = os.clock() -- end
local dt = t2 - t1 -- calulate delta time
-- or looped
local t1 = os.clock() -- begin
while true do
local t2 = os.clock() -- end
local dt = t2 - t1 -- calulate delta time
t1 = t2 -- reset t1
-- use dt ...
end
-- or wait for time elapsed
-- runs until 1 second passed
local t1 = os.clock()
while (os.clock() - t1) < 1 do
-- do stuff while dt is smaller than 1
-- could even reset timer (t1) to current to
-- repeat waiting
-- t1 = os.clock() | ...
end
-- logic for your example
function counter()
local time = os.clock()
local lastLedOn = false
local counter = 0
while true do
if os.clock() - time > 1.0 then
break
end
if getLedValue() == on then -- replace
time = os.clock()
if not lastLedOn then
lastLedOn = true
counter = counter + 1
-- print(counter) | or here if you want to print repeatedly
end
end
end
print(counter)
end -- was unable to test it
I am using timer.performWithDelay to time how long it takes a player to complete a level. I want it to measure down to the 100th of a second (because the game is multiplayer, and I don't want there to be too many ties).
Here is what I did:
local totaltime = 0
local function counter()
totaltime = totaltime + 0.01
print(totaltime)
end
timer1 = timer.performWithDelay( 10, counter, 0)
It results in each "second" lasting about 4 seconds. Is this just not practical or is there a flaw somewhere?
When timer.preformWithDelay is given a time delay smaller then the time between your frames the timer will wait until the next frame is entered to call the function.
That means if you have a game running at 30 or 60 fps, you would have a 'frame ms' of about 16 or 33ms. So the minimum delay you can put is the delay between your frames.
In your case you want to set your timer every 1/100th of a second, or with 10ms. This means, since your frame is most likely 16ms (60fps), that every logged 10ms you are actually waiting an addional 6ms.
Now you could solve this if you ran with 100 FPS and thus achieved said 10 ms, but this is NOT recommendable.
AlanPlantPot provided the answer for following solution on coronaLabs:
I would use the enterFrame function instead. Your timer won't go up in single milliseconds (it will increase by however many ms have passed in each frame), but nobody would be able to read that fast anyway.
local prevFrameTime, currentFrameTime --both nil
local deltaFrameTime = 0
local totalTime = 0
local txt_counter = display.newText( totalTime, 0, 0, native.systemFont, 50 )
txt_counter.x = 150
txt_counter.y = 288
txt_counter:setTextColor( 255, 255, 255 )
group:insert( txt_counter )
and
local function enterFrame(e)
local currentFrameTime = system.getTimer()
--if this is still nil, then it is the first frame
--so no need to perform calculation
if prevFrameTime then
--calculate how many milliseconds since last frame
deltaFrameTime = currentFrameTime - prevFrameTime
end
prevFrameTime = currentFrameTime
--this is the total time in milliseconds
totalTime = totalTime + deltaFrameTime
--multiply by 0.001 to get time in seconds
txt_counter.text = totalTime * 0.001
end
I am using timer.performWithDelay to time how long it takes a player to complete a level. I want it to measure down to the 100th of a second (because the game is multiplayer, and I don't want there to be too many ties).
Here is what I did:
local totaltime = 0
local function counter()
totaltime = totaltime + 0.01
print(totaltime)
end
timer1 = timer.performWithDelay( 10, counter, 0)
It results in each "second" lasting about 4 seconds. Is this just not practical or is there a flaw somewhere?
When timer.preformWithDelay is given a time delay smaller then the time between your frames the timer will wait until the next frame is entered to call the function.
That means if you have a game running at 30 or 60 fps, you would have a 'frame ms' of about 16 or 33ms. So the minimum delay you can put is the delay between your frames.
In your case you want to set your timer every 1/100th of a second, or with 10ms. This means, since your frame is most likely 16ms (60fps), that every logged 10ms you are actually waiting an addional 6ms.
Now you could solve this if you ran with 100 FPS and thus achieved said 10 ms, but this is NOT recommendable.
AlanPlantPot provided the answer for following solution on coronaLabs:
I would use the enterFrame function instead. Your timer won't go up in single milliseconds (it will increase by however many ms have passed in each frame), but nobody would be able to read that fast anyway.
local prevFrameTime, currentFrameTime --both nil
local deltaFrameTime = 0
local totalTime = 0
local txt_counter = display.newText( totalTime, 0, 0, native.systemFont, 50 )
txt_counter.x = 150
txt_counter.y = 288
txt_counter:setTextColor( 255, 255, 255 )
group:insert( txt_counter )
and
local function enterFrame(e)
local currentFrameTime = system.getTimer()
--if this is still nil, then it is the first frame
--so no need to perform calculation
if prevFrameTime then
--calculate how many milliseconds since last frame
deltaFrameTime = currentFrameTime - prevFrameTime
end
prevFrameTime = currentFrameTime
--this is the total time in milliseconds
totalTime = totalTime + deltaFrameTime
--multiply by 0.001 to get time in seconds
txt_counter.text = totalTime * 0.001
end