请求用于循环问题的绘图

时间:2017-06-30 18:31:13

标签: javascript for-loop html5-canvas requestanimationframe

我正在制作俄罗斯方块游戏 - 仍然 - 并且我正在尝试使用requestAnimationFrame在黑板上绘制我的T片。

这就是问题所在。 requestAnimationFrame绘制了2次,然后即使for循环仍在运行也停止绘制。也就是说,经过两次,我只看到黑色背景。当我评论出黑色背景时,这件作品显示/动画就好了。

我真的不知道为什么会这样。

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

const T = [
        [
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],

       [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],

       [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0]
        ],

        [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],
    ]

    var piece = T[0];

    const player = {
        position: {x: 5, y: -1},
        piece: piece,
    }

function colorPiece(piece, offset) {
    for(y = 0; y < piece.length; y++) {
        for(x = 0; x < piece.length; x++) {
            if (piece[y][x] !== 0) {
                ctx.fillStyle = "red";
                ctx.fillRect(x + offset.x, y + offset.y, 1, 1);
            }
        }
    }
}

function drawCanvas() {
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.scale(20, 20);
    colorPiece(player.piece, player.position);
}

function update() {
        drawCanvas();
        requestAnimationFrame(update);
}

update();

1 个答案:

答案 0 :(得分:1)

好的 - 工作版,带有小提琴here。一些变化。最大的是:

  • 请勿使用canvas.scale(),因为它是每this累计的(请参阅“更多示例”)。相反,对于块20x20使用20*x20*y

    修改基于further test,看起来这是最重大的变化。

  • 重命名,以便piece不会用作所有变量,player中的字段名称和参数colorPiece

  • this fiddle examplectx创建内容移至update()(现称为doUpdate())。将ctx作为参数传递给其他函数。

  • 将红色fillStyle分配移出循环,因为您只需要执行一次,然后您可以在不更改的情况下绘制所有矩形。

  • 在循环中:

    for(var y = 0; y < thePiece.length; ++y) {
        for(var x = 0; x < thePiece[y].length; ++x) { ... } }
    

    使用x保留yvar in the local scope

    当你准备好穿过一行时,那是thePiece[y].length,即行的长度。使用thePiece.lengthT的非方形元素会被破坏。

  • 添加了<p id="log"/>和javascript framenum,以便我可以看到确实正在调用doUpdate()

如果您还没有,请确保在测试时打开控制台,以便查看错误消息。如果drawCanvas导致错误,则会阻止再次调用requestAnimationFrame。我认为这就是the fiddle I linked above开头而不是框架绘制功能的 end 调用requestAnimationFrame的原因。

希望这有帮助!

代码

const T = [
        [
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],

       [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],

       [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0]
        ],

        [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0]
        ],
    ]

    const player = {
        position: {x: 5, y: -1},
        piece: T[0]
    }

function colorPiece(ctx, thePiece, offset) {
    ctx.fillStyle = "red";
    for(var y = 0; y < thePiece.length; ++y) {
        for(var x = 0; x < thePiece[y].length; ++x) {
            if (thePiece[y][x] !== 0) {
                ctx.fillRect(20*(x + offset.x), 20*(y + offset.y), 20, 20);
            }
        }
    }
}

function drawCanvas(ctx) {
    ctx.fillStyle = "#000000";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    colorPiece(ctx, player.piece, player.position);
}

var framenum=0;

function doUpdate(timestamp) {
        document.getElementById("log").innerHTML = framenum.toString();
        ++framenum;
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");

        drawCanvas(ctx);
        window.requestAnimationFrame(doUpdate);
}

doUpdate();