iPhone Game Development - Chris Craft [73]
FIGURE 5.14
Tiled image with offset of (0, 0)
FIGURE 5.15
Tiled image with offset of (160, 240)
Listing 5.4
Adding a Timer and the CGContextDrawTiledImage Method
#import “MainView.h”
@implementation MainView
UIImage *currentImage;
int tileOffset = 0;
-(void)awakeFromNib {
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
[car setAlpha:0];
[road setAlpha:0];
currentImage = [UIImage imageNamed:@”road.png”];
// start a timer that will fire every second
[NSTimer scheduledTimerWithTimeInterval:(1.0) target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
// start a timer that will fire every hundredth of a second
[NSTimer scheduledTimerWithTimeInterval:(0.01) target:self selector:@selector(onTimerRoad) userInfo:nil repeats:YES];
}
- (void)onTimerRoad
{
tileIndex += 1;
[self setNeedsDisplay];
}
- (void)onTimer {
[self update];
}
- (void)update {
[self updateRoad];
}
- (void)updateRoad {
[self randomRoadUpdate];
}
- (void)randomRoadUpdate {
int distance = (random() % 11) - 5;
CGPoint oldPosition = road.center;
if(oldPosition.x + distance < 96 || oldPosition.x + distance > 224)
return;
road.center = CGPointMake(oldPosition.x + distance, oldPosition.y);
}
- (void)draw {
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGImageRef image = CGImageRetain(currentImage.CGImage);
CGRect imageRect;
imageRect.origin = CGPointMake(160, 240);
imageRect.size = CGSizeMake(320.0, 480.0);
CGContextRef uiContext = UIGraphicsGetCurrentContext();
CGContextClipToRect(uiContext, CGRectMake(0.0, 0.0, rect.size.width, rect.size.height));
CGContextDrawTiledImage(uiContext, imageRect, image);
}
- (void)dealloc {
[super dealloc];
}
@end
Putting the player in charge
Now that the road is functioning properly, you want to make the player's race car zoom down the highway as expected. Your first objective is to allow the player to move the car to the left or right using the iPhone's built-in accelerometer. The iPhone SDK makes this very easy. Let's review the code that you will need to add to make this happen.
You will need to create a share instance of the UIAccelerometer and set its update interval to every second. At the top of the form you will need to define a constant that stores the accelerometer's refresh rate. Then you will need to point the UIAccelerometer's delegate at the Main View by setting the delegate using the keyword self:
// Constant for the number of times per second (Hertz) to sample acceleration.
#define kAccelerometerFrequency 40
// Configure and start the accelerometer
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
This will inform the iPhone OS that your application would like to be notified of accelerometer changes every second. The following method is the delegate that the iPhone accelerometer will call when the device accelerates:
// UIAccelerometerDelegate method, called when the device accelerates.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
[self updateCar:-acceleration.x* 30];
}
The delegate will call our worker function, and this function will update the screen as needed to match the player's input:
- (void)updateCar:(CGFloat)positionInDegrees {
int distance = positionInDegrees;
CGPoint oldPosition = car.center;
car.center = CGPointMake(oldPosition.x + distance, oldPosition.y - 1);
}
Remember to always update your header file to match any changes