以下是Difference between CCNode::init() and CCNode::onEnter()的主题。但是我按照他们给出的advice。
void MyLayer::onEnter() {
CCLayer::onEnter();
//your code goes here
}
我收到Assertion failed!
错误!
MyLayer代码:
class MyLayer : public CCLayerColor
我应该在CCLayerColor::onEnter()
代码中添加MyLayer::onEnter()
吗? CCLayer::init()
和CCLayer::onEnter()
之间有什么区别?我应该将哪部分代码放入init()
以及哪部分放入onEnter()
?
答案 0 :(得分: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);
};
请注意,“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;
}
注意OnEnterXXX和onExitXXX方法调用父类方法。 你必须这样做,否则它将无法正常工作。
这个类是一个按钮,它将在节点上运行一个动作(可能使它增长/缩小以表示它被按下)。它需要用户的触摸。我无法在进入场景之前将其添加到触摸管理器。因此,我使用onEnterTransitionDidFinish方法添加它,并使用onExitTransitionDidStart删除它,以便在删除场景后不会继续接收触摸。我不知道容器是否会被销毁,所以我必须在按钮退出显示器时将其移除。
这有用吗?
答案 1 :(得分:3)
Ist Part
查看基类的OnEnter方法(CCLayer),如果发生了一些严重的事情,那么你应该调用它。
IInd Part
在主题中......在初始化期间“viewDidAppear”和init时调用OnEnter。
假设您通过此
创建图层MyLayer *newLayer=MyLayer::create(); //...init is called before OnEnter..
之后,将其添加到某个场景
X->addChild(newLayer); // ...*Now onEnter Method is called
* X必须添加到某个场景或父级,依此类推。
第三部分
在某些情况下,您只需创建存储在数组中的多个对象,但不添加它们。您正在等待添加它们的正确时间。当对象进入/添加到屏幕时,您可能希望它执行特定任务。
实施例。在一个游戏中你必须攻击某人并拥有30名士兵。所有部队都是在装载场景中创建的,但没有一个增加到图层。 战斗开始时,用户部署的部队出现在屏幕上。进入后面有一个任务要进入目标建筑,可以通过onEnter调用该方法。
答案 2 :(得分:2)
如果您想在屏幕上显示的某个时刻做某事,请调用onEnter()。 即使屏幕上没有图层,也会调用init()方法。 像这样:
void FirstScene::methodInit()
{
customlayer = new CustomLayer();
customlayer -> init();
customlayer-> retain();
// At this point,customlayer (which is a CustomLayer object that is a subclass of CCLayer)
// is still not on the screen, hence, CustomLayer::onEnter() is still not called
}
void FirstScene::methodEnter
{
this -> addChild( customLayer, customIndex, customTag );
customLayer -> release();
// At this point, CustomLayer::onEnter() is called, because customLayer is being rendered
}