我的Cocos2d-x学习笔记(三)游戏逻辑架构与HelloWorld分析
先来看看Cocos2d-x中关于游戏的一些基础概念,首先盗用官网的图描述一下游戏中各个游戏对象的关系。
从上图中可以知道在Cocos2d-x中只存在一个导演,而事实上之前我们也看到CCDirector是一个单例对象;而游戏中可以存在多个场景,图中存在N个场景;每个场景中又可以存在多个层;每个层中又可以包含多个精灵。 一个导演同一时间只能运行一个场景,一个场景当中,可以同时加载多个层,一个层同可以可载多个精灵。层中亦可以加层。 其实CCScen、CCLayer与CCSprite都直接或间接派生自CCNode;CCNode是与渲染有关的基类,定义了一些用于显示子类的方法,之后再详细介绍它。 导演(CCDirector): Cocos2d-x中统筹游戏大局的类,游戏中一些常用的的操作就是由CCDirector来控制,在游戏中是单例对象,项目中没错获取的CCDirector都是同一个对象。例如:OpenGL ES的初始化,场景的转换,游戏的暂停与继续控制,世界坐标与GL坐标的转换,对游戏节点的控制等都是CCDirector控制。 场景(CCScene): 场景的基础关系:class CC_DLL CCScene : public CCNode。 场景是游戏当中相对来说不变的一个游戏元素,由场景来承载层与精灵,一些层与精灵表现出的游戏内容存放在一个场景中,往往场景切换对应着关卡切换。其重要的作用就是进行流程控制。 在CCDirector中有关CCScene的函数有如下几种,截取类中一部分代码如下: class CC_DLL CCDirector : public CCObject,public TypeInfo { public: void runWithScene(CCScene *pScene); void pushScene(CCScene *pScene); void popScene(void); void replaceScene(CCScene *pScene); void end(void); void pause(void); void resume(void); }void runWithScene(CCScene *pScene):这个函数在启动游戏时候调用,运行场景pScene。AppDelegate.cpp中曾经调用过,其实这个函数是第一次执行主场景时候调用。如果已有正在运行的场景则不能调用该方法。 void pushScene(CCScene *pScene):将当前运行中的场景暂停并压入到代码执行场景栈中,再将传入的pScene设置为当前运行场景,只有存在正在运行的场景时才调用该方法。 void popScene(void);:释放当前场景,再从代码执行场景中弹出栈顶的场景,并将其设置为当前运行场景。如果栈为空,直接结束应用。和PushScene结对使用。 void replaceScene(CCScene *pScene);:直接使用传入的pScene替换当前场景来切换画面,当前场景被释放。这是切换场景时最常用的方法。 void pause(void);:暂停当前运行场景中的所有计时器和动作,场景仍然会显示在屏幕上。 void resume(void): 恢复当前运行场景的所有计时器和动作,场景仍然会显示在屏幕上。 void end(void):释放和终止执行场景,同时退出应用。 场景切换用到的代码如下: CCScene* pScene = TestLayer::scene(); CCDirector::sharedDirector()->pushScene(pScene); CCDirector::sharedDirector()->popScene(); CCDirector::sharedDirector()->replaceScene(pScene);其中我们要知道的是CCScene* pScene = TestLayer::scene();返回的是一个场景指针,执行之后的代码便可进行场景入栈,出栈和场景替换了,当然不能在同一代码库中同时运行。 层(CCLayer): 层的继承关系:class CC_DLL CCLayer : public CCNode,public CCTouchDelegate,public CCAccelerometerDelegate,public CCKeypadDelegate。 由层的继承关系可以看出,层可以接受触摸、加速度计、键盘输入。 层包含显示在屏幕上的内容,多个层可以组成复杂的场景。 层可以包含任何Node作为子节点,包括CCSprites(精灵),,Labels(标签),甚至其他的Layer对象。 要向场景添加层,我们可以使用addChild方法。 addChild方法是继承自CCNode中,只要CCNode的子类,都存在addChild()方法,并且可以利用此方法把节点添加到另一个节点上去,在CCNode中定义如下: class CC_DLL CCNode : public CCObject { public: virtual void addChild(CCNode * child); virtual void addChild(CCNode * child,int zOrder); virtual void addChild(CCNode* child,int zOrder,int tag); }其中,child参数就是节点。先添加的节点会被置于后添加的节点之下。可以使用不同的zOrder值指定先后顺序,zOrder值越大离屏幕越近,越不容易被覆盖。tag是节点的标识号码,如果为子节点设置了tag值,就可以在它的父节点中利用tag值就可以找到它了。 精灵(CCSprite): 精灵的继承关系:class CC_DLL CCSprite : public CCNodeRGBA,public CCTextureProtocol。
导演、场景、层、精灵暂且学习到这里,下面看看HelloWorld中的一些内容。此HelloWorld为精简化的,HelloWorld头文件内容如下: #ifndef __HelloWorld_H__ #define __HelloWorld_H__ #include "cocos2d.h" USING_NS_CC; class HelloWorld:public CCLayer { public: static CCScene* scene(); CREATE_FUNC(HelloWorld); bool init(); }; #endif其中先来看看CREATE_FUNC: #define CREATE_FUNC(__TYPE__) static __TYPE__* create() { __TYPE__ *pRet = new __TYPE__(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } }由此可知CREATE_FUNC是一个宏,这个宏预处理后在程序中添加了一个静态create()函数。把HelloWorld中的进一步翻译后的到如下代码,当我们需要包含参数的create函数的时候,就必须自己仿照下面代码来写这个create函数了。 static HelloWorld* create() { HelloWorld *pRet = new HelloWorld(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } }再来看看static CCScene* scene()函数与bool init()函数,这两个函数在HelloWorld.cpp中定义: #include "HelloWorld.h" CCScene* HelloWorld::scene() { CCScene* scene = CCScene::create(); HelloWorld* layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { if (!CCLayer::init())return false; return true; } static CCScene* scene()中首先创建了一个场景对象保存了指向它的指针,利用CCScene中的create()函数;然后用HelloWorld中的create()函数创建了一个HelloWorld对象并保存了指向它的指针,此时用到的create()函数就是之前CREATE_FUNC替换后的函数;之后通过addChild把HelloWorld对象添加到场景对象scene中;最后返回场景对象指针scene。 其实static CCScene* scene()在需要返回场景时候类中可以添加,不需要返回场景时候可以不添加,具体如何看实际情况。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |