AxeSlide软件项目梳理 canvas绘图系列知识点整理
游戏主循环介绍
我们利用“游戏主循环”的机制来绘制动态的画布,渲染循环。
我们首先补充一下游戏主循环的知识。
“游戏主循环”是一种能够随时间改变状态的用于渲染动画和游戏的技术。它的核心是一个尽可能频繁地运行的方法,来接收用户输入,更新随时间改变的状态,然后绘制当前帧。由于游戏需要根据输入、游戏内状态的改变来不间断地更新游戏画面,所以游戏的主循环往往看起来像一个“死循环”,那么这个“死循环”是如何工作的?
主循环主要做什么?
1.处理游戏逻辑(输入、AI、事件处理)
2.执行渲染操作(更新游戏画面)
整个游戏会按如下流程运转。
该图中的五个方法它们的作用解释如下。
Initialize方法用于初始化与游戏相关的对象,比如初始化图形设备、游戏环境设置等。
LoadContent方法在Initialize方法之后调用,它用于加载游戏所需要的图形或其它素材,比如模型、图片、声音等。
Update和Draw方法构成了游戏循环。
Update方法用于改变和控制游戏的状态,主导着游戏逻辑的进行。
Draw方法用于在屏幕上绘制我们的场景、Sprite。要注意的是,我们应该尽可能少的在Draw方法中处理游戏逻辑——它们应该在Update方法中被处理。Draw方法仅仅负责绘制。
Update和Draw方法都接受一个GameTime类型的参数,GameTime有什么作用了?这个参数可以帮助我们依据实际的游戏时间而不是处理器的速度来决定动画或其它事件的发生时刻。
应用到项目中
下面展示几段在我们实际的项目中实际的代码。
下面的函数run方法是循环开启的入口:
1 public run() { 2 var that = this; 3 var FRAMES_PER_SECOND: number = 30;//最大帧率,每秒刷新的次数 4 var SKIP_TICKS: number = 1000 / FRAMES_PER_SECOND;//两次绘制之间的时间间隔 5 var next_game_tick: number = Date.now();//第一次绘制开始计时 6 var loop = function () { 7 var curTime = Date.now(); 8 if (curTime >= next_game_tick) { 9 next_game_tick = curTime; 10 that.update(); 11 that.draw(); 12 } 13 next_game_tick += SKIP_TICKS; 14 15 window.requestAnimationFrame(loop); 16 } 17 window.requestAnimationFrame(loop);
18 }
window.requestAnimationFrame(callback) 方法请求浏览器在下一次重绘之前尽可能快地调用特定的方法。它是渲染动画专用的 API,但你也可以用 setTimeout 方法设置一个短的超时时间来达到相似的效果。如下对requestAnimationFrame 进行重写:
window.requestAnimationFrame = (function () {
return return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||function (callback) {
window.setTimeout(callback, 1000 / 40); };
})();
that.update()更新画布上每个元素的位置和属性
that.draw()绘制新一帧,根据每个元素的当前状态将其绘制到画布上
我们在绘制draw之前进行了判断if (curTime >= next_game_tick)后,再确定要进行一次绘制。这是因为如果将loop()置于循环中放任不管,帧率会居高不下,与此同时机器的CPU使用率高居不下,于是产生了一种固定帧率的做法。我们这里帧率最大30