RSS

Exploring iPhone Graphics Part 3

May 5th, 2008 Posted in Software Development, iPhone

Graphics Icon

Last time we created a simple iPhone application that made a ball bounce around the screen. This time we are going to extend the last example to use the accelerometer to create a gravity influence on the ball. So as you tilt the device the ball will roll in the direction of the tilt.






The first thing we need to do is add a way to influence the ball’s motion. I’ve added an influence method to the Vector2D class. Also the GravityView class gets a gravity variable that is a Vector2D class instance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- (void)influence:(Vector2D*)influenceVector Max:(CGFloat)max;
{
    [endPoint addVector:influenceVector];
    length = sqrt(endPoint.X * endPoint.X + endPoint.Y * endPoint.Y);
    CGFloat newAngle = atan2(-endPoint.Y, endPoint.X) * ONEEIGHTYOVERPI;
    if(newAngle < 0)
    {
        newAngle += 360;
    }
 
    if(abs(newAngle - influenceVector.angle) >= 90)
    {
        length *= 0.96;
    }
    else
    {
        length *= 1.03;
    }
 
    if(length > max)
    {
        length = max;
    }
    else if(length < 0.0)
    {
        length = 0.0;
    }
 
    [self setAngle:newAngle];
}

This method is passed another vector and a max value. The passed in influenceVector is added to the ball’s endPoint. If the ball is currently moving away from the influence vector then it is slowed down slightly by multiplying the vector length by 0.96. If the ball is currently moving toward the influence vector then it is sped up slightly by multiplying the vector length by 1.03. The maximum length of the vector is capped at the max value passed into the method. The vector is not allowed to have a negative length.

I’ve also added a method to the Vector2D class to scale the length of the vector.

1
2
3
4
5
6
7
8
9
10
11
12
- (void)scaleLength:(CGFloat)factor;
{
    length *= factor;
    if(length < 0.05)
    {
        length = 0.0;
    }
 
    double radians = angle * PIOVERONEEIGHTY;
    endPoint.X = length * cos(radians); // could speed these up with a lookup table
    endPoint.Y = -(length * sin(radians));
}

This method simply multiplies the vector length by the scale factor. When the length of the vector becomes very small it is set to zero.

In order to receive accelerometer events we make the GraphicsView class implement the UIAccelerometerDelegate prototype.

1
@interface GraphicsView : UIView <UIAccelerometerDelegate>

In the GraphicsView initWithFrame method we need to set up the accelerometer.

1
2
3
4
5
    accelX = 0.0;
    accelY = 0.0;
 
    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 60)];
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];

We are initializing the accelerometer x and y values to zero, setting the update interval so that we receive updates 60 times per second and setting self as the delegate.

With the accelerometer set up the accelerometer method of our GraphicsView object instance will be called 60 times per second.

1
2
3
4
5
6
7
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    accelX = (acceleration.x * kAccelFilt) + (accelX * (1.0 - kAccelFilt));
    accelY = (-acceleration.y * kAccelFilt) + (accelY * (1.0 - kAccelFilt));
 
    [gravity setEndPointX:accelX*2 Y:accelY*2];
}

We are using a filter to isolate the current device position. Each time the method is called we set the gravity vector’s end point to two times the accelerometer X and Y values. We don’t need the Z axis accelerometer for this example. Note that we are using negative Y to account for coordinate system differences.

The final piece of the puzzle is to call the influence method of our ball’s vector in the timer tick method.

1
2
3
4
5
6
7
8
9
10
11
- (void)tick
{
    // Apply gravity influence
    [ball.vector influence:gravity Max:8.0];
 
    // Update the balls position
    [ball move:self.bounds];
 
    // Tell the view that it needs to re-draw itself
    [self setNeedsDisplay];
}

That’s all there is to it. Prett simple eh?

Here are the new source files:
Exploring iPhone Graphics Part 3 Source

Share and Enjoy:
  • StumbleUpon
  • Digg
  • Reddit
  • del.icio.us
  • Suggest to Techmeme via Twitter
  • Technorati
  • Slashdot
  • HackerNews
  • Twitter
  • Facebook
  • Print this article!

RSS feed | Trackback URI

5 Comments »

Comment by Ramani
2008-06-20 17:23:46

That’s great. Thank you!

 
Comment by Keith Subscribed to comments via email
2008-09-30 08:57:28

Great tutorials, thanks! I have a question though. No matter how I play with the values here the motion of the ball doesn’t feel exactly right. I want it to be nice and smooth the way apps like “Labyrinth” on the app store are. Do you have any recommendations on how to adapt this code to make it like that, or are they using an entirely different algorithm do you think? Thanks!

Comment by pete
2008-10-08 14:19:08

My algorithm is home grown and just for demonstration purposes.

List of physics engines: http://www.digitalrune.com/KnowledgeBase/RigidBodyDynamics/PhysicsEnginesList/tabid/476/language/en-US/Default.aspx

 
 
2008-10-01 15:44:09

[...] I have found a good tutorial on the subject of making a ball move based on the accelerometer: Exploring iPhone Graphics Part 3 | Trails in the Sand but the motion of the ball does not look nearly as smooth as other apps I have seen (Labyrinth is [...]

 
Comment by iVico Subscribed to comments via email
2009-05-02 02:33:28

Hi, great tutorial, very nice job. However, I can’t deal with a transposition for my own needs. And NOBODY (yes, i said NOBODY) on the web seems to understand something and explains about vectors, except you ^^

I’m sure that my study case should be easy for you, so if you would help me a little on this, it would be very nice :)

If so, send me a PM or email me at ivico92@free.fr (I’d like to talk about my project in privacy ^^)

Thank you, bye bye
iVico

 
Name (required)
E-mail (required - never shown publicly)
URI
Subscribe to comments via email
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped=""> in your comment.