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
Related
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
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
In a game I'm making, there's a square where the game is happening inside. I want the circles that spawn in to start at the top and travel down to the bottom. In the original program, they travel from left to right. How would I go about this? I don't know how to get it to start at the top and travel down instead of starting at the left and traveling to the right.
Here's the original code (I know it's a lot, sorry). I am trying to help a friend.
--Made by Joms or /u/jomy582
--Please credit me if using this in a battle.
spawntimer = 0
timerspawn = 0
storedtime = Time.time
bullets = {}
bulletsbig = {}
bulletswarn = {}
dir = 1
bigheight = {33, 98}
function Update()
spawntimer = spawntimer + (Time.dt*Time.mult)
timerspawn = timerspawn + (Time.dt*Time.mult)
--normal bullets
--change the number in the if statement to make them spawn more frequently/less frequently
--EX: spawntimer > 0.2 spawns them pretty fast
--EX2: spawntimer > 1 spawns them pretty slow
--Make sure to change the subtraction method in the if statement
if spawntimer > 0.16 then
spawntimer = spawntimer-0.16
local bullet = CreateProjectile("bullet", -Arena.width/2, math.random(-Arena.height/2, Arena.height/2))
bullet.SetVar("deadly", true)
table.insert(bullets, bullet)
end
--warning. spawns a warning every 5 seconds
--You could change it, but that may cause some bugs
if timerspawn > 2.2 then
timerspawn = timerspawn-2.2
dir = math.random(1,2)
local bulletwarn = CreateProjectile("warning", 0, Arena.height/2 - bigheight[dir])
bulletwarn.SetVar("warningtimer", 0)
bulletwarn.SetVar("soundtimer", 0)
bulletwarn.SetVar("animtimer", 0)
bulletwarn.SetVar("anim", 1)
table.insert(bulletswarn, bulletwarn)
end
--controlling normal bullets
--a simple method that moves the bullets 1 pixel each frame
--you can change it by editing the bullet.move
--EX: bullet.Move(5*Time.mult, 0) moves the bullets 5 pixels each frame
for i=1, #bullets do
local bullet = bullets[i]
if bullet.isactive then
bullet.Move(2*Time.mult, 0)
if bullet.y > -Arena.height/2 then
bullet.Remove()
end
end
end
--controlling warning timer
--a method that controls the warning timer
for i=1, #bulletswarn do
local bullet = bulletswarn[i]
if bullet.isactive then
local warningtimer = bullet.GetVar("warningtimer") + (Time.mult*Time.dt)
local soundtimer = bullet.GetVar("soundtimer") + (Time.mult*Time.dt)
local animtimer = bullet.GetVar("animtimer") + (Time.mult*Time.dt)
local bulletSprite = bullet.sprite
local anim = bullet.GetVar("anim")
--flashing colors
--change the animtimer > TIME where time is how often you want the warning to blink
--warnings last for 3 seconds. Can change that as well
--to get different colors, find the rgb value of the color you want and insert them below
if animtimer > 0.08 then
animtimer = animtimer-0.08
if anim == 1 then
local r = 0 --put Red value here
local g = 0 --put Green value here
local b = 169 --put Blue value here
bulletSprite.color = {r/255, g/255, b/255} -- changes the color to whatever you'd like. Uses RGB.
bullet.SetVar("anim", 2)
elseif anim == 2 then
local r = 0 --put Red value here
local g = 0 --put Green value here
local b = 255 --put Blue value here
bulletSprite.color = {r/255, g/255, b/255} -- changes the color to whatever you'd like. Uses RGB.
bullet.SetVar("anim", 1)
end
end
--plays a timer evert 10 frames for 3 seconds.
--change the soundname to change the sound
--change the soundtimer > 0.16 to change how often it plays
--can change how long it lasts as well by changing the less than statement
if soundtimer > 0.10 then
soundtimer = soundtimer-0.10
Audio.PlaySound("alarm")
end
--this controls when to spawn the bullets
--change the statement to change how long the warning timer is
if warningtimer > 2 then
warningtimer = warningtimer-2
Audio.PlaySound("shoot")
local bullet1 = CreateProjectile("leftbigbullet", Arena.width/2+30, Arena.height/2 - bigheight[dir]) --where to spawn them
bullet1.SetVar("speed", -4) --how fast
bullet1.SetVar("deadly", true)
local bullet2 = CreateProjectile("rightbigbullet", -Arena.width/2-30, Arena.height/2 - bigheight[dir]) --where to spawn them
bullet2.SetVar("speed", 4) --how fast
bullet2.SetVar("deadly", true)
table.insert(bulletsbig, bullet1)
table.insert(bulletsbig, bullet2)
bullet.Remove()
end
bullet.SetVar("warningtimer", warningtimer)
bullet.SetVar("animtimer", animtimer)
bullet.SetVar("soundtimer", soundtimer)
end
end
--controlling big bullets
--this method controls the big bullets
for i=1, #bulletsbig do
local bullet = bulletsbig[i]
if bullet.isactive then
local speed = bullet.GetVar("speed")
bullet.SendToBottom()
bullet.Move(speed*Time.mult, 0)
if bullet.absx > 700 or bullet.absx < -70 then
bullet.Remove()
end
end
end
end
function OnHit(bullet)
if(bullet.getVar("deadly")) then
Player.Hurt(3)
end
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
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