给DOM开发者的游戏开发指南-04.高性能鸟

241 阅读2分钟

仓库地址:github.com/haiyoucuv/W…

引入概念:requestAnimationFrame 更新和渲染的抽离

经过上一节的操作,我们已经得到了一只演员鸟

众所周知,现在的游戏玩家都鬼的很,游戏没个高帧率他都不玩。

一般人游戏30帧就感觉比较流畅,可是这群游戏玩家,非要60帧才看着舒服

一、概念解释,什么是帧

帧率表示视频、游戏每秒钟刷新画面的次数
60帧即每秒钟刷新60次画面

一般电影的帧率是23.97frame/s,而游戏,低于45帧,会感到明显卡顿

为什么电影只需要24帧就比较流畅呢?

是因为摄影机记录的是1/24秒的所有光线信息,可以理解电影是无数张快门时间是1/24秒的照片同步播放组成的

而游戏计算出来的只有那一瞬间的画面,没有一个时间段内的光线信息,所以需要更高的帧率

因此我们就知道了我们的游戏需要高帧率的重要性了

二、requestAnimationFrame

理解了什么是帧就得出来,一个游戏60帧,每帧的时间是,1/60,约等于16.667ms;

我们大可以把setInterval的延时改成16.667

但是,众所周知,浏览器提供的延时函数都不靠谱,我们无法通过它得到稳定了60帧画面

隆重的介绍 requestAnimationFrame

requestAnimationFrame详解
被誉为神器的requestAnimationFrame

这个是一个浏览器给我们提供的API
借助这个API我们可以在浏览器这个平台很好的控制每秒60帧的帧率

接下来我们将数据更新和渲染更新拆分为两个函数

/**
 * 计算Bird的位置(数据更新)
 */
function update() {
	// 计算新的top
	if (pos.top !== clickPos.top) {
		const dis = clickPos.top - pos.top; // 计算差值
		const dir = dis > 0 ? 1 : -1;  // 计算在top上移动的方向 1 正向移动 或 -1 反向移动;

		// 如果速度过快,本次移动直接过头了(即差值<速度),就直接移动到指定top
		if (Math.abs(dis) < speed) {
			pos.top = clickPos.top;
		} else {
			pos.top = pos.top + dir * speed;    // 计算新的top,新的位置 = 之前的位置 + 方向 * 速度
		}
	}

	// 用相同的方式计算left
	if (pos.left !== clickPos.left) {
		const dis = clickPos.left - pos.left;
		const dir = dis > 0 ? 1 : -1;

		if (Math.abs(dis) < speed) {
			pos.left = clickPos.left;
		} else {
			pos.left = pos.left + dir * speed;
		}
	}
}

/**
 * 更新显示对象位置(渲染)
 */
function render() {
	bird.style.top = pos.top + "px";
	bird.style.left = pos.left + "px";
}

然后用requestAnimationFrame来创建一个主循环,在主循环中依次调用这两个函数

function loop() {
	requestAnimationFrame(loop);    // 循环调用requestAnimationFrame
	update();   // 先数据更新
	render();   // 后渲染更新
}

loop();

再次运行案例,我们得到了更流畅,性能更高的Bird了