您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x: 死磕"HelloWorld"(4)——HelloWorld场景的创建

2014-07-05 07:39 381 查看
该篇将分析万众瞩目的HelloWorld场景是如何出现的。我们在上一篇中已经看到在应用初始化函数applicationDidFinishLaunching()中调用了HelloWorld::scene()来创建场景。因此答案就在HelloWorld::scene()里,我们将对它进行详解。但是在分析之前,我们先来复习一下cocos2d-x的渲染框架,也就是cocos2d-x渲染对象的层次结构。渲染框架主要就是四个概念: 导演类director,场景类scene,图层类layer,精灵类sprite。一个app只有一个导演,它指挥场景的切换和运行。每一个场景里面又包含前后图层,而每一个图层里面又包含人物精灵。所以渲染的对象只有三个,即场景,图层和精灵。它们都继承自一个基本的渲染节点类,即CCNode类。场景包含图层,图层包含精灵,反过来说,精灵在图层内,图层在场景内。场景最大。导演只需把最大的指挥好就行了。可以利用CCNode的成员函数addChild()把精灵加入到图层里,或者把图层加入到场景里。
先来看一下HelloWorld类头文件:

HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();

// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();

// a selector callback
void menuCloseCallback(CCObject* pSender);

// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

可见HelloWorld类继承自图层类,而非场景类。它共有四个成员函数,分别是图层初始化函数init(),场景创建函数scene(),关闭回调函数menuCloseCallback()(在上一篇中提到过用来关闭程序),还有图层创建函数create()(通过宏实现)。其中scence()和create()都是静态函数,分别返回CCScene指针和HelloWorld指针。接下来,我们马上会看到scene()调用了create(),而create()又调用了init(),而init()又调用了menuCloseCallback()。下面就先来看一下HelloWorld::scene()具体定义:

HelloWorldScene.cpp
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();//创建了一个场景类对象,并返回该场景的指针。

// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();//利用静态成员函数create()创建一个HelloWorld图层,并返回该图层的指针。注意HelloWorld的基类CCLayer里也有一个静态成员函数creat(),但是该静态成员函数被HelloWorld重载了。题外话:静态函数直接绑定类,被所有实例共享,所以不存在多态,不能虚函数化。

// add layer as a child to scene
scene->addChild(layer);//将该图层添加到场景里面。

// return the scene
return scene;//返回该场景。
}

第一个create()是场景类的静态成员函数,因此是一般性的,HelloWorld图片肯定不是从这里进入。再者HelloWorld图片应该先绑定一个精灵,然后将该精灵添加到图层里。因此HelloWorld图片肯定是从第二个create()进入的。我们现在就来看看第二个create()的定义。它的定义由宏CREATE_FUNC(HelloWorld)实现。该宏的定义为:

CCPlatformMacros.h

#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; \
} \
}

该定义和CCLayer类中的create()定义基本一致,只是它们创建的对象属于不同的类。由于它们所调用的init()是一虚函数,因此HelloWorld类里的create()创建的对象调用HelloWorld类本身的init()。我们现在就来看看HelloWorld类里的init()函数:

HelloWorldScene.cpp
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )//利用基类成员函数CCLayer::init()对图层对象进行初始化。如果初始化失败则退出函数,返回假。
{
return false;
}

CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//获取可视大小。
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();//获取原点。

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback));//创建关闭图标,调用menuCloseCallback

pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
origin.y + pCloseItem->getContentSize().height/2));//设置关闭图标位置。

// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);//利用关闭图标创建一个按钮。
pMenu->setPosition(CCPointZero);//设置按钮位置。
this->addChild(pMenu, 1);//将按钮添加到当前图层。

/////////////////////////////
// 3. add your codes below...

// add a label shows "Hello World"
// create and initialize a label

CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE);//创建一个Hello World标签

// position the label on the center of the screen
pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - pLabel->getContentSize().height));//设置标签位置。

// add the label as a child to this layer
this->addChild(pLabel, 1);//添加标签到当前图层。

// add "HelloWorld" splash screen"
CCSprite* pSprite = CCSprite::create("HelloWorld.png");//利用HelloWorld.png纹理创建一个精灵。

// position the sprite on the center of the screen
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));//设置精灵位置。

// add the sprite as a child to this layer
this->addChild(pSprite, 0);//添加精灵到当前图层。

return true;
}

一个简单的游戏到此就算制作完成了。作为一个简单的例子,HelloWorld场景只有一个图层,从该图层初始化函数中可以看出,该图层只包含了一个关闭按钮,一个标签,和一个带HelloWorld纹理的精灵。如果要做更为复杂生动的游戏,可以往该初始化函数中添加新的内容。

接下来会用两个篇章来分析场景的渲染。它对于单纯的游戏制作者而言可以不用理会,但是可以帮助我们理解引擎的工作原理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: