【cocos2d-x 源码剖析】启动窗口
来源:互联网 发布:免费洗车的软件 编辑:程序博客网 时间:2024/05/22 06:16
程序从哪里启动
不仅游戏,任何程序都必须有一个启动的入口;几乎每个程序员接触编程的第一个程序都是 HelloWorld 控制台程序,这个最简单的程序的入口就是 Main 函数。接下来就让我们看看 cocos2d-x 创建的游戏是从哪里开始启动的,这里只探讨 win32 程序,其它平台以后有时间再探讨。使用 cocos2d-x 新建一个游戏后,可以在项目下看到这几个文件
|-HelloWorld |-AppDelegate.h |-AppDelegate.cpp |-HelloWorldScene.h |-HelloWorldScene.cpp |-main.h |-main.cpp
直觉告诉我们,游戏启动的入口应该在 main.cpp 中,打开这个文件
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // create the application instance AppDelegate app; return Application::getInstance()->run();}
果然没错,这就是 win32 程序的主函数写法,我们的游戏就是从这个函数开始启动的。再打开 main.h,可以看到这里包含了 win32 程序需要的头文件
#include <windows.h>#include <tchar.h>
再回到我们的主函数中,这里用到了 AppDelegate 和 Application 这两个类,AppDelegate 在 AppDelegate.h 和 AppDelegate.cpp 中定义
class AppDelegate : private cocos2d::Application
AppDelegate 继承自 Application 类,Application 类在 CCApplication-win.h 和 CCApplication-win.cpp 中定义
class CC_DLL Application : public ApplicationProtocol
可以看到 Application 又继承自 ApplicationProtocal 类,ApplicationProtocol 类在 CCApplicationProtocol.h 中定义,这几个文件在 cocos2d-x 引擎中定义
|-libcocos2d |-platform |-win32 |-CCApplication-win32.h |-CCApplication-win32.cpp |-CCApplicationProtocol.h
总结: 游戏从 main.cpp 中启动,AppDelegate 是应用程序的实例,AppDelegate 继承自 Application,Application 继承自 ApplicationProtocol。接下来探究一下这三个类。
ApplicationProtocol
这是应用程序类的最顶层基类,它其实是一个抽象类,定义了一套应用程序接口,最主要的是下面四个方法
virtual void initGLContextAttrs() {}virtual bool applicationDidFinishLaunching() = 0;virtual void applicationDidEnterBackground() = 0;virtual void applicationWillEnterForeground() = 0;
Application
这个类控制应用程序的生命周期,提供和管理一些全局的资源,创建和管理 win32 窗口以及消息循环都是在这个类定义的。Application 定义了几个 protected 字段
HINSTANCE _instance;HACCEL _accelTable;LARGE_INTEGER _animationInterval;std::string _resourceRootPath;std::string _startupScriptFilename;static Application * sm_pSharedApplication;
前两个字段是跟窗口相关的属性,第三个字段是动画播放的间隔,第四个字段是资源文件的搜索路径,第五个字段是绑定的脚本名称,最后一个字段是 Application 的单例。Application 中有两个重要的方法
int run();static Application* getInstance();
getInstance 是获取单例,run 实现 win32 程序窗体创建和消息注册,后面再讲。
AppDelegate
AppDelegate 继承自 Application,主要实现了 ApplicationProtocol 的四个虚函数,
* initGLContextAttrs 设置 OpenGL context 属性
* applicationDidFinishLaunching 游戏资源加载完成后调用
* applicationDidEnterBackground 游戏进入后台时调用
* applicationWillEnterForeground 游戏回到前台时调用
游戏启动过程
我们先来回顾一下 win32 程序的启动过程,定义窗口类,绑定回调方法,注册窗口类,创建窗口,显示和刷新窗口,开始消息循环。然后我们再来看看 cocos2d-x 程序的启动过程以及在哪里完成窗口的初始化工作。
首先,从 main.cpp 的主函数开始运行
AppDelegate app;return Application::getInstance()->run();
先创建一个 AppDelegate 的实例,目的是调用构造函数进行一些初始化工作。回顾 C++ 调用构造函数和析构函数的顺序,是 父类构造函数–>子类构造函数–>…->子类析构函数–>父类析构函数,所以会先调用 Application 的构造函数再调用 AppDelegate 的构造函数。先看看 Application 的构造函数
Application::Application(): _instance(nullptr), _accelTable(nullptr){ _instance = GetModuleHandle(nullptr); _animationInterval.QuadPart = 0; CC_ASSERT(! sm_pSharedApplication); sm_pSharedApplication = this;}
主要是初始化一些值,最主要的就是给静态单例变量 sm_pSharedApplication 赋值,之后 Application::getInstance()
就可以得到正确的值了。AppDelegate 的构造函数并没做什么,接下来看看 Application 的 run 函数
int Application::run(){ PVRFrameEnableControlWindow(false); // Main message loop: LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceCounter(&nLast); initGLContextAttrs(); // Initialize instance and cocos2d. if (!applicationDidFinishLaunching()) { return 1; } auto director = Director::getInstance(); auto glview = director->getOpenGLView(); // Retain glview to avoid glview being released in the while loop glview->retain(); while(!glview->windowShouldClose()) { QueryPerformanceCounter(&nNow); if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % _animationInterval.QuadPart); director->mainLoop(); glview->pollEvents(); } else { Sleep(1); } } // Director should still do a cleanup if the window was closed manually. if (glview->isOpenGLReady()) { director->end(); director->mainLoop(); director = nullptr; } glview->release(); return 0;}
其中 initGLContextAttrs 和 applicationDidFinishLaunching 在子类 AppDelegate 中定义,while(!glew->windowShouldClose())
实时检测窗口是否关闭,如果没关闭,则调用 director->mainloop()
;如果关闭了,则做一些回收工作,然后程序结束。程序在 while 循环这里阻塞住,直到游戏窗口被关闭。看完 run 函数,发现并没有创建窗口的代码啊,但在 while 循环这里却判断窗口是否关闭,说明此时窗口已经创建成功了;如果你断点调试一下,你就会发现执行完函数 applicationDidFinishLaunching 之后窗口就被创建出来了,说明创建窗口的代码在 applicationDidFinishLaunching 函数里,我们打开这个函数
glview = GLViewImpl::createWithRect("HelloWorld", Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
这条语句说明窗口的创建和管理被封装在类 GLViewImpl 里,GLViewImpl 继承自 GlView,GLView 负责 OpenGL 的初始化工作和窗口管理工作。
总结
ApplicationProtocol 定义了一套应用程序的接口,Application 控制着整个应用程序的生命周期,AppDelegate 是 Application 的子类,实现应用程序接口;每个项目都会有一个 AppDelegate 类,在 AppDelegate 中调用 GLView 来初始化窗口和 OpenGL。
- 【cocos2d-x 源码剖析】启动窗口
- cocos2d-x应用窗口相关源码剖析1
- cocos2d-x应用窗口相关源码剖析2
- bombing:cocos2d-x应用窗口相关源码剖析3
- cocos2d-x应用窗口相关源码剖析4
- cocos2d-x应用窗口相关源码剖析5-其他细节
- cocos2d-x应用窗口相关源码剖析5-其他细节
- cocos2d-x源码剖析引子
- cocos2d-x 源码剖析(7)
- cocos2d-x源码剖析之整体框架
- cocos2d-x源码剖析之场景管理
- cocos2d-x源码剖析之精灵对象
- cocos2d-x 源码剖析(1)
- cocos2d-x 源码剖析(2)
- cocos2d-x 源码剖析(3)
- cocos2d-x 源码剖析(4)
- cocos2d-x 源码剖析(5)
- cocos2d-x 源码剖析(6)
- logback配置
- 直接插入排序(Insertion Sort)
- 从collection中取op
- JS 字符串 常用操作
- poj 1679 The Unique MST
- 【cocos2d-x 源码剖析】启动窗口
- 【C++】G++命令简介
- eclispe 设置自动提示
- MySQL 触发器
- logback属性
- 网卡混杂模式Promiscuous与linux上混杂模式的设置
- 艾灸神阙穴的神奇疗效
- 鼠标滑轮成了页面缩放的解决方法
- Fraction to Recurring Decimal问题及解法