• 【Cocos2d-X开发学习笔记】第05期:渲染框架之布景层类(CCLayer)的使用


    本系列学习教程使用的是cocos2d-x-2.1.4版本(截至目前为止最新稳定版) ,PC开发环境Windows7,C++开发环境VS2010        

            

            图层也是渲染框架中很重要的内容。场景类用来划分游戏的状态,图层就用来划分游戏画面。通常图层的尺寸

    与屏幕的尺寸一致。它将会覆盖整个显示名目。所以所图层几乎包含了所有游戏内容。相比场景类,它为玩家呈现

    了丰富的游戏画面。每个游戏场景中可以有很多层,每一层负责各自的任务,如专门负责显示地图的背景、专门负责

    显示敌人、专门负责机关和专门负责主角等;每一层上可以放置不同的元素,包括文本、精灵图片和菜单等。通过层

    与层之间的组合关系就可以构成游戏显示的界面UI,游戏中等。当然为了看到每一层的东西,可把一些层设置为透明

    或半透明的,这样就可以看到不同布景层加到一起的效果了。

    一、布景层类CCLayer

          布景层类CCLayer是CCNode类的子类,并且在此基础上实现触屏事件代理(TouchEventsDelegate)协议,可以

    实现CCNode类的功能,并且可以处理输入,包括触屏和加速传感器。 CCLayer类包含了三个功能。

    <1> 接受用户操作,比如触屏、重力加速度计的信息。

    <2> 作为游戏内容元素的容器,用于显示游戏画面、承载精灵类、字体文本等对象。

    <3> 填充背景游戏背景颜色。

    CCLayer类的继承关系如下图所示。

          由图可以看出CCLayer类继承自CCNode类,并且CCLayer类还遵照触屏代理协议、加速度传感器代理协议、键

    盘时间代理协议等协议。除此之外,CCLayer类还有子类,如下图所示。

    这些子类的功能如下图所示。

              首先来看看CCLayer类的使用,然后再来看主要的子类的使用。

    1、CCLayer类的主要函数如下图所示。

    2、CCLayer类的使用

          新建一个Cocos2D-X的项目,然后在新建项目的HelloWorldScene.cpp文件中,scene函数定义CCLayer类并把它

    加入场景中,代码如下所示。

    CCScene* HelloWorld::scene()
    {  
        // 新建场景类实例
        CCScene * scene = CCScene::create();     
    
        //定义布景层
        HelloWorld *layer = HelloWorld::create();      
    
        // 将布景层加入场景中
        scene->addChild(layer);
       
        // 返回场景类
        return scene;
    }

          CCLayer类的init函数在创建布景层时被调用,如下代码所示。

    bool HelloWorld::init()
    {    
        if(! CCLayer::init())
    	{
    		return false;
    	}
    
        // 创建一个菜单按钮子项
        CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                "CloseNormal.png",
                "CloseSelected.png",
                this,
                menu_selector(HelloWorld::menuCloseCallback));
    
        // 设置菜单按钮的位置
        pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
    
        // 创建一个包含关闭按钮的菜单
        CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
        pMenu->setPosition(CCPointZero);     
    
        // 添加菜单到图层中
        this->addChild(pMenu, 1);
    
        // 得到尺寸大小
        CCSize size = CCDirector::sharedDirector()->getWinSize();
      
        // 创建图片精灵
        CCSprite* pSprite = CCSprite::create("HelloWorld.png");    
    
        // 设置图片精灵的位置
        pSprite->setPosition(ccp(size.width/2, size.height/2));
    
        // 把图片精灵放置在图层中
        this->addChild(pSprite, 0);
    
        return true;
    }


           我们会在后面学习具体显示在层次上的对象,目前只需要了解在init函数中定义要显示的对象并把它作为子类加入

    场景中。另外,关于触屏、键盘、加速度传感器等输入,我们也会在后面学习到。接下来,让我们一起学习CCLayer

    类的子类。

    二、颜色布景层类(CCLayerColor

           颜色布景层类CCLayerColor是CCLayer类的子类,包含CCLayer类的特性,并且有两个扩展功能:可以为布景层

    增添颜色,以及设置不透明度。

          我们新建一个Coco2D-X的项目,然后在看CCLayerColor类的定义初始化,如下代码所示。这段代码在下

    HelloWorldScene.cpp文件中HelloWorld的init函数。

    bool HelloWorld::init()
    {
        bool bRet = false;
        do 
        {      
            CC_BREAK_IF(! CCLayer::init());
        
            // Create a "close" menu item with close icon, it's an auto release object.
            CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                "CloseNormal.png",
                "CloseSelected.png",
                this,
                menu_selector(HelloWorld::menuCloseCallback));
            CC_BREAK_IF(! pCloseItem);
    
            // Place the menu item bottom-right conner.
            pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
    
            // Create a menu with the "close" menu item, it's an auto release object.
            CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
            pMenu->setPosition(CCPointZero);
            CC_BREAK_IF(! pMenu);
    
            // Add the menu to HelloWorld layer as a child layer.
            this->addChild(pMenu, 1);		
    
            // Get window size and place the label upper. 
            CCSize size = CCDirector::sharedDirector()->getWinSize();
     
    		CCLayerColor* layer = CCLayerColor::create(ccc4(0xFF,0x00,0x00,0x80),200,200);
    		layer->ignoreAnchorPointForPosition(false);
    		layer->setPosition(CCPointMake(size.width/2,size.height/2));
    		addChild(layer,1);     
    
            bRet = true;
        } while (0);
    
        return bRet;
    }

    我们主要看的是这几句代码:

    CCLayerColor* layer = CCLayerColor::create(ccc4(0xFF,0x00,0x00,0x80),200,200);
    		layer->ignoreAnchorPointForPosition(false);
    		layer->setPosition(CCPointMake(size.width/2,size.height/2));
    		addChild(layer,1);     


          create函数的第一个参数是颜色的ARGB值,使用ccc4定义,其中第一个参数是颜色A值,第二个参数是R值,第

    三个参数是G值,最后一个参数是B值。除此之外,create函数后两个参数是布景层的宽和高。
          
    另外,使用ignoreAnchorPointForPosition将忽略锚点置为false。由于默认设置是忽略锚点,也就是以左下角为锚

    点,可以让布景层考虑锚点的影响(关于锚点在之前已经学习过),这时默认的锚点在中心。

           

    运行效果图如下图所示。

     

          还有一个比较常用的函数setBlendFunc,可以让布景层的颜色产生渐变的效果。比如,需要在整屛添加全屏的一

    些覆盖效果、全屏变黑或者全屏变暗时,都可以使用这个方法。下面让我们通过示例来学习这个函数的用法。

    <1> 新建一个Coco2D-X的项目,我们取名为MyLayerBlend。首先在HelloWorldScene.h头文件中添加一个函数。

    void newBlend(float dt);

    <2> 然后在HelloWorldScene.cpp文件的init函数中修改如下所示代码。

    bool HelloWorld::init()
    {
        bool bRet = false;
        do 
        {   
            CC_BREAK_IF(! CCLayer::init());     
    
            // Create a "close" menu item with close icon, it's an auto release object.
            CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                "CloseNormal.png",
                "CloseSelected.png",
                this,
                menu_selector(HelloWorld::menuCloseCallback));
            CC_BREAK_IF(! pCloseItem);
    
            // Place the menu item bottom-right conner.
            pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
    
            // Create a menu with the "close" menu item, it's an auto release object.
            CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
            pMenu->setPosition(CCPointZero);
            CC_BREAK_IF(! pMenu);
    
            // Add the menu to HelloWorld layer as a child layer.
            this->addChild(pMenu);
         
            // Get window size and place the label upper. 
            CCSize size = CCDirector::sharedDirector()->getWinSize();
             
    		CCLayerColor* layer1 = CCLayerColor::create( ccc4(255, 255, 255, 80) );
    		
    		CCSprite* sister1 = CCSprite::create("grossinis_sister1.png");
            CCSprite* sister2 = CCSprite::create("grossinis_sister2.png");
       
            addChild(sister1,1);
            addChild(sister2,1);
            addChild(layer1, 100,1);
    
    	    sister1->setPosition( ccp( size.width*1/3, size.height/2) );
            sister2->setPosition( ccp( size.width*2/3, size.height/2) );
         
    	    schedule( schedule_selector(HelloWorld::newBlend), 1.0f);
    
            bRet = true;
        } while (0);
    
        return bRet;
    }

    这里用了一个定时器schedule来切换渐变的效果。

    <3> 最后在newBlend函数中添加如下所示代码。

    void HelloWorld::newBlend(float dt)
    {
         CCLayerColor *layer = (CCLayerColor*)getChildByTag(1);
    
        GLenum src;
        GLenum dst;
    
        if( layer->getBlendFunc().dst == GL_ZERO )
        {
            src = GL_SRC_ALPHA;
            dst = GL_ONE_MINUS_SRC_ALPHA;
        }
        else
        {
            src = GL_ONE_MINUS_DST_COLOR;
            dst = GL_ZERO;
        }
    
        ccBlendFunc bf = {src, dst};
        layer->setBlendFunc( bf );
    }

    传入的参数是一个有起始效果和结束效果的参数。

    <4> 运行效果图。

    三、多层布景层类(CCLayerMultiplex

         在游戏开发中,一般会把游戏分为两部分:一部分是游戏界面部分,也就是常说的UI部分;另一部分就是游戏本

    身的部分。有时UI有很多页面,在页面中用的图也并不是很多,不需要使用切换场景,只需把不同页面做成不同的布

    景层,然后切换布景层。那么这就需要一个“管理者”来管理这些界面,这时候就要使用CCLayerMultiplex类。

         在很多游戏中都需要在不同的界面中使用相同的几个变量,如果不这样做,就需要做大量的保存工作。

            

         在 tests项目中MenuTest.cpp的MenuTestScene类的runThisTest函数中有CCLayerMultiplex类的定义初始化方

    法,如下代码所示。

    void MenuTestScene::runThisTest()
    {
        CCLayer* pLayer1 = new MenuLayerMainMenu();
        CCLayer* pLayer2 = new MenuLayer2();
        CCLayer* pLayer3 = new MenuLayer3();
        CCLayer* pLayer4 = new MenuLayer4();
        CCLayer* pLayer5 = new MenuLayerPriorityTest();
        CCLayer* pLayer6 = new BugsTest();
        CCLayer* pLayer7 = new RemoveMenuItemWhenMove();
    
        CCLayerMultiplex* layer = CCLayerMultiplex::create(pLayer1, pLayer2, pLayer3, pLayer4, pLayer5, pLayer6, pLayer7, NULL);
        addChild(layer, 0); 
    
        pLayer1->release();
        pLayer2->release();
        pLayer3->release();
        pLayer4->release();
        pLayer5->release();
        pLayer6->release();
        pLayer7->release();
    
        CCDirector::sharedDirector()->replaceScene(this);
    }

           首先定义并初始化每个布景层类,然后将这些布景层实例以参数形式传给CCLayerMultiplex的create函数,最后以NULL(空)结束。

         这里在传入参数之后将这些布景层实例的指针释放,是为了防止内存泄露。至于Cocos2D-X的内存管理,我们会

    在后面学习到。

         然后把CCLayerMultiplex实例作为子节点传入场景中,最后运行场景。如下代码所示是切换布景层的switchTo函数

    使用方法。

    void MenuLayerPriorityTest::menuCallback(CCObject* pSender)
    {
        ((CCLayerMultiplex*)m_pParent)->switchTo(0);
    //    [[CCDirector sharedDirector] popScene];
    }

         由于这个函数被CCLayerMultiplex实例的子布景,即初始化CCLayerMultiplex传入的布景类实例调用,所以它的

    m_pParent父节点就是CCLayerMultiplex实例本身。获得CCLayerMultiplex实例指针后,调用switchTo函数就可以转

    换到相应的子布景中。

    示例源码下载地址

  • 相关阅读:
    Eclipse慢慢学会的快捷键
    换行和flush()
    接口Interface
    对象的转型
    抽象类和抽象函数
    BufferedReader
    FileInputStream和FileReader
    Unable to instantiate receiver XXXXXX
    声明对象和定义数组
    Eclipse中文乱码问题
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3206657.html
Copyright © 2020-2023  润新知