Optimizations

Before you think about optimizing the game, you have to evaluate how well it performs. We put an FPSCounter in the GameScreen class, so let's look at its output on a Hero, a Droid, and a Nexus One.

Hero (Android 1.5):
02-17 00:59:04.180: DEBUG/FPSCounter(457): fps: 25
02-17 00:59:05.220: DEBUG/FPSCounter(457): fps: 26
02-17 00:59:06.260: DEBUG/FPSCounter(457): fps: 26
02-17 00:59:07.280: DEBUG/FPSCounter(457): fps: 26

Nexus One (Android 2.2.1):
02-17 01:05:40.679: DEBUG/FPSCounter(577): fps: 41
02-17 01:05:41.699: DEBUG/FPSCounter(577): fps: 41
02-17 01:05:42.729: DEBUG/FPSCounter(577): fps: 41
02-17 01:05:43.729: DEBUG/FPSCounter(577): fps: 40

Droid (Android 2.1.1):
02-17 01:47:44.096: DEBUG/FPSCounter(1758): fps: 47
02-17 01:47:45.112: DEBUG/FPSCounter(1758): fps: 47
02-17 01:47:46.127: DEBUG/FPSCounter(1758): fps: 47
02-17 01:47:47.135: DEBUG/FPSCounter(1758): fps: 46

The Hero struggles quite a bit, but the game is playable at 25 fps. The Nexus One achieves around 47 fps, and the Droid also reaches 47 fps, which is pretty playable. Can it get better?

In terms of state changes, this is not all that bad. You can reduce some redundant changes here and there, for example some glEnable()/glDisable() calls. But from previous optimization attempts, you know that that won't shave off a lot of overhead.

On the Hero, there's one thing you can do: disable lighting. Once you remove the respective glEnable()/glDisable() calls in WorldRenderer.render(), as well as WorldRenderer.renderShip() and WorldRenderer.renderInvaders(), the Hero achieves the following frame rate:

Hero (Android 1.5):
02-17 01:14:44.580: DEBUG/FPSCounter(618): fps: 31
02-17 01:14:45.600: DEBUG/FPSCounter(618): fps: 31
02-17 01:14:46.610: DEBUG/FPSCounter(618): fps: 31
02-17 01:14:47.630: DEBUG/FPSCounter(618): fps: 31

That's quite a bit of improvement, and all you have to do is turn off lighting. Special-casing the rendering code for a certain device is possible, but it's good to avoid that. Is there anything else you can do?

The way you render explosions is suboptimal in the case of an exploding invader. You can change the model and texture bindings in the middle of rendering all invaders, which will make the graphics pipeline a little unhappy. However, explosions don't happen often, and don't take a long time (1.6 seconds). The measurements just shown, however, were taken without any explosions on screen, so that's not the culprit.

The truth is that you are rendering too many objects per frame, causing significant call-overhead and stalling the pipeline a little. With your current knowledge of OpenGL ES, there's nothing much you can do about that. However, given that the game “feels” rather playable on all devices, it's not an absolute must to achieve 60 fps. The Droid and Nexus One have a notoriously hard time rendering even mildly complex 3D scenes at 60 frames per second. So, the final lesson to take away from this is: don't get crazy if your game doesn't run at 60 fps. If it is visually smooth and plays well, you can even make do with 30 fps.

NOTE: Other common optimization strategies involve using culling, vertex buffer objects, and other more advanced topics that aren't discussed here. We tried adding these to our Droid Invaders—the effect: zero. None of these devices benefit from these optimizations. That does not mean these techniques are useless. That depends on a lot of factors and their side-effects, and it's hard to predict how certain configurations will behave. If you are interested, just search for those terms on the Web and try the techniques out yourself!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset