Random delay to a timer

I apologize for this, I was not aware of bad “forum” manners.

No need to apologize, just pointing it out so you know.  I’m keen on helping folks, and threads that morph are one of my pet peeves (behind hijackings which really get my goat)… speaking of which, back on topic.

Again, try my standalone example and you’ll see the concept is sound.  Then apply it to your app and you should be golden.

They are spawning at random now, I had made a silly mistake before, but they only spawn 6 enemies and the timer stops.

Well, it isn’t stopping because the timer is failing.  It is stopping because somewhere in your code you are not calling the timer.performWithDelay() function.

Add print statements at each point where that function can exit and see if it exits without executing timer.performWithDelay().  

The easiest way to do this if your function has NO return statements is to do something like this:

function spawnEnemies() print("Entered spawnEnemies @ ", system.getTimer() ) -- first line ... print("Calling spawnEnemies @ ", system.getTimer() ) -- Right before every call to performWithDelay timer.performWithDelay(math.random(2000, 4000), spawnEnemies) ... print("Exitting spawnEnemies @ ", system.getTimer() ) -- last line end

I’m sorry but what do you mean by the function can exit?

  1. I added comments to my answer above, so go back and check them out.

  2. If you follow those instructions, you’ll see messages like this:

    13:11:43.352 Entered spawnEnemies @ 2605.4 13:11:43.352 Calling spawnEnemies @ 2605.4 13:11:43.352 Exited spawnEnemies @ 2605.4 … 13:11:52.776 Entered spawnEnemies @ 12029 13:11:52.776 Calling spawnEnemies @ 12029 13:11:52.776 Exited spawnEnemies @ 12029

  3. If you see messages like this:

    13:11:43.352 Entered spawnEnemies @ 2605.4 13:11:43.352 Calling spawnEnemies @ 2605.4 13:11:43.352 Exited spawnEnemies @ 2605.4 … 13:11:52.776 Entered spawnEnemies @ 12029 13:11:52.776 Exited spawnEnemies @ 12029

,then you are skipping the call to performWithDelay() in  your code

PS - I’ve gotta get back to work, so I won’t be answering any more for now.  Anyways, I think you’re armed with the info you need now.

PPS - By ‘can’ exit, I meant any place where the function can be exited.  Typically this is only at the end of the function, but if you have a return statement earlier in an if-statement or elsewhere in the function then, that is an alternate exit point.

 function spawnEnemies() print("Entered spawnEnemies @ ", system.getTimer() ) -- first line temp = math.random(1, 4) if temp == 1 then enemy = display.newSprite(beetle, beetleSequenceData) enemy.x = \_R + 100 enemy.y = \_CY enemy.hasBeenScored = false physics.addBody(enemy, "dynamic", physicsData:get("beetle")) enemy.xScale = -1 enemy.id = "enemy" enemy.isFixedRotation = true enemy:play() group:insert(enemy) elseif temp == 2 then enemy2 = display.newSprite(vulture, vultureSequenceData) enemy2.x = \_R + 100 enemy2.y = \_CY - (enemy2.height \* 0.25) enemy2.hasBeenScored = false physics.addBody(enemy2, "dynamic", physicsData:get("vulture")) enemy2.xScale = -1 enemy2.gravityScale = -0.01 enemy2.id = "enemy2" enemy2.isFixedRotation = true enemy2:play() specialGroup:insert(enemy2) elseif temp == 3 then enemy3 = display.newSprite(scorpion, scorpionSequenceData) enemy3.x = \_R + 100 enemy3.y = \_CY enemy3.hasBeenScored = false physics.addBody(enemy3, "dynamic", physicsData:get("scorpion")) enemy3.xScale = -1 enemy3.id = "enemy3" enemy3.isFixedRotation = true enemy3:play() group:insert(enemy3) else enemy4 = display.newSprite(bee, beeSequenceData) enemy4.x = \_R + 100 enemy4.y = \_CY - (enemy4.height \* 0.25) enemy4.hasBeenScored = false physics.addBody(enemy4, "dynamic", physicsData:get("bee")) enemy4.xScale = -1 enemy4.gravityScale = -0.01 enemy4.id = "enemy4" enemy4.isFixedRotation = true enemy4:play() specialGroup:insert(enemy4) end print("Entered doit() at ", system.getTimer() ) iterations = iterations + 1 if( iterations \> 5 ) then return end print("Calling spawnEnemies @ ", system.getTimer() ) timer.performWithDelay( math.random(2000, 4000), spawnEnemies ) print("Exitting spawnEnemies @ ", system.getTimer() ) end --Under scene:show phase == "did" print("Calling spawnEnemies @ ", system.getTimer() ) timer.performWithDelay(math.random(2000, 4000), spawnEnemies)

This is your problem.

if( iterations > 5 ) then return end

This is a point where it can (and will) exit the function.

No worries, thank you for all your help, when you are free:

It had exited without execution on the iterations return statement. So should I get rid of it?

Sincerely, 

Alex

I got it working it is randomized and does not stop.

local function doit() -- do something here timer.performWithDelay( math.random( 1000, 2000 ), doit ) end timer.performWithDelay( math.random( 1000, 2000 ), doit )

Read about math.random and math.randomseed Know more http://lua-users.org/wiki/MathLibraryTutorial 

Hope this help :slight_smile:

When I try using timer.performWithDelay( math.random( 2000, 4000 ), etc, -1 )

It always end up choosing the same number every time. It is not random at all.

That isn’t how it works…

This code: 

timer.performWithDelay( math.random( 2000, 4000 ), function() end , -1 )

Literally does this:

  1.  Evaluates ‘math.random(2000,4000)’ and passes that value as argument ONE  to  timer.performWithDelay()
  • For this example, let’s assume the return value of  ‘math.random(2000,4000)’ is 1500
  1.  Creates  ‘function() end’ and passes a reference to the new closure as argument TWO to timer.performWithDelay(

  2.  Passes -1  as argument  THREE  to timer.performWithDelay() which says ‘loop forever’.

Now, the timer executes every ~1500 ms and calls the function that was passed in argument TWO.

If you want to get a new random time value every time you need to call it the way I showed you above… i.e. Do not call it with -1 arg and re-call it at the end of the function that you do work in.

It is still not random, this is my code:

function spawnEnemies() temp = math.random(1, 4) if temp == 1 then enemy = display.newSprite(beetle, beetleSequenceData) enemy.x = \_R + 100 enemy.y = \_CY enemy.hasBeenScored = false physics.addBody(enemy, "dynamic", physicsData:get("beetle")) enemy.xScale = -1 enemy.id = "enemy" enemy.isFixedRotation = true enemy:play() group:insert(enemy) elseif temp == 2 then enemy2 = display.newSprite(vulture, vultureSequenceData) enemy2.x = \_R + 100 enemy2.y = \_CY - (enemy2.height \* 0.25) enemy2.hasBeenScored = false physics.addBody(enemy2, "dynamic", physicsData:get("vulture")) enemy2.xScale = -1 enemy2.gravityScale = -0.01 enemy2.id = "enemy2" enemy2.isFixedRotation = true enemy2:play() specialGroup:insert(enemy2) elseif temp == 3 then enemy3 = display.newSprite(scorpion, scorpionSequenceData) enemy3.x = \_R + 100 enemy3.y = \_CY enemy3.hasBeenScored = false physics.addBody(enemy3, "dynamic", physicsData:get("scorpion")) enemy3.xScale = -1 enemy3.id = "enemy3" enemy3.isFixedRotation = true enemy3:play() group:insert(enemy3) else enemy4 = display.newSprite(bee, beeSequenceData) enemy4.x = \_R + 100 enemy4.y = \_CY - (enemy4.height \* 0.25) enemy4.hasBeenScored = false physics.addBody(enemy4, "dynamic", physicsData:get("bee")) enemy4.xScale = -1 enemy4.gravityScale = -0.01 enemy4.id = "enemy4" enemy4.isFixedRotation = true enemy4:play() specialGroup:insert(enemy4) end timer.performWithDelay(math.random(2000, 4000), spawnEnemies) end

elseif ( phase == "did" ) then -- Code here runs when the scene is entirely on screen print("shown") physics.start() timer.performWithDelay(math.random(2000, 4000), spawnEnemies) moveEnemiesTimer = timer.performWithDelay(2, moveEnemies, -1) end

Also, how can I remove all timers?

Thank you for your help.

I believe timer.cancel() will cancel all timers, but you should store your timers into a variable. Something like tmr_createEnemies = timer.performWithDelay(1000, spawnEnemies, 1). Then, you can cancel the timer by doing timer.cancel(tmr_createEnemies).

Ok, but I am still having problem with setting a random delay to a timer.

What? and what do you mean it is not random?