虽然cocos2d-x v3.0 alpha版已经出来了,也改进了不少,有兴趣的可以去尝尝鲜。因为后面可能还会配合cocoStudio写一下博客,而现在v1.0.0.0版本需要配合cocos2d-x v2.2.0使用。所以这里选择了V2.2.0版的cocos2d-x。
一个新的东西,从头开始吧!从HelloWorld出发看一下一个cocos2d-x游戏是怎么跑起来的。先看看它的结构。
main函数
还是原来配方还是熟悉的味道。。。霸气的main函数依然是程序的入口点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTRlpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine);
AppDelegate app; CCEGLView* eglView = CCEGLView::sharedOpenGLView(); eglView->setViewName("HelloCpp"); eglView->setFrameSize(2048, 1536); eglView->setFrameZoomFactor(0.4f); return CCApplication::sharedApplication()->run(); }
|
其中:
(1)AppDelegate继承于CCApplication,是整个游戏的程序类,如果有用过MFC的就很清楚,类似于CxxxApp。
(2)CCEGLView封装了使用openGL作为显示底层API的一个基本的Windows窗体的创建和控制。
可以简单的认为,一个控制了程序的逻辑,而另一个负责游戏的显示。
CCEGLView类
我们先看看上一步的CCEGLView::sharedOpenGLView()做了什么。
CCEGLView* CCEGLView::sharedOpenGLView()
{
if (s_pEglView == NULL)//s_pEglView是一个CCEGLView指针,静态成员变量
{
s_pEglView = new CCEGLView();
if(!s_pEglView->Create())//main中调用时,会执行这一步
{
delete s_pEglView;
s_pEglView = NULL;
}
}
return s_pEglView;
}
再看看,create做了什么
1 2 3 4 5 6 7 8 9 10 11 12 13
| m_hWnd = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, kWindowClassName, wszBuf, WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX, 0, 0, 1000, 1000, NULL, NULL, hInstance, NULL );
|
看到上面这一步了吧,使用Win32写过窗体的童鞋,就知道创建一个窗体需要哪些动作:
(1)填充窗口类结构WNDCLASS
(2)注册窗口
(3)创建窗口
(4)显示窗口(这一步没有在CCEGLView中实现,而是在后面的CCApplication中实现,因为这里窗口的属性还没有进行设置)
一样的,创建一个cocos2d-x的win32窗口也是要经过这些步骤。具体的就看源码吧,这里不逐句解释了。就是要注意有个WinProc函数,是用于处理主窗口消息。
CCApplication类
我们再看看CCApplication::sharedApplication()->run()执行的又是什么东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| int CCApplication::run() { PVRFrameEnableControlWindow(false); MSG msg; LARGE_INTEGER nFreq; LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nLast); if (!applicationDidFinishLaunching()) { return 0; } CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();获取CCEGLView的单一实例 pMainWnd->centerWindow(); ShowWindow(pMainWnd->getHWnd(), SW_SHOW); while (1) { if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { QueryPerformanceCounter(&nNow); if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart; CCDirector::sharedDirector()->mainLoop(); } else { Sleep(0); } continue; } if (WM_QUIT == msg.message) { break; } if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }
|
好了,解释的应该算比较清楚了,虽然没有每一个函数都进去。。。这里再总结一下:
(1)首先先获取当前系统的频率和计数。这是一个很大的值,所以用了一个LARGE_INTEGER型变量来存储。
(2)调用子类的applicationDidFinishLaunching(),执行进入程序后的一些初始化工作。
(3)获取CCEGLView单例,显示窗口。
(4)进入循环While(1),重绘每一帧的场景。
好了,更多关于CCApplication的请看源码吧。
AppDelegate类
从上面的分析我们知道CCApplication::run()函数中会调用子类(AppDelegate)的applicationDidFinishLaunching函数,而这里也就是我们要设置窗口属性和运行游戏的地方了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| bool AppDelegate::applicationDidFinishLaunching() {
CCDirector* pDirector = CCDirector::sharedDirector();
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); ...
CCScene *pScene = HelloWorld::scene();
pDirector->runWithScene(pScene); return true; }
|
好了,最后再总结成一张图,cocos2d-x游戏就是这么跑起来的~