Commit 2faf2811 authored by 邱旭's avatar 邱旭

04.高性能鸟

parent 452ed2f1
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<title>04.高性能鸟</title>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#bird {
/* 大小 */
width: 50px;
height: 50px;
/* 颜色 */
background-color: #f00;
/* 位置 */
position: absolute;
/* 旋转、缩放等属性 */
transform: scale(1, 1) rotate(45deg);
/* 锚点 */
transform-origin: center;
}
</style>
</head>
<body>
<div id="bird"></div>
</body>
<script>
const bird = document.getElementById("bird");
const speed = 15; // bird的速度 每次移动多少距离
const pos = { // bird的位置 bird当前的位置
top: 150,
left: 150,
}
const clickPos = { // 鼠标点击的位置 bird将要的到达的位置
top: 150,
left: 150,
}
// 使用mousedown监听鼠标按下,并获得鼠标点击的位置
const mouseDown = (e) => {
// 记录bird将要到达的位置,使用动画慢慢到达
clickPos.top = e.clientY;
clickPos.left = e.clientX;
}
document.addEventListener('mousedown', mouseDown);
/**
* 计算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";
}
function loop() {
requestAnimationFrame(loop); // 循环调用requestAnimationFrame
update(); // 先数据更新
render(); // 后渲染更新
}
loop();
</script>
</html>
# 高性能Bird
引入概念:`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](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame)
[requestAnimationFrame详解](https://segmentfault.com/a/1190000020639465?utm_source=tag-newest)
[被誉为神器的requestAnimationFrame](https://www.cnblogs.com/xiaohuochai/p/5777186.html)
这个是一个浏览器给我们提供的API
借助这个API我们可以在浏览器这个平台很好的控制每秒60帧的帧率
接下来我们将数据更新和渲染更新拆分为两个函数
```javascript
/**
* 计算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`来创建一个主循环,在主循环中依次调用这两个函数
```javascript
function loop() {
requestAnimationFrame(loop); // 循环调用requestAnimationFrame
update(); // 先数据更新
render(); // 后渲染更新
}
loop();
```
再次运行案例,我们得到了更流畅,性能更高的Bird了
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment