上两节讲cocos2d-x的启动并进入主循环的过程,这里还是讲这个,但是是用win32版本讲解。一方面可以巩固,一方面可以看看cocos2d-x是如果做到跨平台的。前面讲到c++的入口是main函数,但是windows下是_tWinMain。嗯,微软家的东西都是这个样子,就是有点不一样。注意main文件都是在xxx.proj目录下面的,因为平台不同,实现也不同,大家可别乱找啊。
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
eglView->setViewName("HelloCpp");
eglView->setFrameSize(2048, 1536);
// The resolution of ipad3 is very large. In general, PC's
//resolution is smaller than it.
// So we need to invoke 'setFrameZoomFactor'(only valid on
//desktop(win32, mac, linux)) to make the window smaller.
eglView->setFrameZoomFactor(0.4f);
return CCApplication::sharedApplication()->run();
}
看看,这里的AppDelegate不再是一个static变量了,而是一个局部变量,同样地这会产生一个单件指针,注意啊注意,这个产生的指针其实是AppDelegate的Parent CCApplication的指针,也就是shareApplication返回的。windwos版本的CCApplication不再是一个虚类了。它自己就实现了主要的逻辑。这与ios版本是截然不同的。你看看main中的代码,可能认为AppDelegate app声明之后什么也没有做,实际上它是最后一句执行的基础。其中的关系,读者慢慢体会。我只知道要是我写出了这样的代码,我会被骂死的。之后就直接开始调用run函数了。 而且run函数返回一个int值是用到了这里。
看看其代码:
intCCApplication::run()
{
PVRFrameEnableControlWindow(false);
// Main message loop:
MSGmsg;
LARGE_INTEGERnFreq;
LARGE_INTEGERnLast;
LARGE_INTEGERnNow;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nLast);
// Initialize instance and cocos2d.
if(!applicationDidFinishLaunching())
{
return0;
}
CCEGLView*pMainWnd=CCEGLView::sharedOpenGLView();
pMainWnd->centerWindow();
ShowWindow(pMainWnd->getHWnd(),SW_SHOW);
while(1)
{
if(!PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// Get current time tick.
QueryPerformanceCounter(&nNow);
// If it's the time to draw next frame, draw it,
// else sleep a while.
if(nNow.QuadPart-nLast.QuadPart>
m_nAnimationInterval.QuadPart)
{
nLast.QuadPart=nNow.QuadPart;
CCDirector::sharedDirector()->mainLoop();
}
else
{
Sleep(0);
}
continue;
}
if(WM_QUIT==msg.message)
{
// Quit message loop.
break;
}
// Deal with windows message.
if(!m_hAccelTable||!TranslateAccelerator(msg.hwnd,
m_hAccelTable,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return(int)msg.wParam;
}
要看懂这个函数需要对win32编程有所了解,我这里不详细介绍了,前面开始是一些窗口创建工作,之后便是一个大的消息处理循环。这里的while循环揭示了其性能原因。ios和android的循环是通知模型,而windows的循环是轮询模型。这两种模型在计算机中广泛存在。等到执行mainLoop时就和ios版本一致无二了。这里的run函数可以边可以看成是主循环,而ios版本的则只是主循环的入口而已。希望大家能仔细比较下两个run函数的不同。