在游戏开发过程中,你可能需要一个主菜单,几个关卡和一个END的界面,如何组织管理这些东西呢?

和其他游戏引擎类似,Cocos也使用了场景(Scene) 这个概念,我们的HelloWorld界面就是一个场景

一部电影或是番剧,就是由不同地点或不同时间线组成的,这些部分就是一个又一个的场景

参考:

这是一个主菜单场景,这个场景是由很多小的对象拼接而成,所有的对象组合在一起,形成了你看到的结果

场景是被渲染器(renderer)画出来的,渲染器负责渲染精灵和其它的对象进入屏幕,那渲染器怎么知道什么东西要渲染在后,什么东西要渲染在前呢?

答案是通过场景图(Scene Graph)实现

场景图(Scene Graph)

Cocos2d-x使用 中序遍历,先遍历左子树,然后根节点,最后是右子树

中序遍历下图的节点,能得到 A, B, C, D, E, F, G, H, I 这样的序列

现在我们再看这个游戏场景:

分解这场景为5个部分

抽象成数据结构就是:

z-order

场景中有一个我们自己的图片,一个关闭按钮,一个HelloWorld的字样,这些东西都是在HelloWorld::init()中生成的

场景初始化"CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); if (closeItem == nullptr || closeItem->getContentSize().width <= 0 || closeItem->getContentSize().height <= 0) { problemLoading("'CloseNormal.png' and 'CloseSelected.png'"); } else { float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2; float y = origin.y + closeItem->getContentSize().height/2; closeItem->setPosition(Vec2(x,y)); } // create menu, it's an autorelease object auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); ... }

cocos里很多对象在生成的时候都会使用create这个静态工厂方法,我们创建图片精灵的时候就用到了auto mySprite = Sprite::create("xxxxxx.png"),HelloWorld这个场景也不例外

MenuItemImage的创建"CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

然后就是计算出x和y的值,也就是右下角的按钮的坐标,getContentSize()获得对象的尺寸,最后使用setPosition设置按钮的坐标

Copy
if (closeItem == nullptr || closeItem->getContentSize().width <= 0 || closeItem->getContentSize().height <= 0) { problemLoading("'CloseNormal.png' and 'CloseSelected.png'"); } else { float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2; float y = origin.y + closeItem->getContentSize().height/2; closeItem->setPosition(Vec2(x,y)); }

但是按钮是不可以直接添加到场景中的,按钮需要依赖菜单,也就是Menu对象

Menu的创建#

我们创建一个包含了closeItem的菜单,并设置坐标为(0,0),最后才能使用addChild将菜单添加到场景中

Copy
// create menu, it's an autorelease object auto menu = Menu::create(closeItem,