Отображение анимации по кадрам?
У меня есть анимация, состоящая из 100 изображений. Я хочу иметь возможность отображать анимацию через последовательность кадров. Например, вместо отображения анимации от 0:00 до 0:32 секунд я предпочел бы использовать Frame 0 to Frame 32. Мне нужно сделать это, потому что мне нужно много контроля над анимацией (даже разница в одном frame создаст неправильный результат). Я рисовал каждый кадр лично, поэтому я знаю изображение каждого кадра.
В любом случае я могу сделать это в Cocoa, используя Objective-C? Как мне это сделать? Все, что у меня есть, - это 100 изображений, и я не знаю, как исходить отсюда. А также, будет ли это "лагги" по сравнению с указанием времени?
Я бы предпочел подробный ответ, потому что я не мог найти какие-либо ресурсы в Интернете и совершенно новичок в этом.
Обратите внимание, что я использую OS X, а не iOS, поэтому, пожалуйста, не предоставляйте ответы, связанные с iOS. Я работаю с Xcode 3.2.6 на Snow Leopard.
Ответы
Ответ 1
Путь к максимальному контролю будет заключаться в том, чтобы хранить все ваши изображения в массиве. Если вы назвали свои изображения чем-то вроде "frame.png" (т.е. "Frame1.png" ), вы можете быстро загрузить все свои изображения следующим образом:
frames = [[NSMutableArray alloc] init]; // In header: NSMutableArray *frames;
for (int i = 1; i < 100; i++) // 100 can be replaced for any number of frames.
{
NSString *filename = [NSString stringWithFormat:@"frame%i.png", i];
[frames addObject:[NSImage imageNamed:filename]];
}
То, что это делает, создает массив и заполняет его с помощью NSImage
, названного в честь ваших файлов. %i
заменяется в строке для текущего значения i
.
Теперь вам понадобится другая переменная, чтобы отслеживать текущий кадр. Что-то вроде unsigned int currentFrame;
. Это можно либо увеличить каждый цикл обновления, либо установить определенное значение, что даст вам полный контроль над отображаемым фреймом.
Затем в вашем цикле рендеринга вы можете отобразить любой кадр, который в настоящий момент хранится следующим образом:
[(NSImage *)[frames objectAtIndex:currentFrame - 1] drawAtPoint:animPos fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
где animPos
- это NSPoint, содержащий позицию, в которую вы хотите нарисовать. - 1
присутствует в индексе, поэтому вы можете ссылаться на свои фреймы, начиная с 1, а не на 0. Этот код вытягивает изображение в рамке currentFrame
и отображает его на экран.
Поскольку вы используете массив, также обязательно проверяйте currentFrame
, никогда не равное значению больше максимального количества кадров, например: if (currentFrame > 100) currentFrame = 1;
. Это заставило бы анимацию зацикливаться, поскольку, когда она попадает в последний кадр, currentFrame будет возвращаться к начальному индексу массива.
Для получения дополнительной информации о чертеже вы должны посмотреть: Cocoa Руководство по рисованию и Ссылка на класс NSImage.
Кроме того, если вам нужна дополнительная информация о том, как обновлять фрейм каждый шаг времени, загляните в NSTimer Class Reference.
Ответ 2
Вы можете использовать этот код для анимации кадра за кадром. Надеюсь, это поможет вам.
// create the view that will execute our animation
UIImageView* imageListView = [[UIImageView alloc] initWithFrame:self.view.frame];
// load all the frames of our animation
imageListView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:@"campFire01.gif"],
[UIImage imageNamed:@"campFire02.gif"],
[UIImage imageNamed:@"campFire03.gif"],
[UIImage imageNamed:@"campFire04.gif"],
[UIImage imageNamed:@"campFire05.gif"],
[UIImage imageNamed:@"campFire06.gif"],
[UIImage imageNamed:@"campFire07.gif"],
[UIImage imageNamed:@"campFire08.gif"],
[UIImage imageNamed:@"campFire09.gif"],
[UIImage imageNamed:@"campFire10.gif"],
[UIImage imageNamed:@"campFire11.gif"],
[UIImage imageNamed:@"campFire12.gif"],
[UIImage imageNamed:@"campFire13.gif"],
[UIImage imageNamed:@"campFire14.gif"],
[UIImage imageNamed:@"campFire15.gif"],
[UIImage imageNamed:@"campFire16.gif"],
[UIImage imageNamed:@"campFire17.gif"],
//all your 100 images// , nil];
// all frames will execute in 1.75 seconds
imageListView.animationDuration = 1.75;
// repeat the annimation forever
imageListView.animationRepeatCount = 0;
// start animating
[imageListView startAnimating];
// add the animation view to the main window
[self.view addSubview:imageListView];
Ответ 3
Вы можете использовать CADisplayLink. Вот пример того, как его использовать:
В вашем методе инициализации настройте ссылку на изображение:
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(playAnimation:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Затем добавьте метод:
- (void)playAnimation:(CADisplayLink*)displayLink
{
// Set the right image to display
self.imageToDisplay = TheRightImageBasedOnYourAnimationSequence
[self setNeedsDisplay];
}
И, наконец, в методе drawRect: отобразите изображение. Класс CADisplayLink имеет атрибуты для управления продолжительностью кадра и т.д.
Ответ 4
Повторить ответ @wquist: -
frames = [[NSMutableArray alloc] init]; // In header: NSMutableArray *frames;
for (int i = 1; i < 100; i++) // 100 can be replaced for any number of frames.
{
NSString *filename = [NSString stringWithFormat:@"frame%i.png", i];
[frames addObject:[NSImage imageNamed:filename]];
}
В прошлом у меня было несколько анимаций с именами файлов, такими как image_00000.png, image_00001.png, и чтобы позаботиться о них, я использовал что-то вроде этого: -
NSString *filename = [NSString stringWithFormat:@"frame%05d.png", i];
Ответ 5
Часть слайд-шоу этого примерного кода может вам помочь.
https://developer.apple.com/library/mac/#samplecode/CocoaSlides/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004072
Ответ 6
Пробовали ли вы подклассифицировать NSAnimation и изменили ли отображаемое изображение каждый тик?
EDIT:
Сначала вы создаете подкласс NSAnimation. Затем переопределите setCurrentProgress:
, вызвав его реализацию суперкласса и изменив представление в зависимости от currentValue
. См. Следующее руководство для более подробных инструкций: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/AnimationGuide/Articles/TimingAnimations.html#//apple_ref/doc/uid/TP40003581-SW1
Ответ 7
Я сделал простой проект, который вы, возможно, можете использовать: вы можете найти здесь проект
Надеюсь, это то, что вам нужно