Основы cocos2d. Статья 2. Использование 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), затем для узла Б.
То есть, по сути, чем ниже число, тем первее вызывается апдейт для узла.
Это далеко не всегда нужно, но есть ситуации, в которых важно, чтобы обновление узлов шло в строгом порядке.
На этом я заканчиваю статью - как видите, в этот раз у нас было много полезной практической информации. А дальше будет еще больше ;)
-(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)
Что такое селектор?
ОтветитьУдалитьКак понял это просто зарезервированное слово, после которого идет имя вызываемого метода.
ОтветитьУдалить