开始阅读Cocos2dx给的示例cpp-tests。本文将从追踪程序直到点开一个示例,了解cocos在期间干了些什么。
首先,依旧是程序入口main.cpp:
#include "main.h"
#include "AppDelegate.h"
USING_NS_CC;
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平台的入口函数。初始化了Application类,如上篇所述,这是个单例类,由语句AppDelegate app;进行了初始化。定位过去
AppDelegate::AppDelegate()
: _testController(nullptr)
{
}
AppDelegate 做了额外的初始化,初始化了_testController,这个是cpp-tests中定义的单例类TestController,用来控制cpp-tests中很多例子的执行。
由类的继承关系,我们可以得知Application本身也得到了初始化。
Application::Application()
: _instance(nullptr)
, _accelTable(nullptr)
{
_instance = GetModuleHandle(nullptr);
_animationInterval.QuadPart = 0;
CC_ASSERT(! sm_pSharedApplication);
sm_pSharedApplication = this;
}
初始化了一些句柄_instance,_accelTable,以及指向本身的指针sm_pSharedApplication。_animationInterval和设置帧率有关,这个之后再说。
之后进入Application::getInstance()->run();追踪进去,代码如下:
<pre name="code" class="cpp">int Application::run()
{
PVRFrameEnableControlWindow(false);//将程序的一些信息写入注册表
// Main message loop:
LARGE_INTEGER nLast; //用来存储时间
LARGE_INTEGER nNow;
QueryPerformanceCounter(&nLast); //得到当前时间并存储到nLast中
initGLContextAttrs();//初始化GL的属性
// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())//程序运行前所做的准备工作
{
return 1;
}
auto director = Director::getInstance();//导演 cocos中所初始化的导演类是DisplayLinkDirector子类 Director本身是个抽象类
//DisplayLinkDirector初始化只做了 : _invalid(false),用来控制mainloop循环执行的内容
//getInstance()中初始化了很多cocos中需要用的单例类
auto glview = director->getOpenGLView();//获取gl对象 在applicationDidFinishLaunching()中已经进行了初始化
// Retain glview to avoid glview being released in the while loop
glview->retain();//由于glview是个自动释放的对象,在进入mainloop()之前务必要retain 因为gl是个需要一直用的东西 不能被release掉
//自动释放池的内容以后再说吧 不能太混乱了
while(!glview->windowShouldClose())//屏幕关闭问题 和平台有关 可以进行修改 游戏不断进行循环 这就是游戏的主循环
{
QueryPerformanceCounter(&nNow);//计算当前时间
if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)//新老时间差满足帧率要求则运行 否则sleep(1),直到条件满足,这个是为了满足帧率
{
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()) //关闭程序后while循环结束 若opengl打开过 则进行收尾工作
{
director->end();// 执行了这么一句 _purgeDirectorInNextLoop = true; 之后再mainloop中就会执行第一种选择
director->mainLoop();//执行其中的第一种选择 执行purgeDirector(); 对资源进行释放 包括OpenGL view _runningScene 字体 缓存 等等 详细可以自己追踪进去看看
director = nullptr;
}
glview->release();//因为是自动释放对象 调用了retain 所以要release掉
return 0;
}
详细信息我都写了注释,其中有几个内容我再追踪进去看一下,1是 auto director = Director::getInstance();
Director* Director::getInstance()
{
if (!s_SharedDirector)
{
s_SharedDirector = new (std::nothrow) DisplayLinkDirector();
CCASSERT(s_SharedDirector, "FATAL: Not enough memory");
s_SharedDirector->init();
}
return s_SharedDirector;
}
可以看到如果Director尚未创建的话,新建DisplayLinkDirector类,并执行s_SharedDirector->init();
init函数就执行了下面这些初始化。
bool Director::init(void)
{
setDefaultValues();
// scenes
_runningScene = nullptr;
_nextScene = nullptr;
_notificationNode = nullptr;
_scenesStack.reserve(15);
// FPS
_accumDt = 0.0f;
_frameRate = 0.0f;
_FPSLabel = _drawnBatchesLabel = _drawnVerticesLabel = nullptr;
_totalFrames = 0;
_lastUpdate = new struct timeval;
_secondsPerFrame = 1.0f;
// paused ?
_paused = false;
// purge ?
_purgeDirectorInNextLoop = false;
// restart ?
_restartDirectorInNextLoop = false;
_winSizeInPoints = Size::ZERO;
_openGLView = nullptr;
_contentScaleFactor = 1.0f;
_console = new (std::nothrow) Console;//控制台 可用于远程调试 tcp连接
// scheduler
_scheduler = new (std::nothrow) Scheduler();//定时器
// action manager
_actionManager = new (std::nothrow) ActionManager();//动作管理器
_scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);//设置动作管理器随时间更新
_eventDispatcher = new (std::nothrow) EventDispatcher();//事件分发器
_eventAfterDraw = new (std::nothrow) EventCustom(EVENT_AFTER_DRAW); //事件分发器相关配置
_eventAfterDraw->setUserData(this);
_eventAfterVisit = new (std::nothrow) EventCustom(EVENT_AFTER_VISIT);
_eventAfterVisit->setUserData(this);
_eventAfterUpdate = new (std::nothrow) EventCustom(EVENT_AFTER_UPDATE);
_eventAfterUpdate->setUserData(this);
_eventProjectionChanged = new (std::nothrow) EventCustom(EVENT_PROJECTION_CHANGED);
_eventProjectionChanged->setUserData(this);
//init TextureCache
initTextureCache();//初始化纹理缓存
initMatrixStack();//初始化矩阵
_renderer = new (std::nothrow) Renderer;//渲染器 和OPENGL渲染相关
return true;
}
好的,这就是第一部分,run()函数做了什么。接下来会介绍 applicationDidFinishLaunching()的运行及 mainloop()的运行。