cocos2d-x 3.1.1学习笔记[23]寻找主循环 mainloop
2014-08-08 09:58
459 查看
文章出自于 http://blog.csdn.net/zhouyunxuan
cocos2d究竟是如何把场景展示给我们的,我一直很好奇。
凭个人猜想,引擎内部的结构类似于这样
在app开始运行时会调用里面的方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
来看看这个函数最后return YES之前的一行代码
cocos2d::Application::getInstance()->run();
没错,就是这个,然后我们进入到run函数里面来看个究竟
然后我们继续跟进看看startMainLoop
CADisplayLink,需要加入QuartzCore.framework
这个函数类似于update函数,默认每秒被调用60次,现在我们再进入doCaller函数吧
其实Director::getInstance();返回的不是Director,被骗了好久-= -
程序的主要逻辑都通过调用mainloop来完成,这个方法负责调用计时器,绘图,发送全局通知,并处理内存回收池,这个方法按帧调用,每帧调用一次,而帧之间取决于两个因素,一个是预设的帧频(默认为每秒六十次),另一个是每帧的计算量大小,当逻辑处理与绘图计算量过大时,设备无法完成每秒六十次的绘制,此时帧率就会降低。
然后我们接着看看这伟大的 drawScene里面做了什么吧!
最初提出来的结构和发现的结构还是有点相似的。只不过引擎更友好的抽象封装出来了,且做了很多防止异常的处理,程序员还都是很小心的嘛。。。
调用的CADisplayLink是ios平台的,如果换成其他平台就不一样啦。毕竟win是木有CADisplayLink的。
不相信?
好吧,我们来看看win是如何调用的吧,首先找到Application::run()函数。
Sleep(0)是指CPU交出当前线程的执行权,让CPU去执行其他线程。也就是放弃当前线程的时间片,转而执行其他线程。
一般来说,如果当前线程比较耗时比较占CPU资源,可以在结尾处加上Sleep(0), 这样效率会得到大大的提高。
看了win上面的调用,发现和我一开始的猜想更像有木有!!!
有时候,做笔记记录下学习过程也挺不错的。
肯定没人会转载的- -
但是为了防止蜘蛛爬走了我的文章,我还是注释下- -
文章出自于 http://blog.csdn.net/zhouyunxuan
cocos2d究竟是如何把场景展示给我们的,我一直很好奇。
凭个人猜想,引擎内部的结构类似于这样
while(true) { if(update_span < min_update_span) { update_game(); if(done) { break; } } else { cal_update_span(); } }
在app开始运行时会调用里面的方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
来看看这个函数最后return YES之前的一行代码
cocos2d::Application::getInstance()->run();
没错,就是这个,然后我们进入到run函数里面来看个究竟
int Application::run() { if (applicationDidFinishLaunching()) { //这个函数在这里调用了startMainLoop [[CCDirectorCaller sharedDirectorCaller] startMainLoop]; } return 0; }
然后我们继续跟进看看startMainLoop
-(void) startMainLoop { // Director::setAnimationInterval() is called, we should invalidate it first [displayLink invalidate]; displayLink = nil; //给CADisplayLink传了一个doCaller函数,让CADisplayLink不断的调用 displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)]; //设置调用频率 [displayLink setFrameInterval: self.interval]; //开始循环吧! [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; }
CADisplayLink,需要加入QuartzCore.framework
这个函数类似于update函数,默认每秒被调用60次,现在我们再进入doCaller函数吧
-(void) doCaller: (id) sender { cocos2d::Director* director = cocos2d::Director::getInstance(); [EAGLContext setCurrentContext: [(CCEAGLView*)director->getOpenGLView()->getEAGLView() context]]; //终于进入到这场表演的主角了,我期待了好久!!! director->mainLoop(); }
其实Director::getInstance();返回的不是Director,被骗了好久-= -
Director::getInstance() 返回的并不是Director,而是Director的子类DisplayLinkDirector(); Director* Director::getInstance() { if (!s_SharedDirector) { s_SharedDirector = new DisplayLinkDirector(); s_SharedDirector->init(); } return s_SharedDirector; }
程序的主要逻辑都通过调用mainloop来完成,这个方法负责调用计时器,绘图,发送全局通知,并处理内存回收池,这个方法按帧调用,每帧调用一次,而帧之间取决于两个因素,一个是预设的帧频(默认为每秒六十次),另一个是每帧的计算量大小,当逻辑处理与绘图计算量过大时,设备无法完成每秒六十次的绘制,此时帧率就会降低。
void DisplayLinkDirector::mainLoop() { //是否在下一循环中清除 //bool _purgeDirectorInNextLoop; // this flag will be set to true in end() if (_purgeDirectorInNextLoop) { log("clear director"); _purgeDirectorInNextLoop = false; //会做一些清理 purgeDirector(); } //如果不清除的话(且为合法的)ps:一般都是会进入到这里,然后进行绘制等等。 else if (! _invalid) { //画场景 drawScene(); // release the objects PoolManager::getInstance()->getCurrentPool()->clear(); } }
然后我们接着看看这伟大的 drawScene里面做了什么吧!
void Director::drawScene() { //计算时间增量 // calculate "global" dt calculateDeltaTime(); // 如果两帧间隔时间太短(_deltaTime等于0)就直接忽略这次的绘制 // FLT_EPSILON 是 __FLT_EPSILON__ 的宏,__FLT_EPSILON__ 是c99的特征,它是满足 x+1.0不等于1.0的最小的正数,直接输出为0。 if(_deltaTime < FLT_EPSILON) { return; } // if (_openGLView) { _openGLView->pollInputEvents(); } //tick before glClear: issue #533 //只要游戏没有暂停,调度器神马的就会在这里被执行。 if (! _paused) { _scheduler->update(_deltaTime); _eventDispatcher->dispatchEvent(_eventAfterUpdate); } 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 (_nextScene) { setNextScene(); } pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); //画场景 if (_runningScene) { _runningScene->visit(_renderer, Mat4::IDENTITY, false); _eventDispatcher->dispatchEvent(_eventAfterVisit); } // 画通知节点 if (_notificationNode) { _notificationNode->visit(_renderer, Mat4::IDENTITY, false); } //如果设置了显示debug信息,就会在这里进行每帧的更新。 if (_displayStats) { showStats(); } _renderer->render(); _eventDispatcher->dispatchEvent(_eventAfterDraw); popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _totalFrames++; // 交换缓冲区 if (_openGLView) { _openGLView->swapBuffers(); } //计算fps上的信息 if (_displayStats) { calculateMPF(); } }
最初提出来的结构和发现的结构还是有点相似的。只不过引擎更友好的抽象封装出来了,且做了很多防止异常的处理,程序员还都是很小心的嘛。。。
调用的CADisplayLink是ios平台的,如果换成其他平台就不一样啦。毕竟win是木有CADisplayLink的。
不相信?
好吧,我们来看看win是如何调用的吧,首先找到Application::run()函数。
//如果窗口不关闭 while(!glview->windowShouldClose()) { //计算时间 QueryPerformanceCounter(&nNow); //两帧间距时间要大一点才给你画哦 if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart) { //上一帧的时间就等于现在这一帧,用于下次计算两帧的间隔时间。 nLast.QuadPart = nNow.QuadPart; //进入到我们伟大的mainloop了,是不是有点小激动 - - director->mainLoop(); glview->pollEvents(); } else { //神马!睡0秒。好吧,光是看表面还是很骗人的。 Sleep(0); } }
Sleep(0)是指CPU交出当前线程的执行权,让CPU去执行其他线程。也就是放弃当前线程的时间片,转而执行其他线程。
一般来说,如果当前线程比较耗时比较占CPU资源,可以在结尾处加上Sleep(0), 这样效率会得到大大的提高。
看了win上面的调用,发现和我一开始的猜想更像有木有!!!
有时候,做笔记记录下学习过程也挺不错的。
肯定没人会转载的- -
但是为了防止蜘蛛爬走了我的文章,我还是注释下- -
文章出自于 http://blog.csdn.net/zhouyunxuan
相关文章推荐
- cocos2d-x 3.1.1学习笔记[23]寻找主循环 mainloop
- cocos2d-x 3.1.1 学习笔记[11] http请求 + json解析
- cocos2d-x 3.1.1 学习笔记[7]Action progress 不仅仅是可以做cd的动画
- cocos2d-x 3.1.1 学习笔记[18] Sprite创建之旅
- cocos2d-x 3.1.1 学习笔记[21]cocos2d-x 创建过程
- cocos2d-x 3.1.1 step by step 学习笔记5 菜单使用
- cocos2d-x 3.1.1 学习笔记[4]GridActions 网格动画
- cocos2d-x 3.1.1 step by step 学习笔记3 Win32平台下中文乱码问题
- cocos2d-x 3.1.1 学习笔记[19] ClippingNode 可以镂空别的精灵
- cocos2d-x 3.1.1 学习笔记[15] Shader 著色器
- cocos2d-x 3.1.1 学习笔记[16] Particle 粒子效果
- cocos2d-x 3.1.1 step by step 学习笔记7 场景与层
- Cocos2d-x 3.1.1 学习笔记(一)关联程序逻辑与CocosStudio导出文件
- cocos2d-x 3.1.1 学习笔记[20] 像素级触摸处理
- cocos2d-x 3.1.1 学习笔记[9]scheduler 调度器
- cocos2d-x 3.1.1 学习笔记[6]ScrollView 可以拖动的Layer
- cocos2d-x 3.1.1 学习笔记[10]序列帧动画
- cocos2d-x 3.1.1 学习笔记[3]Action 动作
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》第四步--地图循环&主角添加动作
- cocos2d-x 3.1.1 学习笔记[21]cocos2d-x 创建过程