Advertisement

iPhone SDK: Learning About Touch Events & Basic Game Animation

by

This Cyber Monday Tuts+ courses will be reduced to just $3 (usually $15). Don't miss out.

One of most common actions used for an iPhone or iPad application is the touch event. An event is not useful if it doesn’t trigger a meaningful action. This tutorial covers how to attach a touch event to a custom button and how to trigger the animation of an object. In the end, the result is a simple on-screen game controller, which can be extended to the limits of your imagination.

Step 1: Create a New Project

Open Xcode and start a new project. Select View-Based Application. Name the app "jumping," so you can follow along easily.

Step 2: Import the Project Resources

After downloading the attached project file, open the "Images" folder. Here you will find all the image resources we need for this project, including three sprite images of Ryu from Streetfighter as created by PanelMonkey. You will need to copy the images into the project resource folder by dragging them from the folder in Finder and into the "Groups & Files" pane in Xcode.

In the Xcode prompt that will appear, be sure to check the box labeled "Copy items into destination group's folder (if needed)."

All the images needed for the project should now be copied to the same folder where the project file is. Now, to keep the resource folder clean, let's group all of the images we just imported together. Select all the images by holding down command and clicking on each file. Now left-click or ctrl + click and select "Group" from the resulting menu. Name the group whatever you wish. I named mine "images."

Build and run the app in the current state. There should be no compiling errors and the simulator should show a plain, grey screen.

Step 3: Modify jumpingAppDelegate.m

Inside jumpingAppDelegate.m, modify the didFinishLaunchingWithOptions method by adding the following line:

// Allocate a new view, add this line:
self.viewController = [jumpingViewController alloc];

[window addSubview:viewController.view];

This will allocate a new view controller. This step is necessary because we won’t be using Interface Builder to create our view for us.

Step 4: Modify jumpingViewController.h

In the view controller header file (jumpingViewController.h), inside the interface, declare a new property by adding:

UIImageView *player;

Then, before @end, add:

@property (nonatomic, retain) UIImageView *player;

This will allow us to use "player" as a class property for an image.

The header file should now look like this:

#import <UIKit/UIKit.h>

@interface jumpingViewController : UIViewController {
	UIImageView *player;
}

@property (nonatomic, retain) UIImageView *player;

@end

Step 5: Modify jumpingViewController.m

Our next step is to add the graphical and interface elements to this view.

Open the jumpingViewController.m file and delete the existing commented methods. Leave the ones that are not commented.

At the top, after @implementation jumpingViewController, add:

@synthesize player;

Update the dealloc method to the following:

- (void)dealloc {
    [player release];
    [super dealloc];
}

Next, insert the following method:

- (void)addButton {

    UIButton *button = [[UIButton buttonWithType:UIButtonTypeCustom]
                                         initWithFrame:CGRectMake(240, 150, 50, 50)];

    // Set the button's image
    [button setBackgroundImage:[UIImage imageNamed:@"button.png"]
                 forState:UIControlStateNormal];

    // Attach an event
    [button addTarget:self action:@selector(buttonPressed)
                 forControlEvents:UIControlEventTouchUpInside];

    // Add the button to the view
    [self.view addSubview:button];
}

The addButton method will be called later in order to, you guessed it, add the button to the view. The first thing to notice is that this is a custom button. Secondly, buttonPressed is the name of a method that will be called when the touch event is fired.

Go ahead and define a temporary buttonPressed method by inserting the following:

- (void)buttonPressed {
	NSLog(@"Button pressed");
}

NSLog() will send a message to the console, which can be accessed from the menu, under Run (cmd + shift + R).

Our new button should appear on screen after the view has loaded. In order for this to occur, add the following method:

- (void)loadView {

    // Allocate the view
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

    // Set the view's background color
    self.view.backgroundColor = [UIColor blackColor];

    // Create the background image
    UIImageView *bg = [[UIImageView alloc] initWithFrame:CGRectMake(0 , 0, 572, 206)];
    [bg setImage:[UIImage imageNamed:@"bg.jpg"]];
    [self.view addSubview:bg];

    // Create the button
    [self addButton];
}

This method comes by default for view controllers. We're adding a background image and sending the addButton message.

Save your work and then build and run the project. You should see the background image and the red button. If the console window is open, touching the button should display a message in the console via NSLog().

Step 6: Adding a Character to the Screen

In order to initialize our UIImageView object, add the following in jumpingViewController.m, above addButton method:

- (void)initPlayer {
	self.player = [[UIImageView alloc] initWithFrame:
				   CGRectMake(10, 100, 77.0, 94.0)];
	[self normalStance];
	// opaque for better performance
	self.player.opaque = YES;
	[self.view addSubview:self.player];
}
- (void)normalStance {
	[self.player setImage:[UIImage imageNamed:@"ryu.png"]];
}

This code will both initialize a UIImageView object and add it to the main view. The normalStance method will turn out to be useful later.

We will now send the initPlayer message to the main view. We do this by modifying the loadView method as follows:

- (void)loadView {
    // Allocate the view
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

    // Set the view's background color
    self.view.backgroundColor = [UIColor blackColor];

    // create the background image
    UIImageView *bg = [[UIImageView alloc] initWithFrame:CGRectMake(0 , 0, 572, 206)];
    [bg setImage:[UIImage imageNamed:@"bg.jpg"]];
    [self.view addSubview:bg];

    //create the button
    [self addButton];

    // now initialize the player
    [self initPlayer];
}

Build and run. A character appeared on the screen, right?

Step 7: Making Our Character Jump

Now for the fun part. Above addButton, add:

- (void)cleanStance {
    [self.player setImage:nil];
    self.player.animationImages = nil;
}
-(void)jumpStance {
    [self cleanStance];

    NSArray *imageArray = [[NSArray alloc] initWithObjects:
                                                   [UIImage imageNamed:@"jump1.png"],
                                                   [UIImage imageNamed:@"jump2.png"], nil];

        self.player.animationImages = imageArray;
        self.player.animationDuration = 0.3;
        self.player.contentMode = UIViewContentModeBottomLeft;
        [self.view addSubview:self.player];
        [self.player startAnimating];
}

The first method added removes any images associated to the player object. We use this to clean the previously used animation frames. The second method adds a simple animation to our player object. This will appear while the object is moving.

After the jumpStance method, add:

- (void)jump:(UIImageView *)image {
    [self jumpStance];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration: 0.3];
    [UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
    [UIView setAnimationBeginsFromCurrentState:YES];
        image.transform = CGAffineTransformMakeTranslation(0, -40);
    [UIView commitAnimations];
}

This method actually moves the player object. First it changes the image set, then moves it by 40 pixels vertically.

The line:

[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];

Adds an easing effect to the animation, so it looks more realistic.

Change the buttonPressed method to look like this:

- (void)buttonPressed {
    [self jump:self.player];
}

Build and run. By pressing the button now, the character will jump, but will remain frozen in mid air. Good progress! Let’s get him down now.

Step 8: Finalizing the Character Animation

Above the previously added jump method, add:

-(void)fall:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    [self cleanStance];
    [self normalStance];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.2];
        self.player.transform = CGAffineTransformMakeTranslation(0, 0);
    [UIView commitAnimations];
}

This method sets the character back to the normal state and moves it back to the initial position.

Now, change the jump method to look like:

- (void)jump:(UIImageView *)image {
    [self jumpStance];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration: 0.3];
    [UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
    [UIView setAnimationBeginsFromCurrentState:YES];

    // Execute fall after the animation ended
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(fall:finished:context:)];
    image.transform = CGAffineTransformMakeTranslation(0, -40);
    [UIView commitAnimations];
}

Build and run. Press the red button now and our character should jump and land back on the ground. That’s it!

Conclusion

Now you should have a basic understanding of some of the most used classed like: UIButton, NSLog, UIImageView and how to execute animations. A similar approach can be applied to add other buttons on the screen, which can trigger different events, so your target object can perform other actions. Do feel free to contact or follow me on Twitter @tudorizer.

Advertisement