June 03, 2012

Shake to Pause

This morning I was groggily playing the game I'm working on called KanaSwirl, supine in bed. Phone inches above my face, purring along in the game, then pow!, I slipped and the bastard hit me right in the cheek. Of course, my game kept running, ignoring my curse, smarting, and eventual rescue of my phone off the floor. But it got me thinking: why didn't the game pause? The iPhone has an accelerometer: surely it would be trivial to sense the sudden jolt of glass hitting flesh.

And it turns out the implementation was indeed trivial. I simply just want to capture the moral equivalent of the "shake" gesture and then automatically launch the pause screen. Most games, mine included, already have automatic pausing (for when you receive a phone call or multitask away), so that part's free. Luckily KanaSwirl doesn't use the accelerometer for in-game effects, so I can abuse it for this feature.

The new code follows. I use the cocos2d game framework which has tiny abstractions over the accelerometer API, but I'm sure it's trivially applicable to other systems as well.

/* during initialization ... */
self.isAccelerometerEnabled = YES;
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 60)];

- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"shakeToPause"]) {
        if (abs(acceleration.x) > 1 || abs(acceleration.y) > 1 || abs(acceleration.z) > 1) {
            [self autoPause];
        }
    }
}

I'm sure that if check for acceleration could be improved (compare the overall magnitude instead of each component separately?), but what I have here has worked well for me. It doesn't automatically trigger when I'm walking even animatedly, but it does pass the phone-falls-into-cheek test. On the off-chance you don't want this behavior, I went ahead and added a snarky setting too.

While I initially added this for when I dropped my phone, it's also useful as advertised — it's easier to shake your phone than it is to peck at the onscreen pause button. I'm sure many other games could benefit from this shake to pause idea. If you add it to your game, I'd like to hear about it!