HTML5 Canvas - 使用剪辑删除后重新绘制新圆圈

时间:2016-01-14 17:05:59

标签: javascript html5 canvas

我有一个独特的问题。

我正在用HTML5和Canvas创建一个蛇游戏

我有一个随机生成苹果的功能,并在一段时间后将其删除。要删除圈子,您必须使用clip()函数,然后使用clearRect()

但是,使用剪辑功能后,您将无法再绘制新的圆圈。

我找到的解决方案是使用ctx.save()ctx.restore()。但是,如果你玩游戏,你会发现当圆圈消失并出现新的圆圈时,蛇会变得疯狂。

我怀疑这与我使用保存和恢复功能有关。

以下是有问题的具体代码

var width = canvas.width;
var height = canvas.height;
var applesArray = [];            // Store the coordinates generated randomly

// Generates a random coordinate within the confines of the canvas and pushes it to the apples array
function randCoord() {
    var coord = Math.floor(Math.random() * height);
    applesArray.push(coord);
    return coord;
}

function generateApples() {
    ctx.beginPath();
    ctx.fillStyle = "green";
    ctx.arc(randCoord(),randCoord(),3,0, 2 * Math.PI);
    ctx.fill();
    ctx.save();           // To redraw circles after clip, we must use save
    ctx.clip();           // Allows only the circle region to be erased
    setTimeout(function() {
        ctx.clearRect(0, 0, width, height);
    },3000);
    ctx.restore();       // We must restore the previous state.
}

setInterval(function() {
    generateApples();
},4000);

你可以在这里玩游戏

https://jsfiddle.net/2q1svfod/9/

任何人都可以解释这种奇怪的行为吗?我没有看到它的到来?

1 个答案:

答案 0 :(得分:1)

代码有多个问题。

绘制蛇的代码(例如upArrow函数)只是扩展当前路径。这是一个问题,因为绘制苹果的代码开始了一条新路径。请注意,在Apple绘图代码中保存/恢复没有帮助,因为路径不是保存/恢复状态的一部分。绘制蛇的代码需要开始一条新路径。例如......

function upArrow() {
    if (direction == "up") {
        goUp = setInterval(function() {
            ctx.beginPath();
            ctx.moveTo(headX, headY);
            ctx.lineTo(headX, headY - 10);
            ctx.stroke();
            headY -= 10;
        }, 400);
    }
}

保存/剪辑/恢复调用位于绘制苹果的代码中。需要将这些方法移动到删除apple的超时回调函数中。此外,删除苹果的代码将需要重新创建路径(因为蛇绘图可能已经改变了绘制苹果和删除苹果之间的路径)。例如......

function generateApples() {
    var cx = randCoord();
    var cy = randCoord();
    ctx.beginPath();
    ctx.fillStyle = "green";
    ctx.arc(cx, cy,3,0, 2 * Math.PI);
    ctx.fill();
    setTimeout(function() {
        ctx.beginPath();
        ctx.arc(cx,cy,3,0, 2 * Math.PI);
        ctx.save();
        ctx.clip();
            ctx.clearRect(0, 0, width, height);
        ctx.restore();
    },40000);
}

这些更改将使您接近预期。但是,仍然会有一些小问题。

绘制苹果时,苹果路径边缘会出现一些抗锯齿现象。清除操作可能会错过清除其中一些像素。清除操作后,您可能会看到苹果所在位置的半透明轮廓。清除苹果时,可以通过使用稍大的圆半径来解决此问题。

另一个问题是苹果可以在蛇的顶部绘制。擦除苹果也会抹掉蛇。这个问题没有一个简单的解决方法。您需要存储蛇的所有坐标,然后重绘全部或部分蛇。

从长远来看,您可能需要考虑评论中有关重构逻辑的建议,以跟踪所有对象并重绘每一帧的所有内容(或在每次更改后重绘所有内容)。