【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函数就可以转

换到相应的子布景中。

 

 

示例源码下载地址

 

posted @ 2013-07-22 20:09  坚固66  阅读(266)  评论(0编辑  收藏  举报