понедельник, 7 января 2013 г.

Основы. Статья 2. Использование CCNode

Основы cocos2d. Статья 2. Использование CCNode

В этой статья мы поговорим о классе, который является основой всех узлов - классе CCNode.
Он никак не отображается на экране, но задает набор методов и свойств, общий для всех узлов.

CCNode

Класс CCNode определяет все необходимые для добавления, получения и удаления дочерних узлов методы.
Вы можете:
  • создать новый узел, используя вызов CCNode* myNode = [CCNode node];
  • добавить созданный узел в другой узел: [someNode addChild:myNode z:0 tag:123]; (про параметр z обозначает, каким по порядку будет нарисован узел (чем меньше z, тем первее будет нарисован), а параметр tag - это некоторое уникальное число, которым вы обозначаете добавляемый узел, чтобы его потом можно было получить. Важно, что tag должен быть уникален, поскольку если вы добавите несколько узлов с одинаковыми тэгами, то получить вы сможете только первый добавленный с этим тэгом узел - остальные будут недоступны)
  • получить один из дочерних узлов: CCNode *myNode = [someNode getChildByTag:123];
  • удалить дочерний узел, используя его тэг: [someNode removeChildByTag:123 cleanup:YES]; - параметр cleanup, если ему передать YES, обозначает остановку всех текущих действий
  • можно удалить дочерний узел, используя его указатель: [someNode removeChild:myNode];
  • или удалить все дочерние узлы разом: [someNode removeAllChildrenWithCleanup:YES];
  • или удалить узел из его родительского элемента: [myNode removeFromParentAndCleanup:YES];

Действия (CCAction)

Что такое действие?
О действиях мы поговорим позже, пока что достаточно знать, что действие - это некоторая трансформация, применимая к узлу (например, вращение, масштабирование или передвижение).
Давайте рассмотрим пример действия.
  • Мигание создается, например, таким образом: CCAction *action = [CCBlink actionWithDuration:10 blinks:20]; action.tag = 123;
  • Для того, чтобы узел помигал, мы должны запустить это действие: [myNode runAction:action];
  • Выше мы присвоили нашему действию тэг 123. В дальнейшем мы можем получать наше действие из нашего узла: CCAction *blinkAction = [myNode getActionByTag:123]; - кстати, тэги для дочерних узлов и тэги для действий могут быть одинаковыми.
  • Действие можно остановить, используя тэг: [myNode stopActionByTag:123];
  • или остановить, используя указатель: [myNode stopAction:action];
  • или остановить все действия, которые происходят на этом узле: [myNode stopAllActions];

Вызовы методов по расписанию

В CCNode есть простой способ вызывать метод на каждом кадре - достаточно вызвать [self scheduleUpdate]; - и тогда каждый кадр будет вызываться метод CCNode -(void)update:(ccTime)delta, который можно переписать, унаследовавшись от CCNode.
delta - это количество времени с прошлого вызова метода.

Если вы хотите вызывать другой метод вашего класса и с другим интервалом, можно использовать синтаксис:
[self schedule:@selector(myUpdateMethod:) interval:0.1f];
В таком случае, будет вызван метод вашего класса, который вы передадите через селектор (если не знаете, что такое селектор - прошу в гугл или в комменты, могу пояснить), а интервал - это временной интервал в секундах. 
В нашем случае, у нас будет вызван метод
-(void)myUpdateMethod:(ccTime)delta
{
//наш код
}

Важно помнить, что, поскольку мы используем селекторы, компилятор соберет программу, даже если метода, на который ссылается селектор, нет - правда, она упадет, как только будет обращение к этому методу.
Чтобы получить предупреждение от компилятора на этапе компиляции, можно открыть настройки проекта, вкладка Build Settings, и в разделе LLVM GCC Warnings установить в YES значение для строки Undeclared Selector.

Для того, чтобы отменить все запланированные вызовы, можно использовать вызов 
[self unscheduleAllSelectors]; или остановить конкретный, используя его селектор: 
[self unschedule:@selector(myUpdateMethod:)];

Вы можете отменить конкретное запланированное действие, находясь в нем, используя простой код:
[self unschedule:_cmd]; 
_cmd - это скрытая переменная Objective-C, обозначающая селектор текущего вызова (круто, а?).
Аналогично, используя _cmd, можно не отменять, а добавлять текущее действие в расписание.

Последний момент, который стоит здесь отметить - это приоритеты вызовов update для разных узлов.

Скажем, есть несколько узлов, добавляющих вызов update по расписанию:
// in Node A
-(void) scheduleUpdates {

[self scheduleUpdate]; }
// in Node B
-(void) scheduleUpdates {

[self scheduleUpdateWithPriority:1]; }
// in Node C
-(void) scheduleUpdates {

[self scheduleUpdateWithPriority:-1]; } 

В этом случае, сначала метод update вызывается для узла С, затем для узла А (по умолчанию - приоритет 0), затем для узла Б.
То есть, по сути, чем ниже число, тем первее вызывается апдейт для узла.
Это далеко не всегда нужно, но есть ситуации, в которых важно, чтобы обновление узлов шло в строгом порядке.

На этом я заканчиваю статью - как видите, в этот раз у нас было много полезной практической информации. А дальше будет еще больше ;)



Иллюстрации и примеры кода взяты из книги Learn cocos2d Game Development with iOS 5.
Посетите также блог автора книги ("Learn Cocos2d", Steffen Itterheim)

2 комментария:

  1. Как понял это просто зарезервированное слово, после которого идет имя вызываемого метода.

    ОтветитьУдалить