- Lowering the frame rate of a game increases the battery life by a significant amount.
- Games do not need a high frame rate when displaying a static screen, or a simple 2D animation.
- Our game actively throttles down the frame rate according to what animations are playing at any given time. This reduces the battery consumption by a small, but not insignificant amount.
- Most commercial games do not make any attempt to lower the frame rate when displaying static screens, wasting battery life.
Background
A lot of game developers bring the PC mind-set with them when they start developing for mobile devices. For PC games the target is to achieve the legendary 60 frames per second rate. This is fine when the hardware is connected to an electrical outlet, but power consumption becomes an important factor when your device is running from a battery. Rather than thinking of speed alone, you need to think of entertainment value. Imagine two people on a 3 hour flight who are playing games on their iPhones to pass the time. One has a 60 FPS game, but the battery runs out mid journey. The other is playing a game that is capped at 30 FPS and the battery lasts the whole journey. Which of these two people gets the most entertainment value? You don't actually even need 30 FPS a lot of the time. At certain points during the game it might be showing only a static menu, or a simple animation - for instance a blinking light and you do not need 30 FPS for that. To play an animation smoothly you need a frame rate that's twice the frame frequency of the animation. For instance, a simple 2D flag animation that has 3 frames and repeats every second only needs 6 FPS to play smoothly. Anything above that is overkill. Apple themselves consider battery consumption to be an extremely important issue. Their own developer guidelines advise the following:Do not draw to the screen faster than needed. Drawing is an expensive operation when it comes to power. Do not rely on the hardware to throttle your frame rates. Draw only as many frames as your application actually needs.
But, we decided to take this idea one step further.Frame rate throttling
The technique we developed works by adjusting the frame rate according to what is being displayed on the screen at each instant. Each object displayed on screen indicates what frame rate it requires and the game loop controller picks the largest frame rate requirement. The screen-shots below illustrate this more clearly:
Test setup
The following devices were used: iPhone 3GS, OS ver 3.1.3 iPod 1st Gen, OS ver 2.2.1 All measurements were done with the device fully charged, the auto-lock disabled and screen brightness at 80%. Only comparative measurements on the same device are valid, as the battery life varies widely between devices, depending on the age of the battery.How much does the frame rate effect battery life?
We want to measure the effect of the frame rate on battery life, so we fully charged the devices, and let it run until the 10% warning message pops up on screen. Armageddon Wars normally runs at 33 FPS during battle sequences and then throttles down to 1 FPS when animation stops. We changed the game to hard code the frame rate to various settings, 60 FPS, 33 FPS, 25 FPS and 1 FPS. (Note: the 60 FPS test could only be run on the iPhone 3GS - The iPod touch is too slow)

Real world tests
Next we tried measuring the actual battery consumption while playing the game. Our game is a turn-based strategy. The user needs time to consider their next move and while they are thinking usually the scene is static; only after they make their move are animations and special effects played: explosions, fire, smoke etc. When the animations are playing the frame rate is at maximum, but when the scene becomes static again the frame rate is throttled down. So, the average frame rate will be below the maximum rate, depending on how long the player needs to make their move. The following diagram illustrates this more clearly:

Compared against other games
The power saving technique works better for strategy games, where there is a tendency to have more static screens, so we tested against some strategy games from the App Store. Each game was put on a static screen and let run until the 10% warning message appeared on the screen.
Technical details
I'd like to give you a brief overview of how the power save technique was implemented. These diagrams have been simplified for clarity. Firstly, the game had the following class structure:

Changing the standard iPhone Game loop
The default OpenGL ES iPhone template uses a NSTimer object to update the game loop. The timer is set on initialization of the game to call the game loop once every 1/60th second. The OS is responsible for making NSTimer call the game loop. If a timer event triggers while the game loop is still running, that event will be ignored and it'll just wait for the next NSTimer event. Because the timer events are not synchronized with the game loop, this method is a bit inaccurate. For our power saving technique to work we need a more precise way to control the game loop. What we do is create a special game loop thread during app startup. Basically, the game loop looks like the following: