本文仅供个人记录和复习,不用于其他用途
什么是帧循环
我们之前对于帧已经有了一个基本的概念,事实上,游戏乃至图形界面都是不断的绘图,然而这些绘图必须遵守一定的逻辑,也就是所谓的游戏逻辑。游戏逻辑控制游戏的内容,会根据用户的输入和时间的流逝而改变。因此,游戏可以抽象为不断地重复以下动作:
- 处理用户输入
- 处理定时事件
- 绘图
游戏的主循环基本上就是如此,它会反复执行以上的动作,保持游戏的进程,直到玩家退出游戏。
mainLoop方法
CCDirector::mainLoop()方法是定义在CCDirector中的抽象方法,它的具体实现在CCDisplayLinkDirector类(3.0找不到的话就把CC去掉)。这个方法负责调用定时器、绘图、发送全局通知、并处理内存回收池。该方法按帧调用,每帧调用一次,而帧间间隔取决于两个因素:预设频率(默认为60帧每秒)和每帧计算量的大小。我们在玩游戏的时候都知道,如果电脑的配置较低,哪怕你设置的帧率为60,电脑的计算力也无法达到60帧每秒。因此,就会出现游戏画面不流畅。下面是从DisplayLinkDirector类中找到的关于mainLoop()方法的实现:
|
|
mainLoop()主要是先查看是否需要释放Director,一般是游戏结束时执行。第三个有一个drawScene()方法,从字面意义上来看就是绘制场景,遍历每一个节点进行绘图。最后将这一帧弹出内存回收池,删除这一帧的内容。具体代码如下:
|
|
可以发现drawScene主要用于处理OpenGL和一些细节,如计算FPS、帧间时间差等,这里我们主要进行了以下操作:
- 计算时间差,2帧之前的时间差,
calculateDeltaTime() - 定时任务调用
_scheduler->update(_deltaTime) - 事件处理
EventAfterUpdate - 设置当前的下一个场景,主要就是把当前场景释放掉,之后把
_nextScene设置为当前的场景 - 调用当前场景的渲染方法
_runningScene->render(_renderer) - 事件处理意思是
Visit调用完了,_eventAfterVisit - 调用渲染引擎进行渲染
_renderer->render() - 事件处理
_eventAfterDraw - 调用
openGLView平台提供的屏幕显示方法,_openGLView->swapBuffers()
游戏的开始
说起来,我们介绍了那么多概念,貌似还没有讲游戏是如何开始的。事实上,游戏的开始文件是main.h,也就是游戏的入口函数,位于win32目录下。查看源文件,能够发现如下代码:
|
|
这里可以看出,在入口函数中,首先创建了一个AppDelegate对象,AppDelegate继承自CCApplication,在创建AppDelegate对象的时候就会隐式调用CCApplication构造函数,在这个构造函数里边会将AppDelegate的this指针传递给全局共享对象sm_pSharedApplication,如下:
|
|
接下来调用Application::getInstance()->run()启动游戏,如下:
|
|
这里可以看到,run()启动了applicationDidFinishLaunching()方法。我们之前介绍过,这个方法用于设置游戏启动相关参数,同时也执行我们自定义的代码。
|
|
另外呢,在applicationDidFinishLaunching()中可以找到这一行代码。它设置了glview对象之后就开始运行场景,GLView主要就是就是负责窗口管理的工作。
|
|
至于Run()方法就是将m_running设置为true,用于启动。我们再来看看使用了m_running的方法:
|
|
可以看到,Rander()渲染方法执行了OnRendering()。而当m_running和m_initialized全为true时,便调用我们的mainLoop()方法。至此,便是游戏的主循环。至于具体的渲染过程,之后再讲。