CCLayer :: init()和CCLayer :: onEnter()之间的区别?

ein*_*rne 2 cclayer cocos2d-x

这是关于CCNode :: init()和CCNode :: onEnter()之间差异的主题.但是我遵循他们给出的建议.

void MyLayer::onEnter() {
    CCLayer::onEnter();
    //your code goes here
}
Run Code Online (Sandbox Code Playgroud)

我收到了Assertion failed!错误!
MyLayer代码:

class MyLayer : public CCLayerColor
Run Code Online (Sandbox Code Playgroud)

我应该添加CCLayerColor::onEnter()我的MyLayer::onEnter()代码吗?和之间有什么区别CCLayer::init()CCLayer::onEnter().我init()应该将哪部分代码放入哪部分应该放入哪部分onEnter()

Fuz*_*ers 5

Cocos2d-x的内存分配模型分为两步,就像objective-c一样.每个对象都分配了内存(通常使用"create"方法),然后初始化其状态(通常使用名为"init"的方法).因此,在create/init方法中,您可以分配内存并执行运行所需的任何对象初始化.

当对象开始放在显示器上,或者当它被添加到另一个容器时,它的"onEnter"方法被调用.当框架本身显示CCScene/CCLayer(其中任何一个可能包含您的CCNode派生对象)时,将调用此方法.

内存分配和对象创建至少有两种模式,我倾向于遵循一个类包含一个静态工厂方法和一个私有构造函数的模式,这样你就必须通过工厂创建对象而不能创建一个你自己.

例如,我目前正在处理这个"按钮"类:

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);
};
Run Code Online (Sandbox Code Playgroud)

请注意,"create"方法是创建它的唯一方法.在这种情况下,它接受按钮参数的参数.其他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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,OnEnterXXX和onExitXXX方法调用父类方法. 您必须这样做,否则它将无法按预期工作.

这个类是一个按钮,它将在节点上运行一个动作(可能使它增长/缩小以指示它被按下).它需要用户的触摸.我无法在进入场景之前将其添加到触摸管理器.所以我使用onEnterTransitionDidFinish方法添加它,并使用onExitTransitionDidStart删除它,以便在删除场景后不会继续接收触摸.我不知道容器是否会被销毁,所以我必须在按钮退出显示器时将其移除.

这个有帮助吗?

  • 嗯......我不能肯定地说......但我想我可能知道发生了什么......我在cocos2d-x(v2.105)中找到了一个位置,如果它是目标触摸处理程序将抛出一个断言添加两次(而不仅仅是返回,它在断言后执行).当您向容器添加一个按钮(如上所示)时,将在其上调用onEnter.如果你在onEnter中执行此操作,它将被调用两次并断言.这是你看到的吗? (2认同)