• 我的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。
        bool HelloWorld::init()中是我们编写程序的主要地方,因为Cocos2d-x中有许多类不使用构造函数进行初始化,所以在HelloWorld::init()中首先调用了其父类的init()函数进行初始化,以防错误发生;如果父类init()产生错误,返回false,之后运行一系列我们自定义的函数后,返回true。


        其实static CCScene* scene()在需要返回场景时候类中可以添加,不需要返回场景时候可以不添加,具体如何看实际情况。

  • 相关阅读:
    浅谈数组
    前端冷知识
    number框
    jQuery封装轮播图插件
    瀑布流的简单制作
    Java script-数组与字符串方法
    Java script-1
    Web前端基础学习-2
    Web前端基础学习-3
    Web前端基础学习-1
  • 原文地址:https://www.cnblogs.com/gongyan/p/4539410.html
Copyright © 2020-2023  润新知