Добавление действий к узлам

Рисование спрайтов полезно, но статическое изображение является изображением, не игрой. Для добавления геймплея необходимо быть в состоянии переместить спрайты вокруг экрана и выполнить другую логику. Основной механизм, что использование Набора Sprite для анимации сцен является действиями. До этой точки Вы видели некоторую часть подсистемы действия. Теперь, пора получить более глубокую оценку для того, как действия создаются и выполняются.

Действие является объектом, определяющим изменение, которое Вы хотите внести в сцену. В большинстве случаев действие применяет свои изменения в узле, выполняющем его. Так, например, если Вы хотите переместить спрайт через экран, Вы создаете действие перемещения и говорите узлу спрайта выполнять то действие. Набор Sprite автоматически анимирует позицию того спрайта, пока не завершается действие.

Действия являются автономными объектами

Каждое действие является непрозрачным объектом, описывающим изменение, которое Вы хотите внести в сцену. Все действия реализованы SKAction класс; нет никаких видимых подклассов. Вместо этого действия различных типов инстанцируют с помощью методов класса. Например, вот наиболее распространенные вещи, которые Вы используете действия, чтобы сделать:

После создания действия его тип не может быть изменен, и у Вас есть ограниченные возможности изменить его свойства. Набор Sprite использует в своих интересах неизменную природу действий для выполнения их очень эффективно.

Действия могут или быть мгновенными или немгновенными:

Полный список методов класса, привыкших к действиям по созданию, описан в Ссылке класса SKAction, но только необходимо пойти туда, когда Вы готовы к подробному взгляду на то, как сконфигурировать определенные действия.

Узлы выполненные действия

Действие только выполняется после того, как Вы скажете узлу выполнять его. Самый простой способ выполнить действие состоит в том, чтобы вызвать узел runAction: метод. Перечисление 3-1 создает новое действие перемещения и затем говорит узлу выполнять его.

Перечисление 3-1  , Выполняющее действие

SKAction *moveNodeUp = [SKAction moveByX:0.0 y:100.0 duration:1.0];
[rocketNode runAction: moveNodeUp];

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

В любое время можно выполнить действия. Однако, если Вы добавляете действия к узлу, в то время как сцена обрабатывает действия, новые действия могут не выполниться до следующего кадра. Шаги, которые сцена использует для обработки действий, описаны более подробно в Усовершенствованной Обработке Сцены.

Даже если те действия выполнялись в разное время, узел может выполнить многократные действия одновременно. Сцена отслеживает то, как далеко каждое действие от завершения и вычисляет эффект, который действие имеет на узел. Например, если Вы выполняете два действия, перемещающие тот же узел, оба действия применяют изменения в каждом кадре. Если бы действия перемещения были в равных и противоположных направлениях, то узел остался бы стационарным.

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

Если узел выполняет какие-либо действия, hasActions возвраты свойства YES.

Отмена рабочих действий

Для отмены действий, которые выполняет узел вызовите removeAllActions метод. Все действия сразу удалены из узла. Если удаленное действие имело продолжительность, любые изменения, которые оно уже внесло в узел, остаются неповрежденными, но не выполняются дальнейшие изменения.

Получение Обратного вызова, когда Завершается Действие

runAction:completion: метод идентичен runAction: метод, но после того, как действие завершается, Ваш блок вызывают. Если действие работает к завершению, этот обратный вызов только вызывают. Если действие удалено, прежде чем оно завершится, обработчик завершения никогда не вызывают.

Используя именованные действия для точного управления действиями

Обычно, Вы не видите, какие действия узел выполняет и если Вы хотите удалить действия, необходимо удалить всех их. Если необходимо видеть, выполняется ли определенное действие, или удалите определенное действие, необходимо использовать названные действия. Именованное действие использует имя уникального ключа для идентификации действия. Можно запустить, удалить, найти и заменить названные действия с узлом.

Перечисление 3-2 подобно Перечислению 3-1, но теперь действие идентифицируется с ключом, ignition.

Перечисление 3-2  , Выполняющее именованное действие

[SKAction *moveNodeRight = [SKAction moveByX:100.0 y:0.0 duration:1.0];
[spaceship runAction: moveNodeRight withKey:@"ignition"];

Следующие основанные на ключе методы доступны:

  • runAction:withKey: метод для выполнения действия. Если действие с тем же ключом уже выполняется, это удалено, прежде чем новое действие добавляется.

  • actionForKey: метод, чтобы определить, работает ли уже действие с тем ключом.

  • removeActionForKey: метод для удаления действия.

Перечисление 3-3 показывает, как Вы могли бы использовать именованное действие для управления перемещением спрайта. Когда пользователь щелкает в сцене, метод вызывается. Код определяет, где щелчок произошел и затем говорит спрайту выполнять действие для перемещения в ту позицию. Заранее вычисляется продолжительность так, чтобы спрайт всегда, казалось, перемещался в фиксированную скорость. Поскольку этот код использует runAction:withKey: метод, если спрайт уже перемещался, предыдущее перемещение, останавливается середина реки и новые перемещения действия от текущей позиции до новой позиции.

Перечисление 3-3  , Перемещающее спрайт в новую позицию щелчка мышью

- (void)mouseDown:(NSEvent *)theEvent
{
    CGPoint clickPoint = [theEvent locationInNode:self.playerNode.parent];
    CGPoint charPos = self.playerNode.position;
    CGFloat distance = sqrtf((clickPoint.x-charPos.x)*(clickPoint.x-charPos.x)+
                             (clickPoint.y-charPos.y)*(clickPoint.y-charPos.y));
 
    SKAction *moveToClick = [SKAction moveTo:clickPoint duration:distance/characterSpeed];
    [self.playerNode runAction:moveToClick withKey:@"moveToClick"];
}

Создание действий, который выполненные другие действия

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

Последовательности выполненные действия последовательно

Последовательность является рядом действий, работающих последовательно. Когда узел выполняет последовательность, действия инициированы в последовательном порядке. Когда одно действие завершается, следующее действие сразу запускается. Когда последнее действие в последовательности завершается, действие последовательности также завершается.

Перечисление 3-4 показывает, что последовательность создается с помощью массива других действий.

Перечисление 3-4  , Создающее последовательность действий

SKAction *moveUp = [SKAction moveByX:0 y:100.0 duration:1.0];
SKAction *zoom = [SKAction scaleTo:2.0 duration:0.25];
SKAction *wait = [SKAction waitForDuration: 0.5];
SKAction *fadeAway = [SKAction fadeOutWithDuration:0.25];
SKAction *removeNode = [SKAction removeFromParent];
 
SKAction *sequence = [SKAction sequence:@[moveUp, zoom, wait, fadeAway, removeNode]];
[node runAction: sequence];

Существует несколько вещей, которые стоит отметить в этом примере:

  • wait действие является специальным действием, обычно использующимся только в последовательностях. Это действие просто ожидает сроком на время и затем заканчивается, ничего не делая; Вы используете их для управления синхронизацией последовательности.

  • removeNode действие является мгновенным действием, таким образом, оно занимает время для выполнения. Вы видите, что несмотря на то, что это действие является частью последовательности, это не появляется на временной шкале на рисунке 3-1. Как мгновенное действие, это начинается и сразу завершается после того, как исчезнуть действие завершается. Это действие заканчивает последовательность.

  Перемещение рисунка 3-1 и изменение масштаба упорядочивают временную шкалу

Группы выполненные действия параллельно

Действия группы являются набором действий, которые все начинают выполнять, как только выполняется группа. Вы используете группы, когда Вы хотите, чтобы синхронизировались действия. Например, код в Перечислении 3-5 поворачивает и поворачивает спрайт для предоставления иллюзии колеса, прокручивающегося через экран. Используя группу (вместо того, чтобы выполнить два отдельных действия) подчеркивает, что эти два действия тесно связаны.

Перечисление 3-5  Используя группу действий для вращения колеса

SKSpriteNode *wheel = (SKSpriteNode *)[self childNodeWithName:@"wheel"];
CGFloat circumference = wheel.size.height * M_PI;
 
SKAction *oneRevolution = [SKAction rotateByAngle:-M_PI*2 duration:2.0];
SKAction *moveRight = [SKAction moveByX:circumference y:0 duration:2.0];
 
SKAction *group = [SKAction group:@[oneRevolution, moveRight]]; [wheel runAction:group];

Несмотря на то, что действия в группе запускаются одновременно, группа не завершается, пока последнее действие в группе не закончило работать. Перечисление 3-6 показывает более сложную группу, включающую действия с различными значениями синхронизации. Спрайт анимирует через его текстуры и перемещает экран вниз сроком на две секунды. Однако в течение первой секунды, спрайт увеличивает масштаб и изменяется от полной прозрачности до существенного появления. Рисунок 3-2 показывает, что два действия, заставляющие спрайт появиться конец на полпути посредством анимации группы. Группа продолжает до других двух завершенных действий.

Перечисление 3-6  , Создающее группу действий с различными значениями синхронизации

[sprite setScale: 0];
SKAction *animate = [SKAction animateWithTextures:textures timePerFrame:2.0/numberOfTextures];
SKAction *moveDown = [SKAction moveByX:0 y:-200 duration:2.0];
SKAction *scale = [SKAction scaleTo:1.0 duration:1.0];
SKAction *fadeIn = [SKAction fadeInWithDuration: 1.0];
 
SKAction *group = [SKAction group:@[animate, moveDown, scale, fadeIn]];
[sprite runAction:group];
Рисунок 3-2  Сгруппированные действия запускаются одновременно, но завершаются независимо

Повторяющиеся действия выполняют другое действие многократно

Повторяющееся действие циклично выполняет другое действие так, чтобы это повторилось многократно. Когда повторяющееся действие выполняется, оно выполняет свое содержавшее действие. Каждый раз, когда циклично выполненное действие завершается, оно перезапущено повторяющимся действием. Перечисление 3-7 показывает, что методы создания раньше создавали повторяющиеся действия. Можно создать действие, повторяющее действие конечное число времен или действия, повторяющего действие неопределенно.

  Действия повторения Создания перечисления 3-7

SKAction *fadeOut = [SKAction fadeOutWithDuration: 1];
SKAction *fadeIn = [SKAction fadeInWithDuration: 1];
SKAction *pulse = [SKAction sequence:@[fadeOut,fadeIn]];
 
SKAction *pulseThreeTimes = [SKAction repeatAction:pulse count:3];
SKAction *pulseForever = [SKAction repeatActionForever:pulse];

Рисунок 3-3 показывает расположение синхронизации относительно pulseThreeTimes действие. Вы видите, что последовательность заканчивается, затем повторяется.

  Синхронизация рисунка 3-3 для повторяющегося действия

Когда Вы повторяете группу, вся группа должна закончить, прежде чем группа перезапущена. Перечисление 3-8 создает группу, перемещающую спрайт и анимирующую его текстуры, но в этом примере эти два действия имеют различные продолжительности. Когда группа повторяется, рисунок 3-4 показывает временную диаграмму. Вы видите, что выполнения анимации текстуры к завершению и затем никакой анимации происходят до повторений группы.

Перечисление 3-8  , Повторяющее анимацию группы

SKAction *animate = [SKAction animateWithTextures:textures timePerFrame:1.0/numberOfImages];
SKAction *moveDown = [SKAction moveByX:0 y:-200 duration:2.0];
 
SKAction *group = [SKAction group:@[animate, moveDown]];
  Синхронизация рисунка 3-4 для повторной группы

То, что Вы, возможно, хотели, было для каждого действия для повторения в его собственной собственной частоте. Чтобы сделать это, создайте ряд повторяющихся действий и затем соберите в группу их. Перечисление 3-9 показывает, как Вы реализовали бы синхронизацию, показанную на рисунке 3-5.

Перечисление 3-9  , Группирующее ряд повторных действий

SKAction *animate = [SKAction animateWithTextures:textures timePerFrame:1.0/numberOfImages];
SKAction *moveDown = [SKAction moveByX:0 y:-200 duration:2.0];
 
SKAction *repeatAnimation = [SKAction repeatActionForever:animate];
SKAction *repeatMove = [SKAction repeatActionForever:moveDown];
 
SKAction *group = [SKAction group:@[repeatAnimation, repeatMove]];
Рисунок 3-5  Каждое действие повторяется в его естественном интервале

Конфигурирование синхронизации действия

По умолчанию действие с продолжительностью применяет свои изменения линейно по продолжительности, которую Вы указали. Однако можно скорректировать синхронизацию анимаций через несколько свойств:

Набор Sprite устанавливает курс, на котором анимация применяется путем нахождения всех уровней, применяющихся к действию и умножению их.

Подсказки для работы с действиями

Действия работают лучше всего, когда Вы создаете их один раз и используете их многократно. Каждый раз, когда возможно, действия по созданию рано и сохраняют их в расположении, где они могут быть легко получены и выполнены.

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

При необходимости во вводе разработчика или художника о том, как свойства узла анимированы, рассматривают перемещение кода создания действия в инструменты индивидуального проекта. Тогда заархивируйте действие и загрузите его в Вашем игровом механизме. Для получения дополнительной информации посмотрите Методы наиболее успешной практики Набора Sprite.

Когда Вы не должны использовать действия

Несмотря на то, что действия эффективны, существует стоимость для создания и выполнения их. Если Вы вносите изменения в свойства узла в каждом кадре анимации, и те изменения должны быть повторно вычислены в каждом кадре, Вы - более обеспеченное внесение изменений в узел непосредственно и не использование действий, чтобы сделать так. Для получения дополнительной информации о том, где Вы могли бы сделать это в своей игре, видеть, что Усовершенствованная Сцена Обрабатывает.

Попробуйте это!

Вот некоторые вещи попробовать действиями: