Random delay to a timer

How can I have a random delay occur for every time the timer is run?

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?

I mean that it chooses the same number every time as the delay.

Show us your exact timer code…  (cut-copy-paste it into a code box)

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

Edit: Only one enemy spawns.

This is all the code relating to the timer.

Also, when I am done with this can I just cancel all timers with timer.cancel()? If I can’t do this then how?

If you call timer.cancel with no arguments then you cancel all active timers (unless they have their exclude parameter set to true)

Read more http://www.jasonschroeder.com/2015/02/25/timer-2-0-library-for-corona-sdk/

  1. It is bad practice to make that function global.
     

  2. That code should work just fine.
     
    Make yourself a basic test case exercising just this concept and prove it to yourself, then apply it to your app.
     
    Here is a test case:

    local iterations = 0 local function doit() print("Entered doit() at ", system.getTimer() ) iterations = iterations + 1 if( iterations > 5 ) then return end timer.performWithDelay( math.random(2000, 4000), doit ) end timer.performWithDelay( math.random(2000, 4000), doit )

I get this in the console when I run the above code:

12:55:29.948 Entered doit() at 4014.9 12:55:32.975 Entered doit() at 7046.8 12:55:35.584 Entered doit() at 9659.6 12:55:37.627 Entered doit() at 11702.2 12:55:39.823 Entered doit() at 13890.1

I also found using timer.cancel() without any parameters is not working for me, it crashes my app.

Yeah, that would be a bad idea as it will cancel ALL timers, some of which you might need.  

Note: You should really keep it ONE TOPIC PER POST.  You started this post about randomizing timers, you should open a separate post about cancelling timers.  

I don’t mean to sound like a jerk, but this is bad forum etiquette, and more importantly, you dilute the value of the thread to future readers.  I answer posts to help the current person and future people.