学习游戏开发也有3个月了,其中也做一个安卓的原创游戏(2D游戏,目前没有接触到3D游戏),之前没有接触过游戏引擎,游戏的一些简单的物理效果都是自己写,cocos2d-x是我第一次接触游戏引擎,下载源码后就开始深入源码去学习,学习别人更好的思想,也在寻找在设计上和自己做的有什么异同点。记录下我现在所看到的,了解到的。废话不多说,我现在看的版本是cocos2d-2.1rc0-x-2.1.2。
做个游戏的应该都知道,我们的游戏一般是在一个死循环中渲染的,比如下面:
复制代码
所以我首先在底层源代码中寻找这个样子的东东。(注:我是用VS在WIN32平台下查看)
首先打开 ...\cocos2d-2.1rc0-x-2.1.2\samples\Cpp\TestCpp\proj.win32\main.cpp
复制代码
这里就是程序的主入口,没有什么好说的,唯一注意的就是AppDelegate类在这里被实例化了。接着进入 CCApplication::run();
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\platform\win32\CCApplication.cpp
复制代码
在这里省去了一些平台有关的代码,主要是WIN32平台的窗口消息的获取等,还有一些计算时间的代码。在这个循环中,只要达到渲染要求,就进入CCDirector::sharedDirector()->mainLoop();代码中,把处理交给引擎自己去完成。接着进入。。。
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\CCDirector.cpp
复制代码
CCDisplayLinkDirector是CCDisplay的子类,从命名就应该可以很清晰的知道它的用处。通过CCDirector::sharedDirector()代码,得到的都是CCDisplayLinkDirector对象。通过drawScene()代码就可以实现场景的绘制了。而开篇我要寻找的那个东东,也就在里面了。。。
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\CCDirector.cpp
复制代码
做个游戏的应该都知道,我们的游戏一般是在一个死循环中渲染的,比如下面:
- float dt;
- while (1)
- {
- ...
- update(dt); //通过时间差更新数据
- present(dt);//通过时间差呈现、绘制游戏画面
- ...
- }
首先打开 ...\cocos2d-2.1rc0-x-2.1.2\samples\Cpp\TestCpp\proj.win32\main.cpp
- int APIENTRY _tWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine,
- int nCmdShow)
- {
- UNREFERENCED_PARAMETER(hPrevInstance);
- UNREFERENCED_PARAMETER(lpCmdLine);
- // create the application instance
- AppDelegate app; //实例化应用代理对象,这个对象是CCApplication的子类,
- //实现了applicationDidFinishLaunching()等方法,目的
- //目的是为了在底层框架中回调,做一些初始化或者结尾的工作
- CCEGLView* eglView = CCEGLView::sharedOpenGLView();//继承和封装了一些对Opengl接口的操作。不同平台实现不一样
- eglView->setViewName("TestCpp");
- eglView->setFrameSize(480, 320);
- return CCApplication::sharedApplication()->run();//一个单实例类,通过run方法进入引擎主循环
- }
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\platform\win32\CCApplication.cpp
- int CCApplication::run()
- {
- ......
- // Initialize instance and cocos2d.
- if (!applicationDidFinishLaunching())//AppDelegate的回调方法,主要就是初始化CCDirector等数据,方便显示第一个场景
- {
- return 0;
- }
- ......
- 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)//判断时间差是不是达到了到下一帧的条件
- { <span style="white-space:pre"> </span>//主要是看锁定多少的FPS
- nLast.QuadPart = nNow.QuadPart;
- CCDirector::sharedDirector()->mainLoop();//进入引擎的主循环
- }
- else
- {
- Sleep(0);
- }
- continue;
- }
- ......
- }
- return (int) msg.wParam;
- }
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\CCDirector.cpp
- void CCDisplayLinkDirector::mainLoop(void)
- {
- if (m_bPurgeDirecotorInNextLoop)//进入下一个主循环,也就是结束这次的主循环,就净化,也就是一些后期处理
- {
- m_bPurgeDirecotorInNextLoop = false;
- purgeDirector();
- }
- else if (! m_bInvalid)
- {
- drawScene();//绘制屏幕
-
- // release the objects
- CCPoolManager::sharedPoolManager()->pop();//释放一些没有用的对象,主要保件内存的合理管理
- }
- }
...\cocos2d-2.1rc0-x-2.1.2\cocos2dx\CCDirector.cpp
- void CCDirector::drawScene(void)
- {
- // calculate "global" dt
- calculateDeltaTime();//计算时间差
- //tick before glClear: issue #533
- if (! m_bPaused) //如果不暂停,就更新数据
- {
- m_pScheduler->update(m_fDeltaTime);//调度者对象,是整个框架中,非常重要的东东,他负责者引擎中精灵、动作等的调度
- //而里面所用的数据结构的组织,一定程度决定者引擎的效率。
- }
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- /* to avoid flickr, nextScene MUST be here: after tick and before draw.
- XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */
- if (m_pNextScene)
- {
- setNextScene();//如果有m_pNextScene对象不为空,就说明需要调用到新的场景中,
- //在其中onEnter()、onEnterTransitionDidFinish()等函数被回调。
- }
- kmGLPushMatrix();//opengl:把当前矩阵放到栈中
- // draw the scene
- if (m_pRunningScene)
- {
- m_pRunningScene->visit();//通过访问方法,去绘制场景中包含的每个层和每个层中的每个节点的draw,
- //这里面是一个递归的过程,其中transform()方法实现,opengl矩阵的变化<span style="white-space:pre"> </span>//,移动,旋转等。
- }
- // draw the notifications node
- if (m_pNotificationNode)
- {
- m_pNotificationNode->visit();//绘制通知节点,目前我也不知道这个是什么!
- }
-
- if (m_bDisplayStats)
- {
- showStats();
- }
- kmGLPopMatrix();//opengl:把当前矩阵从栈中移除,回复之前的矩阵
- m_uTotalFrames++;//记录总帧数
- // swap buffers
- if (m_pobOpenGLView)
- {
- m_pobOpenGLView->swapBuffers();//opengl:交换帧缓冲区,把绘制的东东显示在屏幕。
- }
-
- if (m_bDisplayStats)
- {
- calculateMPF();
- }
- }
好了,到目前为止,我们看到了,我们想看到的东东,开心了,第一次写博文,记录下自己的成长路,今天放假,玩去。。。 未来记下引擎核心之一的CCScheduler的工作方式和里面所用到的数据结构。
来自http://cocos2d.cocoachina.com/bbs/forum.php?mod=viewthread&tid=10881&extra=page%3D2