cocos2dx学习之路----第十章(Node节点生命周期详解)

这一篇我们就来看看Node节点的生命周期问题。

对于Node节点的生命周期,也称回调事件的回调。当对节点进行操作时,比如被添加或者移除,它默认都会调用自己的一些事件方法。现在就让我们看看属于它事件的回调方法有哪些,如下所示:

virtual void onEnter();				//被添加到场景中的节点时调用
virtual void onEnterTransitionDidFinish();	//被添加到场景中的节点完成时调用
virtual void onExitTransitionDidStart();	//开始从场景中的节点移除时调用
virtual void onExit();				//从场景中的节点移除完成后调用
virtual void cleanup();				//停止在场景中运行的所有节点状态
以上就是节点的生命周期回调函数。

好,现在让我们来看看这次要如何来测试它。

既然基本的显示类都与节点相关,我又用了LayerColor类来进行测试(不要问我为什么每次测试例子都有LayerColor这个类,哈哈,只是因为我觉得它比较适合和直观,关键的一点就是其实它可以代替精灵的显示从而避免了纹理的使用~不多说了哈,继续继续~)

然后既然是添加与移除,所以我就用了场景的切换来做这次的测试。至于如何能够看得出切换时的状态,其实一开始我是想用一个打印日志的方法来检测节点的状态的,不过好像效果不是很明显,并且没有分割线,在切换的时候可能状态一下字就一大堆,与上一次的状态输出可能混淆了,所以我就选用了微软的一个函数接口MessageBox。这个可以弹出一个小窗口出来,很方便。然后有两个参数,第一个是窗口内容,第二个是窗口的标题。嗯嗯,那现在就来看看测试的内容吧~

第一个测试:进入场景,初始化层并添加,对层的生命周期回调函数进行重写并检测它。我们先看下效果:


通过测试1,我们可以看到Layer1的生命周期回调的方法如下:

进入例子中的Layer1创建的场景:Layer1:init --> Layer1:onEnter --> Layer1:onEnterDidFinish

关闭Layer1场景当前应用程序:Layer1:onExit --> Layer1:cleanup

好,我们再来看看测试2:


测试2中有两个场景,Layer1和Layer2层所创建的场景,这里进行场景的切换来对Layer1和Layer2生命周期回调函数的情况进行检查。我们知道,切换场景有两种方式,一种是通过导演类单例调用replaceScene()方法进行切换,另外一种是通过导演类调用pushScene()和popScene()来进行切换。这两种方式的区别就是在切换完成时上一个场景的资源是否有被释放。所以,测试3也是进行场景切换的方法进行测试,切换的方式用了第二种。

好,再回过头来说说这个测试2中的问题,这里用了replaceScene的切换方式进行测试,由上面可以分析出它们所回调的过程:

进入Layer1:

Layer1:init->Layer1:onEnter->Layer1:onEnterTransitionDidFinish

进入Layer2:

Layer2:init->Layer1:onExitTransitionDidStart->Layer1:onExit-> Layer1:cleanup->Layer2:onEnter->Layer2:onEnterTransitionDidFinish

重新进入Layer1:

Layer1:init->Layer2:onExitTransitionDidStart->Layer2:onExit->Layer2:cleanup->Layer1:onEnter->Layer1:onEnterTransitionDidFinish

退出应用程序:

Layer1:onEix->Layer1:cleanup


最后在来看下第三个测试:


测试3这里通过pushScene()及popScene()来进行测试,就直接看看它们回调的过程吧:

进入Layer1:

Layer1:init->Layer1:onEnter->Layer1:onEnterTransitionDidFinish

进入Layer2:

Layer2:init->Layer1:onExitTransitionDidStart->Layer1:onExit->Layer2:onEnter->Layer2:onEnterDidFinish

重新进入Layer1:

Layer2:onExitTransitionStart->Layer2:onExit->Layer2:cleanup->Layer1:onEnter->Layer1:onEnterTransitionDidFinish

退出应用程序:

Layer1:onEix->Layer1:cleanup


好了,以上就是对节点生命周期回调函数的重写及测试。下面就直接贴出这里测试的源码吧:

NodeLifeCircleTest.h:

#ifndef __NODE_LIFE_CIRCLE_TEST__
#define __NODE_LIFE_CIRCLE_TEST__

#include"cocos2d.h"

USING_NS_CC;

class TestLayer1 :public LayerColor
{
public:
	static Scene *createScene();
	virtual bool init();
	CREATE_FUNC(TestLayer1);

	//生命周期事件回调重写
	virtual void onEnter();						//被添加到场景中的节点时调用
	virtual void onEnterTransitionDidFinish();	//被添加到场景中的节点完成时调用
	virtual void onExitTransitionDidStart();	//开始从场景中的节点移除时调用
	virtual void onExit();						//从场景中的节点移除完成后调用
	virtual void cleanup();						//停止在场景中运行的所有节点状态

};

class TestLayer2 :public LayerColor
{
public:
	static Scene *createScene();
	virtual bool init();
	CREATE_FUNC(TestLayer2);

	//生命周期事件回调重写
	virtual void onEnter();
	virtual void onEnterTransitionDidFinish();
	virtual void onExit();
	virtual void onExitTransitionDidStart();
	virtual void cleanup();
};
#endif
NodeLifeCircleTest.cpp:

#include"NodeLifeCircleTest.h"

/**********************************************
*****说明:LayerColor1相关函数定义
************************************************/
Scene *TestLayer1::createScene(){
	auto scene = Scene::create();
	auto layer = TestLayer1::create();
	scene->addChild(layer);

	return scene;
}
bool TestLayer1::init(){
	if (!LayerColor::initWithColor(Color4B::GREEN)){
		return false;
	}

	MessageBox("init...", "TestLayer1");

	auto visibleSize = Director::getInstance()->getVisibleSize();

	//当前测试标签描述
	auto test_label = Label::createWithSystemFont("Node Life Circle Test", "", 30);
	test_label->setPosition(Vec2(visibleSize.width / 2, visibleSize.height - test_label->getContentSize().height));
	this->addChild(test_label);

	//跳转菜单
	auto EnterMenuItem1 = MenuItemLabel::create(
		Label::createWithSystemFont("This is Layer1 \nClick Here Enter Layer Two...", "", 25),
		[](Ref *r){
		Director::getInstance()->replaceScene(TestLayer2::createScene());
		//Director::getInstance()->pushScene(TestLayer2::createScene());
	});
	auto EnterLayer2 = Menu::create(EnterMenuItem1, NULL);
	this->addChild(EnterLayer2);


	return true;
}
//TestLayer1生命周期事件回调重写
void TestLayer1::onEnter(){
	//调用父类
	LayerColor::onEnter();
	CCLOG("TestLayer1 onEnter...");

	MessageBox("onEnter...", "TestLayer1");

}
void TestLayer1::onEnterTransitionDidFinish(){
	//调用父类
	LayerColor::onEnterTransitionDidFinish();
	CCLOG("TestLayer1 onEnterTransitionDidFinish...");

	MessageBox("onEnterTransitionDidFinish...", "TestLayer1");

}
void TestLayer1::onExit(){
	//调用父类
	LayerColor::onExit();
	CCLOG("TestLayer1 onExit...");

	MessageBox("onExit...", "TestLayer1");

}
void TestLayer1::onExitTransitionDidStart(){
	//调用父类
	LayerColor::onExitTransitionDidStart();
	CCLOG("TestLayer1 onExitTransitionDidStart...");

	MessageBox("onExitTransitionDidStart...", "TestLayer1");

}
void TestLayer1::cleanup(){
	//调用父类
	LayerColor::cleanup();
	CCLOG("TestLayer1 cleanup...");

	MessageBox("cleanup...", "TestLayer1");

}

/**********************************************
*****说明:LayerColor2相关函数定义
************************************************/
Scene *TestLayer2::createScene(){
	auto scene = Scene::create();
	auto layer = TestLayer2::create();
	scene->addChild(layer);

	return scene;
}
bool TestLayer2::init(){
	if (!LayerColor::initWithColor(Color4B::RED)){
		return false;
	}

	MessageBox("init...", "TestLayer2");

	auto visibleSize = Director::getInstance()->getVisibleSize();

	//当前测试标签描述
	auto test_label = Label::createWithSystemFont("Node Life Circle Test", "", 30);
	test_label->setPosition(Vec2(visibleSize.width / 2, visibleSize.height - test_label->getContentSize().height));
	this->addChild(test_label);

	//跳转菜单
	auto EnterMenuItem2 = MenuItemLabel::create(
		Label::createWithSystemFont("This is Layer2 \nClick Here Enter Layer One...", "", 25),
		[](Ref *r){
		Director::getInstance()->replaceScene(TestLayer1::createScene());
		//Director::getInstance()->popScene();
		});
	auto EnterLayer1 = Menu::create(EnterMenuItem2, NULL);
	this->addChild(EnterLayer1);

	return true;
}

//TestLayer2生命周期事件回调重写
void TestLayer2::onEnter(){
	//调用父类
	LayerColor::onEnter();
	CCLOG("TestLayer2 onEnter...");

	MessageBox("onEnter...", "TestLayer2");

}
void TestLayer2::onEnterTransitionDidFinish(){
	//调用父类
	LayerColor::onEnterTransitionDidFinish();
	CCLOG("TestLayer2 onEnterTransitionDidFinish...");

	MessageBox("onEnterTransitionDidFinish...", "TestLayer2");

}
void TestLayer2::onExit(){
	//调用父类
	LayerColor::onExit();
	CCLOG("TestLayer2 onExit...");

	MessageBox("onExit...", "TestLayer2");

}
void TestLayer2::onExitTransitionDidStart(){
	//调用父类
	LayerColor::onExitTransitionDidStart();
	CCLOG("TestLayer2 onExitTransitionDidStart...");

	MessageBox("onExitTransitionDidStart...", "TestLayer2");

}
void TestLayer2::cleanup(){
	//调用父类
	LayerColor::cleanup();
	CCLOG("TestLayer2 cleanup...");

	MessageBox("cleanup...", "TestLayer2");

}


好了,如果有什么不明白的自己多运行测试一下理解理解。对于节点的生命周期问题如果能够理解还是对以后开发很有帮助的。比如游戏进入场景时就播放声音,游戏结束切换界面时对声音处理的时候应该适合在哪个回调函数进行声音播放的添加或停止,这是个很值得思考的问题。如果理解了这个,相信你心中也有了底了哈~既然说到声音,那下一篇也来聊聊这个声音的加载播放问题哈~大笑





你可能感兴趣的:(cocos2dx学习之路----第十章(Node节点生命周期详解))