【玩转cocos2d-x之三】cocos2d-x游戏是怎么跑起来的

虽然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
//main.cpp  
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTRlpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);//该宏用于通知编译器不用检测变量是否使用,如果你喜欢用LV4级的警告。
UNREFERENCED_PARAMETER(lpCmdLine);

// create the application instance
AppDelegate app;//创建AppDelegate实例
CCEGLView* eglView = CCEGLView::sharedOpenGLView();//获取CCEGLView的单一实例,因为还未创建,所以这里会进行创建
eglView->setViewName("HelloCpp");//设置eglView属性
eglView->setFrameSize(2048, 1536);
eglView->setFrameZoomFactor(0.4f);
return CCApplication::sharedApplication()->run();//调用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,// Extended Style For The Window
kWindowClassName,// Class Name
wszBuf,// Window Title
WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX,// Defined Window Style
0, 0,// Window Position
1000, // Window Width
1000, // Window Height
NULL,// No Parent Window
NULL,// No Menu
hInstance,// Instance
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);

// Main message loop:
MSG msg;
LARGE_INTEGER nFreq;
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;

QueryPerformanceFrequency(&nFreq);//获取当前系统频率和计数
QueryPerformanceCounter(&nLast);

// Initialize instance and cocos2d.
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)//获取退出消息,跳出循环
{
// Quit message loop.
break;
}

// 处理Windows消息
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单例,设置窗口属性和fps等等
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();

...

// 创建场景
CCScene *pScene = HelloWorld::scene();

// 进入场景
pDirector->runWithScene(pScene);

return true;
}

好了,最后再总结成一张图,cocos2d-x游戏就是这么跑起来的~



文章目录
  1. 1. main函数
  2. 2. CCEGLView类
  3. 3. CCApplication类
  4. 4. AppDelegate类
,