In Part 1 of this series of articles we drew some simple graphic primitives on the iPhone display. In this article we are going to look at how to do some simple animation. The goal of this example is to create a 2D ball that bounces around the iPhone screen.
First of all we need an object to represent a point in our 2 dimensional coordinate system.
The Point2D object will take care of this and just keeps track of X and Y values.
It can be initialized with an X and Y value using the initWithX:Y method. The addVector method will be used to move our ball around the screen.
Next we need a class that represents a vector. The vector will be used to determine the direction that our ball is currently moving in and its speed. The Vector2D class will take of of this.
The Vector2D class manages the angle of the vector and the length of the vector. It also keeps track of the end point of the vector for convenience since we’ll be using the end point to move our ball. The vector can be initialize with an end point using the initWithX:Y method. The angle and length will automatically be calculated.
The angle is calculated from the end point by using the atan2 function. This function returns the angle in radians so we multiply the result by 180/PI to get the angle in degrees. You’ll also notice that we pass a negative Y coordinate to the atan2 function. This is because in our screen coordinate system the Y axis starts at zero at the top of the screen and has positive values as your go down the screen. The geometry functions we are using expect the opposite so we need to reverse the Y coordinates.
If the atan2 function returns a negative number we add 360 to make it positive.
To get the length of the vector we take the square root of x squared + y squared.
Calling the setAngle method will change the angle of the vector and update it’s end point to match the angle. First we convert the angle in degrees to radians by multiplying the angle by PI/180. We get the x end point by multiplying the length of the vector by the cosine of the angle. We get the y end point by multiplying the length of the vector by the sine of the angle. Notice we used a negative on the y value of the endpoint to fix the coordinate system problem.
Now we need a class to represent the ball we are going to move around the screen. I’m calling it Object2D because later this will most likely become a base class for other types of objects. It’ll just be a ball for now though.
The data stored for our ball is just its current position and its current vector. We also have a size that determines the width and height of the ball. If you just call init on the object you get a ball at 0,0 with a zero vector so it won’t move. If you call initWithPostion:vector you can pass in the initial position and vector.
The move method is called to actually move the ball. It adds the vector to the position then it checks to see if the ball has hit any of the screen edges including landing exactly in the corners of the screen. If it has hit a screen edge the bounce method is called and passed the normal angle for the screen edge that was hit.
The bounce method uses the normal angle passed to it to calculate the correct bounce angle for the ball. Then it calls setAngle on the vector to update it.
The draw method is passed a graphics context and draws the ball on it.
Now all we need is a view to make this work.
The view class derives from UIView and will be created by the application delegate class. It just creates a single Object2D to represent our ball and starts an NSTimer to move the ball around. We initialize the ball at 0,0 on the screen and give it a vector with an X,Y of 5,4. We then start a timer that will be called every 1/30th of a second. The timer will call the tick method of the GraphicsView class.
The tick method calls the ball’s move method and passes in the bounds of the view to use for our bounce testing. It then calls setNeedsDisplay to notify the view that it needs to redraw itself.
The drawRect method gets the graphics context, clears it and then calls the ball’s draw method to tell it to draw itself.
That’s all there is to it. Pretty simple, eh? Next time we’ll tie in the accelerometer and maybe add some physics to simulate gravity.
Here are all of the source files:
main.m – ExploringGraphics2AppDelegate.h – ExploringGraphics2AppDelegate.m – GraphicsView.h – GraphicsView.m – Object2D.h – Object2D.m – Point2D.h – Point2D.m – Vector2D.h – Vector2D.m