Статьи

iPhone SDK: изучение сенсорных событий и базовой анимации игры

Одним из наиболее распространенных действий, используемых для приложений iPhone или iPad, является сенсорное событие. Событие бесполезно, если оно не вызывает значимого действия. В этом руководстве рассказывается, как прикрепить сенсорное событие к пользовательской кнопке и как запустить анимацию объекта. В итоге получается простой экранный игровой контроллер, который можно расширить до пределов вашего воображения.

Откройте Xcode и начните новый проект. Выберите View-Based Application. Назовите приложение «прыжки», чтобы вы могли легко следовать за ним.

Загрузив вложенный файл проекта, откройте папку «Изображения». Здесь вы найдете все ресурсы изображений, которые нам нужны для этого проекта, включая три спрайт-изображения Рю из Streetfighter, созданные PanelMonkey. Вам нужно будет скопировать изображения в папку ресурсов проекта, перетащив их из папки в Finder на панель «Группы и файлы» в XCode.

В появившейся подсказке Xcode обязательно установите флажок «Копировать элементы в папку целевой группы (при необходимости)».

Все изображения, необходимые для проекта, теперь должны быть скопированы в ту же папку, где находится файл проекта. Теперь, чтобы сохранить папку ресурсов в чистоте, давайте сгруппируем все изображения, которые мы только что импортировали вместе. Выберите все изображения, удерживая команду и нажимая на каждый файл. Теперь щелкните левой кнопкой мыши или Ctrl + щелкните и выберите «Группа» в появившемся меню. Назовите группу как хотите. Я назвал мои «изображения».

Создайте и запустите приложение в текущем состоянии. Не должно быть ошибок компиляции, и симулятор должен показывать простой серый экран.

Внутри jumpingAppDelegate.m измените метод didFinishLaunchingWithOptions, добавив следующую строку:

1
2
3
4
// Allocate a new view, add this line:
self.viewController = [jumpingViewController alloc];
 
[window addSubview:viewController.view];

Это выделит новый контроллер представления. Этот шаг необходим, потому что мы не будем использовать Interface Builder для создания нашего представления для нас.

В заголовочном файле контроллера представления (jumpingViewController.h) внутри интерфейса объявите новое свойство, добавив:

1
UIImageView *player;

Затем, перед @end, добавьте:

1
@property (nonatomic, retain) UIImageView *player;

Это позволит нам использовать «player» как свойство класса для изображения.

Заголовочный файл должен выглядеть следующим образом:

1
2
3
4
5
6
7
8
9
#import <UIKit/UIKit.h>
 
@interface jumpingViewController : UIViewController {
    UIImageView *player;
}
 
@property (nonatomic, retain) UIImageView *player;
 
@end

Наш следующий шаг — добавить графические элементы и элементы интерфейса в это представление.

Откройте файл jumpingViewController.m и удалите существующие методы с комментариями. Оставьте те, которые не комментируются.

Вверху, после @implementation jumpingViewController, добавьте:

1
@synthesize player;

Обновите метод dealloc следующим образом:

1
2
3
4
— (void)dealloc {
    [player release];
    [super dealloc];
}

Далее вставьте следующий метод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
— (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];
}

Метод addButton будет вызван позже, чтобы, как вы уже догадались, добавить кнопку в представление. Первое, что нужно отметить, это то, что это пользовательская кнопка. Во-вторых, buttonPressed — это имя метода, который будет вызываться при срабатывании сенсорного события.

Идем дальше и определяем временный метод buttonPressed, вставляя следующее:

1
2
3
— (void)buttonPressed {
    NSLog(@»Button pressed»);
}

NSLog () отправит сообщение на консоль, к которому можно получить доступ из меню, в разделе Run (cmd + shift + R).

Наша новая кнопка должна появиться на экране после загрузки представления. Чтобы это произошло, добавьте следующий метод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
— (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];
}

Этот метод используется по умолчанию для контроллеров представления. Мы добавляем фоновое изображение и отправляем сообщение addButton.

Сохраните свою работу, а затем соберите и запустите проект. Вы должны увидеть фоновое изображение и красную кнопку. Если окно консоли открыто, прикосновение к кнопке должно отобразить сообщение в консоли через NSLog ().

Чтобы инициализировать наш объект UIImageView, добавьте следующее в jumpingViewController.m выше метода addButton:

01
02
03
04
05
06
07
08
09
10
11
— (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»]];
}

Этот код будет инициализировать объект UIImageView и добавить его в главное представление. Метод normalStance окажется полезным позже.

Теперь мы отправим сообщение initPlayer на основной экран. Мы делаем это, изменяя метод loadView следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
— (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];
}

Сборка и запуск. На экране появился персонаж, верно?

Теперь самое интересное. Выше addButton добавьте:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
— (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];
}

Первый добавленный метод удаляет все изображения, связанные с объектом игрока. Мы используем это для очистки ранее используемых кадров анимации. Второй метод добавляет простую анимацию к нашему объекту игрока. Это появится, когда объект движется.

После метода jumpStance добавьте:

1
2
3
4
5
6
7
8
9
— (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];
}

Этот метод фактически перемещает объект игрока. Сначала он меняет набор изображений, затем перемещает его на 40 пикселей по вертикали.

Линия:

1
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];

Добавляет эффект смягчения анимации, чтобы она выглядела более реалистично.

Измените метод buttonPressed так, чтобы он выглядел следующим образом:

1
2
3
— (void)buttonPressed {
    [self jump:self.player];
}

Сборка и запуск. Нажав кнопку сейчас, персонаж прыгнет, но останется замороженным в воздухе. Хороший прогресс! Давай его сейчас свалим.

Над ранее добавленным методом прыжка добавьте:

01
02
03
04
05
06
07
08
09
10
11
-(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];
}

Этот метод возвращает персонажа в нормальное состояние и возвращает его в исходное положение.

Теперь измените метод прыжка так:

01
02
03
04
05
06
07
08
09
10
11
12
13
— (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];
}

Сборка и запуск. Нажмите красную кнопку сейчас, и наш персонаж должен прыгнуть и приземлиться на землю. Это оно!

Теперь у вас должно быть общее представление о некоторых наиболее часто используемых классах, таких как: UIButton, NSLog, UIImageView и о том, как выполнять анимацию. Аналогичный подход может быть применен для добавления других кнопок на экране, которые могут инициировать различные события, чтобы ваш целевой объект мог выполнять другие действия. Не стесняйтесь связаться или следовать за мной в Твиттере @tudorizer.