html画布流畅运动

时间:2014-08-31 19:25:32

标签: javascript html html5 canvas

我现在已经打破了一段时间了。我用画布在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);

尝试使用箭头键移动相机。按下一个键,你有时会看到跳动。

我真的希望有人可以帮我解决这个问题,因为我一直试图找出为什么会发生一段时间。

1 个答案:

答案 0 :(得分:0)

在我的桌面上,我得到了矩形的正常半光滑运动,但没有跳跃或撕裂。我猜这个问题发生在可用资源少于良好桌面的设备上。

你的代码看起来效率很高,但我确实在你的动画循环中看到了相当多的东西 - 但这不会导致你的跳跃和撕裂。

这是一个不那么狡猾的重构(不会解决你的问题):http://jsfiddle.net/m1erickson/0k2Ljth5/

可能导致您跳跃的是var dt = (curTime - prevTime) / 1000;。如果requestAnimationFrame由于某种原因无法执行循环(通常会导致其他系统任务需要花费时间),那么dt将大于预期,并且你的rect将“跳过”预期位置到达由更大dt

另一方面,撕裂是由新循环帧开始时不完整的先前绘图引起的。您要求的绘图量并不总是适合循环。撕裂的方法是减少画布在循环中必须完成的工作。