ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 2

13. Анимация

Анимация UIImageView

Создание анимации в приложении — обычное дело. Более того, мало какая игра обходится без таких функций. С помощью UIImageView можно реализовать покадровую анимаци (frame-by-frame animation). Этот вид анимации похож на киноленту, она состоит из серий кадров, которые прорисовываются один за другим через регулярные временные интервалы. Просьба не путать покадровую анимацию с промежуточной (tweening animation), которая чаще всего используется в GIF-файлах. Промежуточными в анимации называются такие рисунки, которые отображаются между основными. На компьютере эти рисунки создаются методом изменения средних значений через определенные промежутки времени и перерисовываниями фона.

 

Сначала вы создаете массив этих самых картинок, заметм передаете этот массив UIImageView. После чего устанавливаете регулярный временной интервал и количество повторов. В интернете достаточно примеров как это делать. По одному из таких примеров я создавал анимации в своих играх. И вдруг я заметил, что мое приложение начало «тупить» при создании такой анимации. Происходило это в тех случаях, когда я загружал в массив большое количество файлов. А связано это с тем, что файловая система iOS, как и большинство других файловых систем работает быстрее с одним большим файлом, чем много маленьких. Именно момент чтения большого количества файлов блокировали интерфейс в моих приложениях.
Чтобы исправить ситуацию я решил посмотреть как в таких случаях поступают профессионалы. В руки мне попала замечательная играPlants vs. Zombies. Я открыл установочный файл программой для архивации и нашел много файлов похожих на этот. Тогда я понял, что все изображения нужно сохранять в один файл, а потом программно разбивать его на нужные мне картинки. Этот процесс я и собираюсь продемонстрировать.

В первую очередь нам следует создать проект. Я создал его на основе представления (View-based Application) и назвал ImageAnimator. Затем добавим в проект вот этот файл.

Перейдем к процессу программирования. Изменим интерфейс класса ImageAnimatorViewController:

<code data-result="[object Object]">#import &lt;UIKit/UIKit.h&gt;

@interface ImageAnimatorViewController : UIViewController {
    UIImageView *animImage;
}

@property (nonatomic, retain) IBOutlet UIImageView *animImage;

- (NSArray*)creatAnimation:(NSString*)fileName;

@end</code>

 

Здесь мы объявили объект типа UIImageView позже мы свяжем его с объектом интерфейса. И метод creatAnimation, который будет возвращать нам массив картинок для анимации.

Теперь изменим соответственно реализацию класса ImageAnimatorViewController:

 

<code data-result="[object Object]">#import "ImageAnimatorViewController.h"

@implementation ImageAnimatorViewController

@synthesize animImage;

- (void)dealloc
{
    self.animImage = nil;
    [super dealloc];
}

- (void)viewDidUnload
{
    self.animImage = nil;
    [super viewDidUnload];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    animImage.animationImages = [self creatAnimation:@"Images.jpg"];
    animImage.animationDuration = 1.0f;
    animImage.animationRepeatCount = 0;
    [animImage startAnimating];
}

- (NSArray*)creatAnimation:(NSString*)fileName {
    UIImage *image = [UIImage imageNamed:fileName];
    NSMutableArray *animationImages = [NSMutableArray array];

    for (int i = 0; i&lt;8; i++) {
        CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage,
                                                           CGRectMake(i*600.0f, 0.0f, 600.0f, 262.0f));
        UIImage *animationImage = [UIImage imageWithCGImage:imageRef];
        [animationImages addObject:animationImage];
        CGImageRelease(imageRef);
    }

    return animationImages;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end</code>

 

Как видите, изменений мы внесли не много. Синтезировали методы доступа и организовали очистку памяти для объекта animImage. Добавили реализацию метода creatAnimation. В него мы передаем имя файла, который будет разбивать на картинки. В самом же методе, по имени этого файла мы создаем объект типа UIImage и здесь же инициализируем массив, в котором будут храниться картинки для анимации. После этого запускаем цикл (массив выполнит 8 итераций поскольку я знаю, что в файле столько картинок). В теле цикла с помощью метода CGImageCreateWithImageInRect мы создаем объект imageRef. Вторым параметром этого метода являются координаты и размер картинки (CGRect), которую мы хотим получить с файла. Затем мы передаем объект imageRef в метод imageWithCGImage, который возвращает нужную нам картинку. Добавляем ее в массив и очищаем после нее память. Чтение всего файла проходит пошагово. При каждой итерации координаты смещаются на 600 пикселей по оси X. Таким образом мы берем с файла все картинки слева на право и складываем их в массив. По окончанию работы цикла метод creatAnimation возвращает сформированный массив.
В методе viewDidLoad мы передаем этот массив параметру animationImages объекта animImage. Кроме массива следует задать длительность выполнения анимации (animationDuration), она задается в секундах. И количество повторов анимации (animationRepeatCount), 0 — означает бесконечно. После установки всех параметров даем команду старта анимации (startAnimating).

Теперь осталось добавить в файле ImageAnimatorViewController.xib объект типа UIImageView и связать его с animImage. Если кто-то забыл как это делается, можно посмотреть здесь.