Game Loop的几种实现方式
写这篇博客的目的是为了对game loop(游戏主循环)做一个全面的总结和介绍,包括它的定义,与之相关的专业术语(terminology),以及最重要的,对它的几种实现方式,从代码层次做一些介绍以及优缺点分析。 1.什么是Game Loop 对任何一个游戏开发者来说,game loop都应该不是一个陌生的概念。任何一款游戏都会有一个自己的game loop,它是整个游戏的核心,是游戏的心脏。具体什么是game loop,这是来自于Game Engine Architecture[2]上对于game loop的定义:game loop是对于一个游戏(或者一个游戏引擎)的所有子系统(subsystem)的周期性的更新。一个游戏会包含各种不同的子系统(比如渲染,物理,动画,AI等等),这些不同的子系统负责处理不同的游戏任务,game loop的实现方式就决定了这些子系统的任务执行的组织方式。而这些就决定了整个游戏的基础架构,同时也将决定game在不同的机器上将如何运行,在下面介绍game loop的不同实现方式时会对此有详细介绍。 game loop中所处理的逻辑和操作包罗万象,但一般可抽象为以下这几种模块: 处理输入:这些输入包括,来自于交互设备(键盘,鼠标,游戏控制器等等)的输入,来自于网络的输入; 系统更新(update):(根据输入或者自发的)对各个子系统进行更新,以决定当前的游戏状态; 渲染(render):对整个游戏场景进行渲染。 所以一个最最简单的game loop可以抽象为如下的这些伪代码: 2.相关术语 常常和渲染紧密相连的一个参数是FPS(frame per second),它指的是每秒显示设备在屏幕上进行绘制的频率。对于游戏来说,一般50-60的FPS是最优,最低也不要低于16帧[1]。游戏中还有一个容易被忽略的重要参数可以被称为游戏速度(game speed)[3],它指的是游戏状态每秒被更新的次数,容易与FPS混淆。一个通俗的理解和区别它们的方式可以是,FPS是render函数被调用的频率,而game speed则是update函数被调用的频率。 游戏是对实时性(real-time)要求很高的系统,所以在game loop中,time是尤其重要的一个因素。这里需要说的是,游戏中会包含好几种不同的时间,这些时间有着各自的时间线(timeline),并且在游戏中发挥着各自不同的重要作用[2]。 系统的真实时间(real time)。真实时间一般在操作系统被定义为从过去某个固定时间点(比如常见的一个时间点被称之为Epoch, 是1970年1月1日的0:00:00, UTC时间)到当前点总共逝去的时间。 游戏时间(game time)。一般情况下,游戏时间等于系统时间。但在某些特殊情况下,游戏时间可以发挥不同的作用:比如在游戏暂停的时候,需要停止更新游戏时间;在游戏需要以慢速运行时,可以用比真实时间低的频率来更新游戏时间,这在我们需要进行一些游戏调试的时候,尤其有用。下面会介绍到,一个好的game loop结构,可以有助于游戏调试,这对开发人员来说是非常重要的。 局部时间线(local timeline)。不管是一个动画,还是一个音频或者视频片段,都会有一个局部时间线。通过将此局部时间线以不同的方式映射到全局的时间线,可以灵活的控制片段以特定的方式进行播放。[2] 帧时间(frame time)。两次帧循环之间所间隔的时间,具体可看本文章的3.2.1节。 3.Game Loop的实现方式 OK,介绍了这么多跟game loop相关的概念,接下来进入正题,game loop的各种实现方式大盘点。 有一点需要强调的是,game loop在单线程的游戏系统中是一种情况,而在多线程的系统中又是另一个不同的故事。多线程对于系统会引入异常的复杂性,关于这个,可以看我之前的一篇关于游戏引擎多线程的文章:http://www.bennychen.cn/2011/01/关于游戏引擎多线程的一些整理和思考/。相比来讲,单线程要简单很多,这篇文章里以下的一些game loop的实现方式也主要是针对在单线程环境中的。 在单线程环境中,game loop按照实现方式可以分为以下这几种类型: 基于帧的(frame-based)game loop 基于时间的(time-based)game loop 可变频率(variable-step)game [...]


