UWP简单示例(三):快速开发2D游戏引擎
准备
IDE:Visual Studio
图形 API:Win2D
MSDN 教程:UWP游戏开发
游戏开发涉及哪些技术?
- 游戏开发是一门复杂的艺术,编码方面你需要考虑图形、输入和网络
- 以及相对独立的音频、物理仿真和 AI 引擎等,每一个部分单独开发都一场是旷日持久的“战斗”
- 美术、音乐和剧本也是组成游戏的重要部分,当然引擎不必包含这些素材
不要试图一个人去完成所有的事情
- 设计和实现完整的游戏引擎并不是一件轻松的事情
- 制定几个特定的目标,然后将有限的时间花在这些“简单的”但靠谱的目标上
- 得益于开源社区,你可以很便捷的找到各类完善的开源引擎,懂得借鉴它们并完善自己。
第一节 场景
你轻轻闭上眼睛,脑海中回想起过往的某个画面,美好的画面喻示着你此刻的心情还不错。我们称组成这个画面的所有元素就是一个场景(Scene)。
(上述定义从某个角度告诉我们,场景是一系列游戏元素的集合)
场景包含哪些元素?
- 摄像机 Camera
- 图层 Layer
- 物体 Body
- 外部资源 Resource
场景摄像机
- 摄像机是场景中一类特殊对象,几乎具有可视化对象的全部属性与行为,但它是不可见的
- 摄像机与场景绘制紧密相关,平面变换、效果和动画都将作用于摄像机裁剪时或裁剪后的画面
- 场景中允许多个摄像机存在,但同一时间最多一个会被激活
- 通过摄像机实现场景虚拟化,由可视化元素是否在摄像机视口内决定它是否要被绘制
资源加载与预绘制
- 场景绘制与更新前需要先加载外部资源和预绘制
- 外部资源包括贴图、音频、文本和用户自定义数据
- 预绘制完成内存占用较多的缓存对象的绘制
- 若加载花费一段时间,需要向用户提供加载动画
- 不同场景之间资源不共享,这意味着切换场景必须重新加载资源
图1-1 可视对象接口继承层次(仅供参考)
第二节 图层
你试图向我描述回忆画面,远处缥缈隐现的连绵山峰,近处一片相对开阔的草地,天空似乎还有着淅沥的小雨。不像3D画面可以天然的展现景深关系,2D需要依赖图层(Layer)来实现。
(分层绘制不仅能表达景深,还可以很容易地为不同图层定制不同的行为)
图层怎么分类?
- 静态层 StaticLayer
- 动态层 AnimateLayer
- UI层 ControlLayer
静态层
- 通常由一副静态图像组成,玩家不能改变其中的内容
- 一些景深丰富的游戏还会有超前景图层,它也是静态的
动态层
- 玩家直接控制的角色所在的图层
- 主景图层通常由区块( Tile )和角色( Character )组成
- 区块构成场景环境,角色则在区块上活动
- 区块严格意义上不是静态的,可能会有来自玩家的破坏
UI层
- 展现 UI 的图层,比如显示消息框、文本框或按钮
- 有时候用户接触的 UI 可能来自外部,而不是场景中的元素
图2-1 图层类继承层次(仅供参考)
第三节 物体
我对你的回忆产生了兴趣并希望了解更多的细节,你向我继续描述,草地上青草随风浮动,天空偶有不知名的鸟儿飞过。具体的某个可视化元素我们称之为物体(Body)。
(一般情况下,2D 游戏中的物体是一个 Sprite)
物体有哪些属性?
- 平面变换 Transform:描述元素的平面变换
- 外观 Appearance:描述元素的外观
- 附加组件 Compnent:表示附加在元素上的游戏组件
平面变换
- 平移 Translation :元素在场景中的位置
- 旋转 Rotation :元素绕旋转中心旋转
- 缩放 Scale :元素垂直或水平缩放
外观
- 可见性 Visible :元素是否可见
- 透明度 Opacity :元素不透明度
*模型与视图分离
- 模型是游戏中可视化对象的数据
- 视图是决定如何渲染模型的对象
- 分离的好处之一是同一模型可绑定不同的视图
- 改变一个模型的渲染行为,只要改变与它绑定的视图即可
图3-1 视图类继承层次(仅供参考)
第四节 行为
你继续回忆,脑海中画面不断的变化,有新的景象出现,也有旧的消失不见。画面中总有一些元素是动态的(Dynamic),它们具有自己特定的行为(Behavior)。
(行为就是游戏元素做出动作,发出声音,作出反应)
元素有哪些行为?
- 初始化 Start
- 更新 Update
- 事件 Event
- 绘制 Draw
初始化
- 完成元素初始化的操作
- 比如指定元素的初始位置,绑定事件等
- 通常在整个元素的生命周期中初始化只进行一次
- 多次初始化可能会导致某个事件多次绑定事件处理程序
更新
- 每帧调用并执行的操作
- 通常更新帧率与绘制帧率保持一致
- 有的游戏元素没必要每帧都更新,比如计算量大的 AI
事件
- 为某个事件提供事件通知
- 可以动态的为某个事件注册事件处理程序
- 事件处理机制可为游戏元素实现丰富的行为
绘制
- 只有可视化的对象具有该行为
- 为节约性能,一个可绘制的元素可以缓存成静态图像
- 为保证画面在不同机器上的流畅性,需要设定渲染级别
*元素集合变动
- 游戏过程中修改游戏元素集合会导致集合不能遍历
- 一种方法是先将集合改动的行为缓存起来,当一帧结束后再执行这些行为
- 另一种方法是使用线程安全的集合,在集合遍历期间的更新操作将会被阻塞
图4-1 不同行为预制件类继承层次(仅供参考)
第五节 组件
我吐槽你没有什么想象力,你描述的画面中蜻蜓和鸟儿都是在飞,而不是其中一个会在陆地上飞奔。通常不同的元素很有可能会具有相同的行为,这类行为可以封装为组件(Compnent)。
(组件有自己的属性、方法和事件,但它们不能独立存在,必须附加在游戏物体上)
有哪些类型的组件?
- 动画器 Animation
- 效果器 Effect
- 音效器 Audio
- 触发器 Trigger
- 命令器 Command
- 行为器 Behavior
动画器
- 附加于游戏对象的动画器在时间线的控制下播放一段动画
- 多种动画经常组合在一起,比如角色跳跃时既有帧位图动画也有按路径移动的动画
- 理想情况下,游戏中应使用尽可能多的动画来增强画面效果,使得游戏更具有吸引力
音效器
- 附加于游戏对象的音效器用于播放一段音频
- 音效对烘托游戏环境气氛起着十分关键的作用
- 音效器最有必要体现的是动态感和方位感
- 高性能的音效引擎应该是低延迟的且支持动态缓冲
- XAudio2 支持同步采样准确播放以及隐式源速率转换
效果器
- 平面变换 Transform :平移、旋转和缩放
- 高斯模糊 GaussianBlur :减少噪声或降低细节层次
- 颜色矩阵 ColorMatrix :特殊的位图颜色变化效果
- 光照效果 Light :点光源,方向光源,全局光照
- 阴影效果 Shadow :生成模糊的阴影
触发器
- 触发器由三个部分组成,事件、条件、动作
- 事件:当某个事件发生的时候就运行触发器
- 条件:判断是否达到指定的条件,如果没有达到条件将不执行动作
- 动作:条件通过后所要做的事情
命令器(行为器)
- 命令器和行为器是决定游戏对象如何进行动作的附加对象
- 命令器是行为器的超集,前者区别于后者是它在每帧都会有更新行为
- 很显然,行为器只是控制下一步的动作,命令器则是控制时间线上的一系列动作
图5-1 组件接口继承层次(仅供参考)
第六节 真实
你回应这是真实的回忆而不是梦境,鸟儿只会在蓝天翱翔。事实上,游戏不是真实的(Reality),只是感觉上有些真实。
(游戏中尽量让玩家感受真实的部分就是物理仿真与游戏AI)
物理引擎
- 物理引擎通过为刚性物体赋予真实的物理属性的方式来计算刚体运动、旋转和碰撞
- 为每个游戏或者每个游戏对象使用物理引擎并不是完全必要的
- 取决于需求,游戏运行时的物体引擎需要平衡实时性和高精度两者
Box2D 引擎
- Box2D 以固定的离散时间步长实现游戏物理世界的仿真
- Box2D 提供了支持像圆形或多边形这样的几何形状的刚体仿真
- Box2D 可用关节连接不同的形状,还可以包括关节马达和滑轮
游戏 AI
- 游戏 AI 是游戏中能够像人一样思考和行动的元素
- AI 设计需要考虑趣味性、随机性和难度三个因素
- AI 三大系统主要是感知系统、导航系统和决策系统
AI 分层
- 感知事件层:对输入的信息进行过滤和分配
- 行为层:具体描述如何执行指定动作
- 动画层:判断哪组动画更符合当前游戏状态
- 运动层:处理探路、碰撞和躲避等行为
- 短期决策层:AI 实体短幅视距上的智能处理层
- 长期决策层:AI 实体开阔视距上的智能处理层
- 基于位置的信息层:包括来自影响图、智能地形或类似结构的信息
*蜻蜓在地上飞奔
- 违背真实性或荒诞不经的设定虽然讨趣,但最好不要让玩家有上当的感觉
- 除非你在一开始就告诉他,如游戏名字叫《地上飞奔的蜻蜓》,玩家才可能会原谅你
图6-1 物理引擎关节类继承层次(仅供参考)
附录
《AI Game Engine Programming》[美] BrianSchwab 著
《Object-Oriented Game Development》[美] Julian Gold 著
《Ulimate Game Design-Building Game Worlds》[美] Tom Meigs 著