首页 > 解决方案 > 如何在 JS 的画布中更好地移动没有 clearRect() 的框?

问题描述

每个人。我打算在 JS 中开发一个类似 Piano Tiles 的游戏。我遇到的问题是我需要让几个可能出现在不同时间的图块移动,它让我不能使用 clearRect() 然后绘制下一个位置的图块,如果我这样做,我的多个图块会闪烁(因为当A瓷砖调用clearRect,B瓷砖将消失,这是不应该发生的)

我想出的解决方案是不使用 clearRect()清除整个屏幕,我只是清除我不想要的 Rectangle ,然后 fillRect (它的填充样式与我的背景颜色相同)再次填充这个小空矩形。

我的解决方案几乎可以达到我的目的,但我的代码中仍然存在一些缺陷。当我的黑色瓷砖移动时,仍然会出现一些微小的灰色矩形(并且很快就会消失)。

我想知道有没有更好的方法可以移动多个框(或矩形)?

PS:我的背景使用渐变,所以它可能使我的问题更加棘手。

以下是我的代码:

myTiles存储两个瓦片,paintWindow 函数针对绘制背景,我的解决方案是写在move() 函数中

var c = document.getElementById("piano");
var context = c.getContext("2d");

startGame();
function startGame(){
  paintWindow();
  myTiles = [];
  myTiles[0] = new Block(0);
  myTiles[1] = new Block(1);
}
function paintWindow(){
  my_gradient = context.createLinearGradient(0,0,0,600);
  my_gradient.addColorStop(0,"rgba(65,234,246,0.6)");
  my_gradient.addColorStop(1,"rgba(254,74,251,0.5)");

context.fillStyle = my_gradient;
context.fillRect(0,0,300,600);

context.beginPath();
context.moveTo(72,0);
context.lineTo(72,600);
context.strokeStyle = "white";
context.stroke();

context.beginPath();
context.moveTo(148,0);
context.lineTo(148,600);
context.strokeStyle = "white";
context.stroke();

context.beginPath();
context.moveTo(226,0);
context.lineTo(226,600);
context.strokeStyle = "white";
context.stroke();

context.beginPath();
context.moveTo(0,470);
context.lineTo(300,470);
context.strokeStyle = "white";
context.stroke();
}

function Block(index){
 this.index = index;
 this.appearPos = Math.floor(Math.random()*4);

 this.width = 70;
 this.height = 120;
 this.color = "black";
  switch(this.appearPos){
    case 0:
        this.x = 0;
        this.y = 0;
        break;
    case 1:
        this.x = 75;
        this.y = 0;
        break;
    case 2:
        this.x = 152;
        this.y = 0;
        break;
    case 3:
        this.x = 228;
        this.y = 0;
        break;
}
context.fillStyle = this.color;
context.fillRect(this.x,this.y,this.width,this.height);
this.interval = setInterval(move,10,this.index);
}
function move(index){
//context.clearRect(0,0,300,600);
//paintWindow();
myTiles[index].y += 1;
context.fillStyle = "black";
context.fillRect(myTiles[index].x,myTiles[index].y,70,120);

context.clearRect(myTiles[index].x,myTiles[index].y-2,70,2);
context.fillStyle = my_gradient;
context.fillRect(myTiles[index].x,myTiles[index].y-2,70,2);
}

标签: javascript

解决方案


我建议您不要为每个新块创建一个新间隔,而是创建一个间隔,您可以在其中一次更新所有块。这可能看起来像这样:

setInterval(moveAll,10);
function moveAll(){
    context.clearRect(0,0,c.width,c.height);

    for (var i=0;i<myTiles.length;i++){
        move(i);
    }
}

如果由于某种原因不能这样做,您还可以在单​​独的画布中绘制图块,以便在清除图块时保留背景:

<div>
    <canvas id="background" style="position:absolute;left:0;top:0;">
    <canvas id="tiles" style="position:absolute;left:0;top:0;">
</div>

这样,第二个画布将显示在第一个画布上,但背景仍然在它后面透明的地方可见。


推荐阅读