Accelerometer and Vibration on the iPhone

Last friday I attended an excellent session at Øredev 2008, on Android by Mike Jennings from Google. At the end of the presentation Mike show the code for a simple application with a bouncing blue ball, controlled by the accelerometer. What stroke me was that the git of the application was 85 lines of code, and Mike told us most of the physics and life cycle code was hidden away. I have never used the accelerometer on the iPhone, but my gut told me that 85 lines was allot of code.

So I took out my laptop during the next 60 minutes of Panel Debate, and wrote an iPhone app, and as I expected the code landed on 46 lines of code for the actual application logic, physics, grits and all. Or 112 lines of code if headers and boiler-plate should be counted as well.

This blog post will describe what I did, in a quite nice model-view-controller fashion (Model and Controller is implemented in the same class).

  • First of all I needed a view to display my bouncing ball on, I choose to subclass UIViewController to handle this view.
  • A standard UIView instance with a UIImageView sub-view for the ball is all I need for my view, this I setup using Interface Builder.
  • And the model/logic is handled by one CGPoint for the current location, and one CGPoint with the current delta movement of the ball.

First the custom view controller sets up itself as the accelerometer delegate when awakening from it’s nib-file.

-(void)awakeFromNib;
{
  self.location = CGPointMake(160, 230);
  UIAccelerometer* accelerometer = [UIAccelerometer sharedAccelerometer];
  accelerometer.updateInterval = 0.02;
  accelerometer.delegate = self;
}

Then comes a private function for the quite faked physics, it is responsible for detecting if a value with a given delta movement has hit a min or max edge. If it do hits an edge, it flips it’s delta movement with some deceleration, and corrects it’s value.

static inline BOOL bounce(float* val, float* delta, float min, float max) {
#define FLIP(val, c) (c - (val - c))
  if (*val < min || *val > max) {
    *delta = -(*delta * 0.75);
    float loc = *val < min ? min : max;
    *val = FLIP(*val, loc);
    return YES;
  }
  return NO;
}

And lastly the delegate method that is called by the accelerometer. Here we update the delta movement, and use the bounce-function to detect and compensate location+delta when the ball hits any edges. If an edge it hit, a vibration is also triggered.

-(void)accelerometer:(UIAccelerometer*)accelerometer
       didAccelerate:(UIAcceleration*)acceleration;
{
#define CAP(val, max) (val < -max ? -max : (val > max ? max : val))
  CGPoint delta = CGPointMake(CAP(self.delta.x + acceleration.x, 32),
                              CAP(self.delta.y - acceleration.y, 32));
  CGPoint location = CGPointMake(self.location.x + delta.x,
                                 self.location.y + delta.y);
  if (bounce(&location.x, &delta.x, 8, self.view.bounds.size.width - 8 ) ||
      bounce(&location.y, &delta.y, 8, self.view.bounds.size.height - 8))
  {
      AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
  }
  self.delta = delta;
  self.location = location;
  self.ballView.center = self.location;
}

In conclusion Cocoa Touch requires surprisingly little code for accessing and using the accelerometer and trigger a vibration. Triggering a vibration is literary done with a single line of code. The lines of code needed to setup and listen to the accelerometer can literary be counted on the fingers of one hand.

On the downside there is no finer control of the vibration, and if you like to have the rotation angles of the device instead of simple gravity forces of the x, y and z axis, then you must do the math for yourself. Simple enough, but it would had been nice to have to current rotations around each axis as well.

The full source code can be downloaded here.

ps. I dare Mike Jennings to best this :). ds.

This Post Has 5 Comments

  1. guyal

    Very helpful, thx

  2. john mabassa

    Cool stuff!! Please add more tutorials :)

  3. Will Culpepper

    Please pardon my OCD but I noticed a typo at the end of your first paragraph. “allot” instead of “a lot”. Feel free to delete this comment.

  4. Caleb Daniels

    Very very good

Leave a Reply