# Another noob question (timers and spawning actors)

Hello all!

Ran into another problem in my Codea learning adventure…

I am trying to spawn clouds at a certain frequency using a timer and delta time, however something strange is happening. The first 2 clouds spawn at the correct interval, but after that the clouds start spawning closer and closer together until they are spawning once every frame… not sure what I’m doing wrong. Any advice would be appreciated.

Here is what the code looks like:

``````-- Gravity test

supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)
function setup()
clds={} -- clouds table
grnd={} -- ground table
obst={} -- obstacles table
rectMode(CENTER) -- rectangle coordinates from center of rectangle
heliX = WIDTH/6 -- helicopter x starting position
heliY = HEIGHT/2 -- helicopter y starting position
timer=0
cloudFrequency=3.5 -- cloud spawn frequency
heliGrav = 0 -- starting vertical velocity
heliAccel = -.15   -- New variable for acceleration speed
sky() -- spawn first cloud at startup
end
-- cloud spawning function
function sky()
table.insert(clds,vec2(WIDTH+WIDTH/2,700))
end
-- ground spawning function
function ground()

end
-- obstacle spawning function
function obstacles()

end

function draw()
-- draw background
sprite("SpaceCute:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
-- spawn clouds
for a,b in pairs(clds) do
sprite("Space Art:Cloudy Nebula",b.x,b.y,1024,128)
b.x=b.x-6
end
-- destroy clouds when off screen
for a,b in pairs(clds) do
if b.x<-500 then
table.remove(clds, a)
end
-- cloud spawn timer
timer=timer+DeltaTime
if timer>cloudFrequency then
sky()
timer=0
end
end
-- spawn spaceship
sprite("SpaceCute:Rocketship",heliX, heliY, 128, 64)
heliGrav = heliGrav + heliAccel     -- Apply acceleration
heliY = heliY + heliGrav
end

function touched(t)
-- When you touch and when you let go, reverse the acceleration
if t.state == BEGAN or t.state == ENDED then
heliAccel = heliAccel * -1
end
-- So, when you touch it switches to going up, but when you let go it will start falling again
end
``````

What’s happening is you Delta Time is getting larger as the clouds get added. This means there is more time per frame. As a consequence, there is less movement in a given amount of time since the cloud movement occurs once per frame and the fps is slowing down. However, the clouds are still spawning when the timer hits your cloud frequency. This causes the clouds to appear on time but they their movement over time is decreasing. This causes clouds to spawn on top of each other since the other clouds aren’t moving as far. I hope that makes sense. If not do a print statement on delta time and watch.

@Crumble - assuming the diagnosis above is correct, one thing you can do is to make the cloud movement dependent on time as well, so even if the clouds draw more slowly, they will still be the correct distance apart.

``````b.x=b.x-6
``````

use this (6 pixels every 1/60 of a second = 3600 pixels per second)

``````b.x=b.x-3600*DeltaTime
``````

So the reason it is happening is because the frame rate is slowing down? I tried it without using delta time and using a regular timer instead and the same thing occurred, so I don’t think it is tied to frame rate slowdown.

The way I tried with a timer was:

``````cloudFrequency=180
``````

Then

``````Timer=timer+1
``````

Which should have spawned one every 3 seconds

That didn’t seem to work Ingatz, it spawned one cloud that moved very fast, then no other clouds.

I disagree, I think you need to remove timers and focus on counters so a changing delta time won’t hurt you. Using this method it works great! Note: wait a few seconds for clouds to start spawning.

Try this:

``````-- Gravity test

supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)
function setup()
clds={}
grnd={}
obst={}
rectMode(CENTER)
heliX = WIDTH/6
heliY = HEIGHT/2
timer=0

--Now this is a counter variable instead of time
cloudFrequency=200
heliGrav = 0
heliAccel = -.15   -- New variable for acceleration speed

--New Counter
counter=0
end

function sky()
table.insert(clds,vec2(WIDTH+WIDTH/2,700))

end

function ground()

end

function obstacles()

end

function draw()
--Increase counter
counter = counter + 1

--rint(counter)
sprite("SpaceCute:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)

for a,b in pairs(clds) do
sprite("Space Art:Cloudy Nebula",b.x,b.y,1024,128)
b.x=b.x-6
end

for a,b in pairs(clds) do
if b.x<-500 then
table.remove(clds, a)
end
end

--If your counter is a multiple of your cloud frequency then...
if counter%cloudFrequency==0 then
sky()
print("draw")

end

sprite("SpaceCute:Rocketship",heliX, heliY, 128, 64)
heliGrav = heliGrav + heliAccel     -- Apply acceleration
heliY = heliY + heliGrav
end

function touched(t)
-- When you touch and when you let go, reverse the acceleration
if t.state == BEGAN or t.state == ENDED then
heliAccel = heliAccel * -1
end
-- So, when you touch it switches to going up, but when you let go it will start falling again
end
``````

That works perfect!

Thanks much for the help!

I’m confused on what the below is actually doing:

``````If counter%cloudFrequency==0 then
``````

What is the % calculation doing? And how does it equal zero?

It’s cool that it works, but I don’t understand how it works.

% is a modulus. This returns the remainder of the first number divided by the second number. A modulus returns zero if the first number divided by the second number is an integer.

modulus is like this: `a % b` is the same as `b * ((a / b) - math.floor(a / b))`

so 1%2 returns 1, 30%25 returns 5, etc.

This is useful for looping, because as as a increases, it loops back when it reaches b.

For example: b = 10 and a is increasing (a = a + 1), `a % b` will return: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, etc.

So saying `if a % b == 0` will happen every time a has gone b times, so in my above example it would be true every 10 steps.

Hope this helps clear it up for you

Actually modulus is the remainder of one number divided by another number. A modulus returns 0 when one number is evenly divisible by another number, ie. 8%4, 21%7, 99%3 will all have a modulus of 0. Other examples of modulus are 23%7 will return 2, 12%9 will return 3.

Interesting, that makes sense!

So with a 200 cloudFrequency, and the count increasing by 1 every frame(60 fps), it will spawn a new cloud every 3.3333… seconds, or at 200 draws, 400, 600, etc. Cool trick.

When Codea is keeping track of draws, does it start to slow down if the game goes on for say 15 minutes and the draw count gets really high?

You guys are the best, I would be seriously lost without the help of you guys on the forums that are willing to take the time to help. I greatly appreciate it!

You shouldn’t have a problem, if you are worried simply reset counter every time a cloud is spawned so the number will never be high.

@Crumble There are different ways of doing a timer. You can use a counter that increments in the draw function, but the more objects you draw, the more draw slows down. You could use os.time to check the difference between a time start and the current time, that’s not dependent on draw. Or you could use Tweens. I have a tween example below.

``````
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
clds={} -- table of clouds
clouds=cloud()  -- instance of cloud
clouds:start(0) -- spawn a cloud at startup
end

function draw()
background(40, 40, 50)
-- draw cloud and move it
for a,b in pairs(clds) do
sprite("Space Art:Cloudy Nebula",b.x,b.y,1024,128)
b.x=b.x-6
end
-- destroy clouds when off screen
for a,b in pairs(clds) do
if b.x<-500 then
table.remove(clds, a)
end
end
end

cloud=class()   -- cloud timer class

function cloud:start(dur)  -- start a tween with length of dur
tween(dur,{0,0},{0,0},tween.loop.once,function() cloud:spawn() end)
end

function cloud:spawn()
table.insert(clds,vec2(WIDTH+WIDTH/2,700))  -- put cloud in table
clouds:start(4)   -- spawn the next cloud in 4 seconds
end

``````

@dave1707 No need for an empty tween, you can just use tween.delay (which is designed for exactly what you need)

``````
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
clds={} -- table of clouds
clouds=cloud()  -- instance of cloud
clouds:start(0) -- spawn a cloud at startup
end

function draw()
background(40, 40, 50)
-- draw cloud and move it
for a,b in pairs(clds) do
sprite("Space Art:Cloudy Nebula",b.x,b.y,1024,128)
b.x=b.x-6
end
-- destroy clouds when off screen
for a,b in pairs(clds) do
if b.x<-500 then
table.remove(clds, a)
end
end
end

cloud=class()   -- cloud timer class

function cloud:start(dur)  -- start a tween with length of dur
tween.delay(dur,function() cloud:spawn() end)
end

function cloud:spawn()
table.insert(clds,vec2(WIDTH+WIDTH/2,700))  -- put cloud in table
clouds:start(4)   -- spawn the next cloud in 4 seconds
end

``````

@SkyTheCoder Thanks. That just goes to show how often I use Tweens.

You guys are awesome!

I’m going to have to read up on Tweens, no idea what they are.

Woah Tweens are powerful stuff. Looks like I will be using them a lot for moving objects and looping.

Thanks for that