HTML5 画布 - 使用剪辑擦除新圆圈后重新绘制新圆圈

HTML5 Canvas - Redrawing new circles after erasing them with clip

本文关键字:新圆圈 新绘制 绘制 擦除 画布 HTML5      更新时间:2023-09-26

我有一个独特的问题。

我正在用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/

谁能解释这种奇怪的行为?我没看到它来了?

代码有多个问题。

绘制蛇的代码(例如向上箭头函数)只是扩展当前路径。这是一个问题,因为绘制苹果的代码开始了一条新路径。请注意,在 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);
    }
}

保存/剪辑/还原调用位于绘制苹果的代码中。这些方法需要移动到擦除苹果的超时回调函数中。此外,擦除苹果的代码将需要重新创建路径(因为蛇形绘图可能会更改绘制苹果和擦除苹果之间的路径)。例如。。。

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);
}

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

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

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

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