cocos2dx win32下的MainLoop分析(启动流程)
来源:互联网 发布:雷霆机甲数据没雷诺好 编辑:程序博客网 时间:2024/04/29 07:40
大家都知道,游戏其实就是在死循环中无限绘制,渲染的过程,里面参杂了许多操作,接下来在win32中查看一下cocos2dx的循环过程
一般游戏主循环的简单逻辑如下
float dt;while (1)
{
...
update(dt); //通过时间差更新数据
present(dt);//通过时间差呈现、绘制游戏画面
...
}
我是用VS在WIN32平台下查看,要分析cocos2dx的启动流程那么就从main函数开始吧,打开main.cpp文件可以看到这里有win32的入口函数,
下方代码为main函数中的核心代码
// 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方法进入引擎主循环
接着进入 CCApplication::run();\win32\CCApplication.cpp
int CCApplication::run(){ PVRFrameEnableControlWindow(false);//这个好像是专门用于windows的,写注册表禁用pvr frame。 // Main message loop: MSG msg; //获取cpu滴答数相关数据结构,可以认为是高精度的计时器。 LARGE_INTEGER nFreq; LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nLast); // Initialize instance and cocos2d. //执行AppDeletegate重载的applicationDidFinishLaunching函数,如果进入这个函数里边可以看到这个函数里代码初始化了cocos2dx的导演类对象、文件模块对象,设置帧数创建场景等等。 if (!applicationDidFinishLaunching()) { return 0; } //创建窗口,并显示。 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.控制帧数的。<span style="font-family: Arial, Helvetica, sans-serif;">判断时间差是不是达到了到下一帧的条件</span>
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);//如果不需要绘制下一帧那么释放CPU控制权。 } 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;}
从run()函数代码可以看出来,渲染主要发生在CCDirector::sharedDirector()->mainLoop();里边。mainLoop()函数循环检查程序是否退出的标志位(m_bPurgeDirecotorInNextLoop,导演类调用end()方法将会使这个标志位记为true。这个方法在窗口过程收到WM_CLOSE消息的时候调用的),如果为true则清除资源。如果m_bPurgeDirecotorInNextLoop为false并且 m_bInvalid 并没有被置为true(这个变量由startAnimation()和stopAnimation()控制) ,那么绘制场景以及检查是否需要释放没有引用计数的内存资源。
void CCDisplayLinkDirector::mainLoop(void)//实际上CCDirector::sharedDirector();获取的是CCDisplayLinkDirector类型对象。{ if (m_bPurgeDirecotorInNextLoop)//是否停止渲染。进入下一个主循环,也就是结束这次的主循环,就净化,也就是一些后期处理 { m_bPurgeDirecotorInNextLoop = false; purgeDirector(); } else if (! m_bInvalid)//可以通过调用stopAnimation()的方式停止渲染,在win32下通常在对窗口进行缩小的时候会被调用。 { drawScene();//绘制屏幕 // release the objects CCPoolManager::sharedPoolManager()->pop(); //释放一些没有用的对象,主要保件内存的合理管理 }}
CCDisplayLinkDirector是CCDisplay的子类,从命名就应该可以很清晰的知道它的用处。通过CCDirector::sharedDirector()代码,得到的都是CCDisplayLinkDirector对象。通过drawScene()代码就可以实现场景的绘制了
// Draw the Scenevoid CCDirector::drawScene(void){ // calculate "global" dt calculateDeltaTime();//计算时间差 //tick before glClear: issue #533 if (! m_bPaused)//如果不暂停,就更新数据 m_pScheduler->update(m_fDeltaTime);//调度者对象,是整个框架中,非常重要的东东,他负责者引擎中精灵、动作等的调度,而里面所用的数据结构的组织,一定程<span style="white-space:pre"></span>度决定者引擎的效率。 } 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()方法实现,open<span style="white-space:pre"></span>gl矩阵的变化 //,移动,旋转等。 } // draw the notifications node if (m_pNotificationNode) { m_pNotificationNode->visit()//绘制通知节点 } if (m_bDisplayStats) { showStats(); } kmGLPopMatrix();//opengl:把当前矩阵从栈中移除,回复之前的矩阵 m_uTotalFrames++;//记录总帧数 </span> // swap buffers if (m_pobOpenGLView) { m_pobOpenGLView->swapBuffers();//opengl:交换帧缓冲区,把绘制的东东显示在屏幕。 } if (m_bDisplayStats) { calculateMPF(); }}
参考http://blog.csdn.net/crazy_number/article/details/37915145
0 0
- cocos2dx win32下的MainLoop分析(启动流程)
- cocos2dx-mainloop
- cocos2d-x 游戏引擎的处理流程 MainLoop主循环(下)
- Cocos2dx lua 启动流程
- cocos2dx 执行流程分析
- Win32应用程序的加载与启动分析
- Win32应用程序的加载与启动分析 .
- VS2010-win32下cocos2dx控制台打印的方法
- VS2010-win32下cocos2dx控制台打印的方法
- VS2010-win32下cocos2dx控制台打印的方法
- VS2010-win32下cocos2dx控制台打印的方法
- bootloader的启动流程分析
- Linux的启动流程分析
- Activity 的启动流程分析
- STM32的启动流程分析
- Activity的启动流程分析
- Service的启动流程分析
- ContentProvider的启动流程分析
- 第三方静态库编译:ZBar编译libZbar.a
- 【android】NDK开发编译C++文件出现Type 'jint' could not be resolved和Unresolved inclusion: <jni.h>的解决办法
- 修改dired插件
- 不可以!
- 【android】解决NDK开发中的 Method 'NewStringUTF' could not be resolved
- cocos2dx win32下的MainLoop分析(启动流程)
- 使用Python开发Kafka消息生产者
- IText构造PDF文件
- setStyleSheet 设置多个属性
- Files类的常用方法Guava
- Pidgin下使用Gtalk问题
- SQL语句
- 浅谈HTTP中Get与Post的区别
- FFMPEG 中dts和pts区别