Cocos2d-x использует модель распределения памяти как двухэтапный процесс, как и target-c. Каждому объекту выделяется память (обычно с помощью метода «создать»), а затем инициализируется его состояние (обычно с помощью метода, называемого «инициализация»). Таким образом, в методах create/init вы выделяете память и выполняете любую инициализацию объекта, необходимую для его запуска.
Когда объект начинает выводиться на дисплей или когда он добавляется в другой контейнер, вызывается его метод onEnter. Это вызывается, когда CCScene/CCLayer (любой из которых может содержать ваш производный объект CCNode) отображается самой структурой.
Существует по крайней мере 2 шаблона для выделения памяти и создания объектов, я склонен следовать шаблону, когда класс содержит статический фабричный метод и частный конструктор, поэтому однозначно, что вы должны создавать объекты через фабрику и не можете создать один сами.
Например, сейчас я работаю над этим классом «кнопки»:
class ActionButton;
class ActionButtonTarget
{
public:
virtual void ActionButtonActivated(ActionButton* button) = 0;
};
class ActionButton : public CCNode, public CCTargetedTouchDelegate
{
private:
ActionButton();
CCNode* _node; // Weak Reference
CCRect _testRect;
ActionButtonTarget* _target;
bool init(ActionButtonTarget* target, CCNode* node, CCRect rect);
bool IsTouchInside(CCTouch* touch);
void NotifyTarget();
protected:
virtual CCAction* CreateAction();
public:
virtual ~ActionButton();
// The class registers/unregisters on entry
// or exit of the layer. This
virtual void onEnterTransitionDidFinish();
virtual void onExitTransitionDidStart();
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
static ActionButton* create(ActionButtonTarget* target, CCNode* node, CCRect rect);
};
Обратите внимание, что метод «создать» — единственный способ создать его. В этом случае он принимает аргументы для параметров кнопки. Другие объекты, производные от CCNode (например, CCScene), обычно этого не делают.
Внутри:
ActionButton::ActionButton()
{
}
ActionButton::~ActionButton()
{
}
// The class registers/unregisters on entry
// or exit of the layer. This
void ActionButton::onEnterTransitionDidFinish()
{
CCNode::onEnterTransitionDidFinish();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
void ActionButton::onExitTransitionDidStart()
{
CCNode::onExitTransitionDidStart();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool ActionButton::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
if(IsTouchInside(pTouch))
{
return true;
}
return false;
}
void ActionButton::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
// Nothing to do here.
}
void ActionButton::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
NotifyTarget();
}
bool ActionButton::IsTouchInside(CCTouch* touch)
{
CCPoint point = touch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
return _testRect.containsPoint(point);
}
void ActionButton::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
{
_target->ActionButtonActivated(this);
}
ActionButton* ActionButton::create(ActionButtonTarget* target, CCNode* node, CCRect rect)
{
ActionButton *pRet = new ActionButton();
if (pRet && pRet->init(target,node,rect))
{
pRet->autorelease();
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
return NULL;
}
}
CCAction* ActionButton::CreateAction()
{
return NULL;
}
void ActionButton::NotifyTarget()
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(Constants::SOUND_EFFECT_BUTTON_CLICK());
_target->ActionButtonActivated(this);
}
bool ActionButton::init(ActionButtonTarget* target, CCNode* node, CCRect rect)
{
assert(target != NULL);
assert(node != NULL);
assert(dynamic_cast<ActionButtonTarget*>(target) != NULL);
_target = target;
_node = node;
_testRect = rect;
addChild(_node);
return true;
}
Обратите внимание, что методы OnEnterXXX и onExitXXX вызывают метод родительского класса. ВЫ ДОЛЖНЫ СДЕЛАТЬ ЭТО, иначе это не сработает должным образом.
Этот класс представляет собой кнопку, которая запускает действие на узле (возможно, заставляет его увеличиваться/уменьшаться, чтобы указать, что он был нажат). Он принимает прикосновения от пользователя. Я не могу добавить его в сенсорный менеджер до того, как он выйдет на сцену. Поэтому я использую метод onEnterTransitionDidFinish, чтобы добавить его, а также использую метод onExitTransitionDidStart, чтобы удалить его, чтобы он не продолжал получать касания после удаления сцены. Я не знаю, будет ли контейнер уничтожен или нет, поэтому я должен удалить его, когда кнопка покинет дисплей.
Было ли это полезно?
person
FuzzyBunnySlippers
schedule
25.12.2013