main函数作为所有C语言程序的入口 cocos2dx也不例外 在win32文件夹下我们可以看到 main.cpp这个文件 其中代码如下:
#include "main.h"
#include "AppDelegate.h"
#include "cocos2d.h"
USING_NS_CC;
int APIENTRY _tWinMain(HINSTANCE hInstance,//程序当前实例的句柄,以后随时可以用GetModuleHandle(0)来获得
HINSTANCE hPrevInstance,//这个参数在Win32环境下总是0,已经废弃不用了
LPTSTR lpCmdLine,//指向以/0结尾的命令行,不包括EXE本身的文件名,
int nCmdShow)//指定以什么方式显示主窗口
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
return Application::getInstance()->run();
}
我们来分别解释其中代码的含义:
APIENTRY:这个是一个宏定义 这个标明这里函数的从左到右的压栈约定
_tWinMain做为c语言程序的入口
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); //这两句表面再这里让编译器忽略hPrevInstance和IpCmdLine有定义但未使用的警告
//cocos2dx的真正运行
AppDelegate app;
return Application::getInstance()->run();
我们会发现我们所实例的app从来没有调用过 那么在这里有何用意呢?
一般有些编程经验的人可以推测出,这里应该是对 Application的构造函数的一个调用 那么如何才会调用到 Application的构造函数呢 ?是继承?还是组合? 我们看看源码
//AppDelegate源码
class AppDelegate : private cocos2d::Application//很明显这里是继承 我们继续往上走 看看Application源码
{
public:
AppDelegate();
virtual ~AppDelegate();
virtual void initGLContextAttrs();
/**
@brief Implement Director and Scene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief The function be called when the application enter background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief The function be called when the application enter foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
{
public:
AppDelegate();
virtual ~AppDelegate();
virtual void initGLContextAttrs();
/**
@brief Implement Director and Scene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief The function be called when the application enter background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief The function be called when the application enter foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
};
Application源码
class CC_DLL Application : public ApplicationProtocol
{
public:
/**
* @js ctor
*/
Application();
/**
* @js NA
* @lua NA
*/
virtual ~Application();
/**
@brief Run the message loop.
*/
int run();
/**
@brief Get current applicaiton instance.
@return Current application instance pointer.
*/
static Application* getInstance();
.......
只贴了一部分
根据先前我们的分析 我们着重看构造函数 和 run函数 以及getInstance函数
Application * Application::sm_pSharedApplication = 0;
Application::Application()
: _instance(nullptr)
, _accelTable(nullptr)
{
_instance = GetModuleHandle(nullptr);
_animationInterval.QuadPart = 0;
CC_ASSERT(! sm_pSharedApplication);
sm_pSharedApplication = this;
}
可以看到构造函数主要是一些变量的初始化
Application* Application::getInstance()
{
CC_ASSERT(sm_pSharedApplication);
return sm_pSharedApplication;
}
getinstance函数 主要用于获取sm_pSharedApplication实例
int Application::run()
{
PVRFrameEnableControlWindow(false);
// Main message loop:
LARGE_INTEGER nFreq;
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nLast);
initGLContextAttrs();//初始化窗口信息
// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())//此处调用了这个函数 正式进入cocos2dx
{
return 0;
}
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;
director->mainLoop();//由mainloop进行维持
glview->pollEvents();
}
else
{
Sleep(0);
}
}
//当我们要关闭窗口时接着运行以下的代码
// Director should still do a cleanup if the window was closed manually.
if (glview->isOpenGLReady())
{
director->end();//导演end
director->mainLoop();//
director = nullptr;
}
glview->release();//释放窗口
return true;
}
由以上我们可以得到一个清晰的运行过程:
在win32文件下的 main.cpp文件中 先执行appdelegate app 调用其构造函数 以调用 application 构造函数 将 sm_pSharedApplication 初始化后 调用application 中的run 继而调用 applicationDidFinishLauching() 初始化 director和scene 在此函数内正式运行 scene 再由director->mainloop进行维持 当我们 手动关闭窗口时 进行资源回收 关闭窗口 也调用了director->end