Discussion about how to speed up your game

Hi folks,

I would like to discuss about how you can avoid slowdowns in your game loop. Means how to avoid that the framerate drops below 30 FPS.

Atm I am working on an arcade/action game. The gameplay requires that the framerate stays at 30 FPS each frame.
During gameplay I have one background sprite (320x480), one GUI sprite (320x32) and 5-30 sprites with a size of 32x32 on the screen. 5 sprites are always visible and stationary, 10 sprites appear depending on the player input and 10-15 are particles which are handled by the game logic.

For all movements and animation I use TRANSITION.TO commands, which have onComplete functions that also call a TRANSITION.TO method. So for each method I use this approach:

  1. Span object, move it via transition.to (including an onComplete handler)
  2. On complete call another transition.to to handle alpha,size and rotation (including an 2nd onComplete handler)
  3. On 2nd complete, remove the object.

At first I was creating each object on the run via display.newImage and removed it when not needed anymore.
As you can imagine, my framerate was jumping sometimes when I created 10-20 images (particles) in one frame.
Now I preload all the images, store them in a group and have them invisible at first.
When I spawn an object now, I loop throught the group to find the first which is invisible and bring it on the screen. When I want to remove it, I just set it to invisible.

In my enterFrame event handler, I just do collision checks and act on them. For this I loop again through the groups and just check for visible ones, which will be checked for collision. Collisionchekc is done via simple Circle2Circle check or Box2Box checks.

Another thing I did was that I precalculated random-tables to avoid costly math.random calls.

Here is a summary of my speedup methologies:

  1. Preload the images, set them to invisible. Just placing them outside the screen doesn’t help. Or set alpha to 0.0, the engine handles this the same as object.isVisible=false
  2. Use precalculated tables for math.random calls
  3. Use transition.to calls
  4. Create function headers like this local myfuncname = function()
  5. Use locals as much as possible, they are faster than globals. Even in the first level.

I thought that transitions would help big time, but now I am not so sure anymore and will revert the movement and animation handler back into the enterframe function for a test to handle the movement and animation there manually. Maybe it is because of the transition bug I found, but they should be much faster than something that is coded in LUA.

Anyway, I still experience dropping of the framerate. Can you share some of your tips, how to avoid this? Or is Corona only be useable for puzzle games or games that don’t involve 20-40 moving elements? Btw, I test on an IPod touch 2.Generation. I don’t think that the device is that limited regarding objects.

Have a play of geoDefense (lite) and you can see what I mean.

Any input to this is much appreciated.

Michael Hartlef
[import]uid: 5712 topic_id: 848 reply_id: 300848[/import]

Hi, MikeHart.

I don’t think that number of game objects should be a problem for performance. One quick demonstration is that physics video we put up a couple of weeks ago, which generates 45 random objects and then does mutual, continuous collision detection among all of the objects: http://www.youtube.com/watch?v=eDnxN_t7rpU

Of course, that’s in the desktop simulator, but I’m getting the same performance on my iPhone: it hits the 30 fps cap, so it’ll probably go even faster once we remove that cap. Your 2nd-gen Touch should also be pretty fast – they were faster than the iPhone 3G.

However, that demo uses a collision engine that you don’t currently have access to (although we will release it ASAP!) So I have a two-part answer for you:

(1) In the short term, I suspect that your performance bottlenecks, in order, might be: (i) your collision logic, if there’s a lot of cases to test in each frame; (ii) your particle logic, if it’s math-intensive; and (iii) the number of simultaneous transitions you’re using. I’m less certain about (iii), but the issue there might not be the animation itself, but the fact that each transition is registering a callback function, and there might be an issue with having a lot of those piled up.

  • About how many transitions do you have running at the same time?

  • Can you do any culling in your collision loop? Do you have to test everything against everything else in each frame, or can you break that up somehow? Or, as a preliminary test for hotspots: does your game get noticeably faster if you remove half of the collision tests? If collisions really turn out to be the issue, can you get away with box-to-box in your current circle-to-circle cases?

  • Your image preloading is probably a good idea, since the main hardware bottleneck on the iPhone is pushing bitmap data through the pipeline to the GPU, which is basically what happens when you load a new image in Corona. However, loading another copy of the image does not actually use more texture memory, since Corona will intelligently re-use the image data from the first one, and I think it should also be faster for that reason. In other words, you may only want to preload one copy of an image you use multiple times.

(2) Looking ahead, the optimal way of solving your problem will be the new collision engine. We just updated Game Edition from Box2D 2.0.x to 2.1.x, and one of the interesting Box2D design changes is allowing collision detection WITHOUT physics, in case you don’t want gravity or friction or all those other properties, but just want to register events when sprites collide. This part of our API is still in development, so I haven’t tested it yet, but I believe it might be appropriate for arcade-game cases like yours.

[import]uid: 3007 topic_id: 848 reply_id: 1868[/import]

Hi Evan,

thanks for your suggestions. I don’t think it is the collision code. When I do no collision checks at all, the game doesn’t become faster noticable. I cull there already everything possible.
Here is the code:

–****************************************************************
local ColCheck_B2B = function( source, target )
–****************************************************************
local rad = source.radius + target.radius
if mAbs(source.y - target.y) < rad then
if mAbs(source.x - target.x) < rad then
return true
end
end
return false
end

–****************************************************************
local ColCheck_C2C = function( source, target )
–****************************************************************
local xf = (source.x - target.x)
xf = xf * xf
local yf = (source.y - target.y)
yf = yf * yf

local rf = (source.radius*source.xScale) + (target.radius*target.xScale)
rf = rf * rf
if (xf+yf) < rf then
return true
end
return false
end

I think the bottle neck here are the transitions. I have from 2 to 20 running at the same time.
And I notice the slowdown when I create more particles which each has a transition. Like I said, I will test how the game runs without using transition.go . I think they are buggy atm (see my bug report). [import]uid: 5712 topic_id: 848 reply_id: 1869[/import]

I’m convinced now that the transitions are your bottleneck. Those are convenience frameworks that work well for animation sequences, but we never really intended them to be used as a game engine by stacking up a couple dozen of them at once. (This is independent of the bug issue.)

You’ll likely get better performance by just updating everything programmatically in an enterFrame, or (for more OOP architecture) you should also find that multiple enterFrame listeners are much less expensive than running lots of transitions simultaneously.

Like I said, the ultimate solution will be kinematic bodies in the physics engine, which will automate position updates with forces and velocities and collisions, all from the C++ side. But it still sounds like your game should be able to work well without that – keep us updated. [import]uid: 3007 topic_id: 848 reply_id: 1887[/import]

@evank

" Looking ahead, the optimal way of solving your problem will be the new collision engine. We just updated Game Edition from Box2D 2.0.x to 2.1.x, and one of the interesting Box2D design changes is allowing collision detection WITHOUT physics, in case you don’t want gravity or friction or all those other properties, but just want to register events when sprites collide. This part of our API is still in development, so I haven’t tested it yet, but I believe it might be appropriate for arcade-game cases like yours"

Is this available and how do you go about implementing it?

Thanks [import]uid: 8192 topic_id: 848 reply_id: 5262[/import]