好多使用Cocos引擎的开发者有没有考虑过这样一个问题,我们创建好的Cocos项目是怎样运行起来的呢?其工程入口又在哪里呢?
那么我们先来看看我们工程目录的结构:
发布工程后我们会看到工程文件目录下有Classes子目录,Classes是用来存放用户自己写的C++文件,其中还包含了创建工程时生成的类AppDelegate.h、AppDelegate.cpp和HelloWorldScene.h、HelloWorldScene.cpp。Classes目录下的源文件是所有6个平台共用的代码文件,不管是android还是ios都使用这个目录下的源文件,属于真正跨平台部分的代码;
win32目录下的源文件有一个main主入口文件,负责win32平台下对游戏的调用。其实在对应的proj.android的工程里也有一个android平台对应的main主入口文件,只是由于平台的不同实现代码也各有不同,但是目的一样;
另外工程目录下还有个Resources子目录,用于存放资源文件,其目录下res文件中有一个MainScene.csb文件,这是我们发布项目时生成的二进制文件,它主要用来保存CocoStudio编辑的场景文件,通过该文件来显示我们编辑好的场景。
项目运行主要看Classes目录下的AppDelegate、HelloWorldScene两个类。
我们先看AppDelegate.cpp类:
class AppDelegate : private cocos2d::Application { public: AppDelegate(); virtual ~AppDelegate(); virtual void initGLContextAttrs(); virtual bool applicationDidFinishLaunching(); virtual void applicationDidEnterBackground(); virtual void applicationWillEnterForeground(); };
AppDelegate类中除构造、析构函数外主要有四个方法:
//设置 OpenGL context 属性,该设置对所有平台都有效 void AppDelegate::initGLContextAttrs() { //设置6个属性:red,green,blue,alpha,depth,stencil GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8}; GLView::setGLContextAttrs(glContextAttrs); }
//当应用程序启动时执行,游戏程序启动入口 //在这里我们启动了第一个scene(场景) //在具体游戏中通常在这里启动loading界面 //你的游戏从这里开始 bool AppDelegate::applicationDidFinishLaunching() { //初始化 director auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLViewImpl::createWithRect("HaHaHa", Rect(0, 0, 960, 640)); director->setOpenGLView(glview); } director->getOpenGLView()->setDesignResolutionSize(960, 640, ResolutionPolicy::SHOW_ALL); // 设置是否在屏幕上显示游戏帧数 // 开发阶段建议开启这个设置,可以通过这个对自己游戏性能有个大体了解 // 等游戏正式发布时关闭这个设置 director->setDisplayStats(true); // 设置帧率,默认值为60帧每秒 director->setAnimationInterval(1.0 / 60); FileUtils::getInstance()->addSearchPath("res"); // 创建一个HelloWorld的scene.这个是自动回收的对象 auto scene = HelloWorld::createScene(); // 告诉director运行HelloWorld的scene //只有执行了这一步才能让场景类显示出来 director->runWithScene(scene); return true; }
// 当游戏进入后台时会调用这个方法 // 比如玩游戏时按下android手机的home按键 // 比如当游戏时有电话打入直接显示来电界面 void AppDelegate::applicationDidEnterBackground() { Director::getInstance()->stopAnimation(); }
//当游戏恢复到前台运行时会调用这个方法 // 比如接电话结束是游戏界面又恢复到前台时 void AppDelegate::applicationWillEnterForeground() { Director::getInstance()->startAnimation(); }
接下来看类HelloWorld
HelloWorld : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(HelloWorld); };
这里需要注意HelloWorld 类继承自Layer类,所以HelloWorld对象为Layer对象。该类提供了3个方法:
1.创建场景方法createScene(),供AppDelegate使用;
2.重载了Layer的init方法,对其自身进行初始化;
3..通过宏函数CREATE_FUNC创建了HelloWorld的create()方法。
//创建场景方法 Scene* HelloWorld::createScene() { //创建一个自释放的场景对象 auto scene = Scene::create(); //创建一个自释放的层对象 auto layer = HelloWorld::create(); //把层对象添加到场景上 scene->addChild(layer); //返回这个创建的场景 return scene; }
//场景初始化方法 bool HelloWorld::init() { //首先进行父类初始化 if ( !Layer::init() ) { //如果初始化父类失败返回false return false; } //MainScene.csb是发布项目时生成的二进制文件 //通过该文件保存了我们编辑场景的完整信息 auto rootNode = CSLoader::createNode("MainScene.csb"); //将CocoStudio编辑的场景信息加到HelloWorld的layer上进行显示 addChild(rootNode); return true; }
好了,最后总结一下:
1.游戏运行是通过AppDelegate类里的applicationDidFinishLaunching()方法中的一句director->runWithScene(scene)完成的;
2.runWithScene(scene)的这个参数scene就是HelloWorld类里的createScene()方法返回的一个Scene类型的场景对象;
3.但是HelloWorld类本身并不是Scene类型而是Layer类型,它在createScene()方法中创建了一个HelloWorld对象和一个Scene场景对象,将HelloWorld对象添加到Scene对象上并将Scene对象返回;
4.HelloWorld对象通过create()方法创建,该对象为Layer类型,而create()方法是由宏函数CREATE_FUNC定义的;
5.MainScene.csb文件保存了在CocoStudio编辑的场景信息,在HelloWorld对象的init()方法里我们通过代码CSLoader::createNode("MainScene.csb")加载该二进制文件并添加到了HelloWorld对象上。
到这里cocos的项目工程大家应当都熟悉了,如果哪里有问题欢迎留言一起交流讨论哈!