我现在已经打破了一段时间了。我用画布在javascript中写了一个太空游戏。我使用800x600分辨率和16x16瓷砖,我在视口中随时都有大约200-300个瓷砖。
当然,这对于重绘每一帧都太慢了所以我将它渲染到一个屏幕外的画布,每一面都是1个大的画布。移动时我只需移动屏幕外画布,只重新绘制新的图块。这可以在60fps下完美运行,即使有1000多个瓷砖。只有一个小故障,四处移动不是100%平滑。
我无法解释发生了什么,这是一种跳跃运动/屏幕撕裂。 我虽然这是我的代码中的一些错误,但是当我用1个tile创建一个简单的测试时,我有完全相同的错误。
以下是我的测试:http://jsfiddle.net/da7g9khj/1/
var prevTime = new Date().getTime();
function loop(time) {
requestAnimationFrame(loop);
var curTime = new Date().getTime();
var dt = (curTime - prevTime) / 1000;
prevTime = curTime;
var speed = 6;
if(keys.up) camera.y -= speed * dt;
if(keys.down) camera.y += speed * dt;
if(keys.left) camera.x -= speed * dt;
if(keys.right) camera.x += speed * dt;
var leftMost = (camera.x - scn.width / 2);
var topMost = (camera.y - scn.height / 2);
var screenCoordinates = {
x: (300 - leftMost) * 16,
y: (250 - topMost) * 16
};
rsc.ctx.clearRect(0, 0, scn.width * 16, scn.height * 16);
rsc.ctx.fillStyle = "black";
rsc.ctx.beginPath();
rsc.ctx.rect(Math.round(screenCoordinates.x), Math.round(screenCoordinates.y), 16, 16);
rsc.ctx.fill();
rsc.ctx.closePath();
}
var camera = {x: 300, y: 250}
var rsc = {};
var scn = {
width: 50,
height: 37.5
};
var keys = {
up: false,
down: false,
right: false,
left: false
};
rsc.canvas = document.getElementById("canvas");
rsc.canvas.width = 16 * scn.width;
rsc.canvas.height = 16 * scn.height;
rsc.ctx = rsc.canvas.getContext("2d");
window.onkeydown = function(e) {
switch(e.keyCode) {
case 40:
keys.down = true;
return false;
case 38:
keys.up = true;
return false;
case 37:
keys.left = true;
return false;
case 39:
keys.right = true;
return false;
}
};
window.onkeyup = function(e) {
switch(e.keyCode) {
case 40:
keys.down = false;
return false;
case 38:
keys.up = false;
return false;
case 37:
keys.left = false;
return false;
case 39:
keys.right = false;
return false;
}
};
requestAnimationFrame(loop);
尝试使用箭头键移动相机。按下一个键,你有时会看到跳动。
我真的希望有人可以帮我解决这个问题,因为我一直试图找出为什么会发生一段时间。
答案 0 :(得分:0)
在我的桌面上,我得到了矩形的正常半光滑运动,但没有跳跃或撕裂。我猜这个问题发生在可用资源少于良好桌面的设备上。
你的代码看起来效率很高,但我确实在你的动画循环中看到了相当多的东西 - 但这不会导致你的跳跃和撕裂。
这是一个不那么狡猾的重构(不会解决你的问题):http://jsfiddle.net/m1erickson/0k2Ljth5/
可能导致您跳跃的是var dt = (curTime - prevTime) / 1000;
。如果requestAnimationFrame由于某种原因无法执行循环(通常会导致其他系统任务需要花费时间),那么dt
将大于预期,并且你的rect将“跳过”预期位置到达由更大dt
。
另一方面,撕裂是由新循环帧开始时不完整的先前绘图引起的。您要求的绘图量并不总是适合循环。撕裂的方法是减少画布在循环中必须完成的工作。