小游戏之“太空防御者”的编写思路

这是啥?

太空防御者(SpaceDefender)是笔者模仿某DOS游戏的H5高清重制版,可以说是在怀旧啦。

在线试玩

玩法简介

游戏的玩法十分简单,敌方会源源不断地投放炸弹,玩家只能靠一个老旧的防空炮来守卫自己的基地。不同于大部分射击游戏,你的防空炮弹会在你鼠标点击的位置爆炸,而不是碰撞爆炸。

所以推算敌我炮弹的行动轨迹和爆炸范围就相当关键了,也就是所谓的“提前量”。

TIM截图20171211170948.png

整体架构

首先我们需要一张画布,它负责绘制图像,将一幅幅图像串联起来,也就实现了游戏的动画。
敌方会投掷炮弹,我方会发射炮弹,它们会按照一定的规则运动和爆炸,画布的每一帧,都需要体现出这些炮弹的位置和形象。
我们设计出一个信号nextFrame(下一帧),通知所有的炮弹需要更新它们的行为,以及画布需要绘制出下一帧的图像。

炮弹行为

具有不变的速度

速度=距离/时间。在2D游戏的世界中,距离可以通过平面坐标计算得出,时间就比较麻烦了。
玩过游戏的都明白,游戏的帧率并不是恒定的,会因为种种因素变化(比如硬件性能,渲染难度变化)。假如要求每秒稳定10帧,每帧的平均渲染时间为0.1秒,则要求0.1秒内必须把游戏场景渲染完成,而这恰恰是无法保证的。
实际情况往往是:每帧耗时=渲染时间+空闲时间。
所以炮弹在每一帧移动的距离=速度*上一帧的总耗时

空闲时间是有必要的,防止系统总是忙于不停地渲染画面,得不到一点空闲时间去处理其他事情。

设定了预定爆炸坐标

由上文得知,炮弹在每一帧移动的距离=速度*上一帧的总耗时,所以它的位置坐标不一定恰好等于规定的爆炸坐标(比如规定的是10,结果炮弹运动轨迹是9.2,10.1,11.0 ....),但是一些数学规律是不会变得,炮弹总是在不断接近目标点,然后掠过并远离目标点;所以一旦炮弹开始远离目标点了,它就该爆炸了。

如果被爆炸范围波及到,将会提前爆炸

这一点就比较简单了,炮弹需要检查自己是否在其他炮弹的爆炸范围之内。

帧率稳定

我们希望在什么游戏场景和硬件条件下,游戏都能有稳定的帧率,获得一致的体验。
上文分析过,每帧耗时=渲染时间+空闲时间,而渲染时间是不太稳定的,所以我们需要对应地修改空闲时间,使它们的和尽量接近我们的目标。

如果空闲时间远大于渲染时间,那么渲染时间的波动对于最终的每帧耗时影响很小,不需要去频繁的微调,这一点对于大部分js小游戏都是适用的。你只需要设置一个较大的空闲时间即可,如100ms。

渲染时间影响较大,我们就需要其他稳定策略了。

1.负反馈。很简单的一种策略,如果帧率过高,增大空闲时间,反正减少。这是很容易理解而且很容易实现的一种策略,帧率会在一个标准值上下小幅波动。
2.可靠信号源。假如你有一个很稳定的信号源,每隔一段时间发出可靠的信号,根据这个信号进行渲染自然是很稳定的了。缺点是条件比较苛刻,有时候甚至需要硬件的支持。