Version Information
This tutorial has been updated for Codea version 2.3.1(47). You can check your version of Codea by tapping on the Two Lives Left logo in the bottom middle of the Codea start screen (Tutorial 1, Figure 1).
Interlude 1.1 Delay and Frame Rate
A question on the Codea Forums got me thinking about how you might slow things down if your code is animating too quickly. There is no sleep or delay function in Lua so initially I thought something like the following would work.
function delayForSeconds(secs) secs = secs or 1 local endTime = os.time() + secs while os.time() < endTime do end end
This doesn't actually work on my iPad unless you use a delay of greater than 65 seconds. Which is not particularly useful. Why is this so?
Well if you whip out your handy print() function and have a look at what os.time() returns you will see that it is a VERY large number (something like 1.34e+09 which is the number of seconds since the EPOCH or possibly something else...). A quick visit to the Codea Reference will tell you that the number you get backs depends on your system. There is probably something useful that you can do with this but Codea provides easier ways.
So next I looked at DeltaTime and ElapsedTime. Note that the trick with using these is they only change each time draw() gets called so you can't use them in separate function and wait for these to change to the value you are looking for.
The approach I ended up with is shown in the code example below which prints out the frame rate every second. Remember in Tutorial 1 I said that Codea tries to call the draw() function 60 times per second, this code will show you what is actually being achieved. if you have a complex program your frame rate may be less than 60.
function setup() initTimeValue = ElapsedTime frameCounter = 0 end function draw() if (ElapsedTime - initTimeValue < 1) then frameCounter = frameCounter + 1 else print("Frames per second: "..frameCounter) frameCounter = 0 initTimeValue = ElapsedTime end end
Interlude 1.2 A Better Approach to Displaying Frame Rate
The problem with the previous approach to displaying frame rate for your program is that it is continually printing to the console. This makes it difficult if you are printing out other variables or status because they keep scrolling off the screen.
A better approach is to use the parameter.watch() function which is designed specifically for monitoring variables in real time. Here is the revised code.
function setup() -- FPS is the variable which contains our Frames Per Second calculation FPS = 0 parameter.watch("FPS") timeInterval = 0 frameCount = 0 end function draw() -- Set the background to Black background(0, 0, 0) -- Calculate Frames Per Second (FPS) frameCount = frameCount + 1 timeInterval = timeInterval + DeltaTime if timeInterval > 1 then FPS = math.round(frameCount / timeInterval) timeInterval = 0 frameCount = 0 end end function math.round(num) -- There is no math.round in Codea currently. -- Thanks to @Vega for providing this function return math.floor(num + 0.5) end
Interlude 1.3 An Even Simpler Approach to FPS
function setup() -- FPS is the variable which contains our Frames Per Second calculation FPS = 0 parameter.watch("FPS") end function draw() -- Set the background to Black background(0, 0, 0) -- Calculate Frames Per Second (FPS) -- -- DeltaTime = time in seconds since the last frame was drawn, -- it is a number provided by Codea. FPS = math.round(1/DeltaTime) end function math.round(num) -- There is no math.round in Codea currently. -- Thanks to @Vega for providing this function return math.floor(num + 0.5) end
If we add this to our rounded rectangle app from Tutorial 2 it will look like Figure 15.
When we run the updated program, you will be able to see (Figure 16) that drawing a rounded rectangle runs at 60 frames per second or thereabouts as we would expect - since it isn't a very complicated rendering exercise. You will need to scroll down to see the FPS parameter as it was the last one that we added.
Figure 15. RoundRect with FPS.
Figure 16. FPS Displayed
Dear David,
ReplyDeleteI'm following your tutorial. Very nice...
One little mistake here:
-- FPS is the variable which contains our Frames Per Second calculation
FPS = 0
watch(FPS)
Should be:
-- FPS is the variable which contains our Frames Per Second calculation
FPS = 0
watch("FPS")
Franz
Hi Franz,
ReplyDeleteThanks for the comment and and well spotted. You are correct, this is one of the dangers of typing code in rather than copy and paste. I will correct it in the Tutorial.
Cheers,
D
Did you try using LUA's os.clock() function?
ReplyDeleteIt delivers time values in millisecs and can be used for small delays. I haven't tried it with Codea on iPad, but it works with LoveCodea on a Win machine.
example for a milliseconds delay:
function delay(msec)
if msec>0 then
local start=os.clock()
local stop=start+msec/1000
while os.clock()<stop do end
end
end
...quite wasteful on CPU time but works.
Thanks for the code - yes that would probably work. As you say, there are more elegant approaches than just causing the CPU to spin its wheels.
Delete