2.1 在Cocos2d-x中创建一个新的场景
在Cocos2d-x中新建一个项目,命名为CocosProject01,并在Visual Studio 2013中打开,可以看到它的目录如图2-1所示。
图2-1 Cocos2d-x项目的目录
右击该项目,在快捷菜单中选择“添加”|“类”命令,创建一个新类,命名为MyScene,然后参照HelloWorldScene.h中的内容对文件MyScene.h进行编辑,如范例2-1所示。
【范例2-1】新建类MyScene的定义。
01 #include "cocos2d.h" 02 class MyWorld :public cocos2d::Layer 03 { 04 public: 05 static cocos2d::Scene* createScene(); //静态函数,用于获取场景对象 06 virtual bool init(); //初始化场景 07 CREATE_FUNC(MyWorld); //这里使用了一个宏 08 };
接下来再在MyScenecpp中实现MyScene.h中定义的方法,如范例2-2所示。
【范例2-2】新建类MyScene中方法的实现。
01 #include "MyScene.h" 02 USING_NS_CC; 03 Scene* MyWorld::createScene() 04 { 05 auto scene = Scene::create(); //创建一个场景对象 06 auto layer = MyWorld::create(); //创建Myscene对象 07 scene->addChild(layer); //将layer加入到场景scene中去 08 return scene; //返回创建好的场景对象 09 } 10 bool MyWorld::init() 11 { 12 if (!Layer::init()) 13 { 14 return false; 15 } 16 //今后就在这里向场景中加入内容 17 return true; 18 }
好了,到目前为止我们已经实现了一个新的类,但是读者应该还是迷迷糊糊的,不知道这究竟是要干嘛,那么接下来的任务就是解析这两段代码。
看范例2-2的第03~09行,该方法实现了创建并返回一个场景对象的功能。首先在第05行中创建一个Scene类型的对象scene,注意这并不是使用的MyWorld本身,之后才是创建了一个MyWorld类型的对象layer并将scene加入到其中,如第06、07行所示。
这里需要注意两个问题,首先就是在第05、06行中定义对象时使用了关键字auto,这是在C++ 11中新定义的自动类型变量,编译器将会在编译时自动对变量类型进行识别;其次是在第06行中使用的MyWorld类中的create方法与在第05行使用的create方法是不同的,那么这种不同又是怎样产生的呢?
现在看范例2-1的第07行,这里使用了一个宏定义。在Visual Studio中选中CREATE_FUNC,然后右击鼠标,在快捷菜单中选择“查看定义”命令就可以查看关于该宏定义的解释,如范例2-3所示。
【范例2-3】宏CREATE_FUNC的定义。
01 #define CREATE_FUNC(__TYPE__) \ 02 static __TYPE__* create() \ 03 { \ 04 __TYPE__ *pRet = new __TYPE__(); \ 05 if (pRet && pRet->init()) \ 06 { \ 07 pRet->autorelease(); \ 08 return pRet; \ 09 } \ 10 else \ 11 { \ 12 delete pRet; \ 13 pRet = NULL; \ 14 return NULL; \ 15 } \ 16 }
也许这让人看起来一头雾水,不过先不要着急,现在把这个宏定义的参数MyWorld带入到代码中,如范例2-4所示。
【范例2-4】将参数MyWorld带入到宏定义中。
01 static MyWorld * create() 02 { 03 MyWorld *pRet = new MyWorld (); 04 if (pRet && pRet->init()) 05 { 06 pRet->autorelease(); 07 return pRet; 08 } 09 else 10 { 11 delete pRet; 12 pRet = NULL; 13 return NULL; 14 } 15 }
这样看起来好像是清楚多了,但仔细推敲的话貌似雾水还在,不过没有关系,现在所需要知道的只是在MyWorld和Scene类中的create方法是两个不同的方法就可以了。
注意:这里唯一需要强调的就是MyScene虽然因为命名习惯将文件名叫做scene,而且也经常在习惯上将其称呼为场景类,但是它却并不是继承自Scene而是继承自Layer,因此它是一个层而不是一个场景。对于这一点的理解在今后的开发中非常重要。
在HelloWorldScene.h文件中可以看到如下所示的代码:
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ //对类的定义 #endif
这是干什么用的呢?
原来在实际的Cocos2d-x项目中,多个类之间经常会相互引用,比如要从MyWorld中切换到HelloWorld中就需要在MyWorldScene.h中引入HelloWorldScene.h,而再从HelloWorld切换回MyWorld则又要在HelloWorldScene.h中引入MyWorldScene.h,这就导致了编译器在编译时会重复许多工作。有了这段宏定义则可以保证,编译器确认对该类进行过编译工作后,就直接跳过这段代码,这节省了许多麻烦。