我一直致力于开发一款视频游戏,最近一直致力于将触摸屏功能合并到该程序中。但是,我注意到触摸事件往往会导致画布中的运动冻结。
这是我编写的一些代码来演示这一点:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="cnvs" width="400" height="400"></canvas>
<script>
var canvas, canvasContext;
var x = 0, y = 30;
var incrementor = 1;
window.onload = function() {
canvas = document.getElementById('cnvs');
canvasContext = canvas.getContext('2d');
colorRect(0, 0, canvas.width, canvas.height, 'white');
setInterval(updateAll, 1);
canvas.addEventListener('touchstart', touchStart);
canvas.addEventListener('touchend', touchEnd);
}
function touchStart(e) {
console.log(e);
}
function touchEnd(e) {
console.log(e);
}
function colorRect(p,a,i,n,t) {
canvasContext.fillStyle = t;
canvasContext.fillRect(p,a,i,n);
}
function updateAll() {
moveAll();
drawAll();
}
function moveAll() {
x += incrementor;
if(x > canvas.width - 20 || x < 0) {
incrementor = incrementor * -1;
}
}
function drawAll() {
colorRect(0, 0, canvas.width, canvas.height, 'black');
colorRect(x, y, 20, 20, 'red');
}
</script>
</body>
</html>
请注意,当您使用带有触摸屏的设备触摸画布时,程序似乎有点“卡顿”。并不一定会出现错误。事实上,程序运行没有任何错误。出现的唯一“错误”是,当调用触摸事件时,画布上的移动往往会冻结。
我的主要问题是:如何编写一个与此类似的程序来执行完全相同的任务,但又不会在进程中冻结程序?我没有任何使用 jQuery 或任何其他精美 JS 插件的经验,因此使用纯 JavaScript 来完成此操作的方法将对我的事业有所帮助。
您可能遇到了处理器过度工作的问题。
JavaScript 有一个非常有用的方法可以实现更好的渲染性能,这就是
Window
方法requestAnimationFrame(updateAll)
。就像 setInterval
但回调在浏览器呈现其内容的每一帧运行一次。
按照惯例,浏览器以 60fps 的速率渲染内容,该速率可以配置,也可以不配置。
但是您的代码使用
setInterval(updateAll, 1)
,这会导致您的代码每秒渲染图像一千次,而浏览器只会渲染其中的 60 次。您渲染的图像比需要的多 1940 倍。
请注意,这也是基于帧速率的测量,这很糟糕,因为如果它更大(例如 120fps),那么一切都会移动得更快而不是更平滑(游戏速度应该根据时间保持不变)。 .
由于后一个问题与实际问题无关,所以我将其放在一边。
使用下面的代码片段尝试您的代码:
var canvas, canvasContext;
var x = 0, y = 30;
var incrementor = 1;
// EDIT: Using this function to adjust the game velocity.
function speed(v) {
incrementor = v;
}
window.onload = function() {
canvas = document.getElementById('cnvs');
canvasContext = canvas.getContext('2d');
colorRect(0, 0, canvas.width, canvas.height, 'white');
canvas.addEventListener('touchstart', touchStart);
canvas.addEventListener('touchend', touchEnd);
// EDIT: Refresh the image with initial data.
updateAll();
}
function touchStart(e) {
console.log(e);
}
function touchEnd(e) {
console.log(e);
}
function colorRect(p,a,i,n,t) {
canvasContext.fillStyle = t;
canvasContext.fillRect(p,a,i,n);
}
function updateAll() {
moveAll();
drawAll();
// EDIT: Refresh the image on the next frame renderization.
requestAnimationFrame(updateAll);
}
function moveAll() {
x += incrementor;
if(x > canvas.width - 20 || x < 0) {
incrementor = incrementor * -1;
}
}
function drawAll() {
colorRect(0, 0, canvas.width, canvas.height, 'black');
colorRect(x, y, 20, 20, 'red');
}
<canvas id="cnvs" width="400" height="400"></canvas>
<div>
<button onclick="speed(1)">Speed 1</button>
<button onclick="speed(5)">Speed 5</button>
<button onclick="speed(10)">Speed 10</button>
</div>