我有一个独特的问题。
我正在用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/
任何人都可以解释这种奇怪的行为吗?我没有看到它的到来?
答案 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);
}
这些更改将使您接近预期。但是,仍然会有一些小问题。
绘制苹果时,苹果路径边缘会出现一些抗锯齿现象。清除操作可能会错过清除其中一些像素。清除操作后,您可能会看到苹果所在位置的半透明轮廓。清除苹果时,可以通过使用稍大的圆半径来解决此问题。
另一个问题是苹果可以在蛇的顶部绘制。擦除苹果也会抹掉蛇。这个问题没有一个简单的解决方法。您需要存储蛇的所有坐标,然后重绘全部或部分蛇。
从长远来看,您可能需要考虑评论中有关重构逻辑的建议,以跟踪所有对象并重绘每一帧的所有内容(或在每次更改后重绘所有内容)。