仅在可见区域绘制 canvas

draw in canvas only in visible area

我正在开发简单的迷你游戏,我开始注意到一些性能下降。游戏的制作方式是您拥有 5000 x 5000 大小的大空间 (canvas),并且玩家配备了可以通过鼠标拖动移动的视口摄像机。现在的问题是,如果我为整个房间绘制 2000 个对象,则会导致性能显着下降。我在想是否有一种方法可以只绘制在当前相机区域可见的对象,而不是在玩家显然看不到的整个房间中。

我试过按扇区(区域)划分房间,但效果不佳。也许有人对这个问题有一些想法。

这是最大数量对象的渲染代码:

for(var i = 0; i < game.objects.stars.pool.length; i++) {
    var current = game.objects.stars.pool[i];
    game.components.star.apply(i);
    game.mechanics.draw.circle(current.x, current.y, current.r);
}

如何才能按照我描述的方式提高性能?

我的建议是检查当前对象是否在范围内,只有在范围内才绘制它,所以:

for(var i = 0; i < game.objects.stars.pool.length; i++) {
    var current = game.objects.stars.pool[i];
    if (withinBounds(current)){
        game.components.star.apply(i);
        game.mechanics.draw.circle(current.x, current.y, current.r);    
    }
}

function withinBounds(gameObject){
    if (gameObject.x + gameObject.r < viewPort.x && viewPort.x - gameObject.r > viewPort.x + viewPort.width) {
        if ( gameObject.y + gameObject.r < viewPort.y && gameObject.y - gameObject.y > viewPort.y + viewPort.height){
            return false;
        } else {
            return true;
        }
    } else {
        return true;
    }
}

其中视口与您的 5000 x 5000 区域相关。

这并没有看到您的所有代码,因此您可能需要针对您的数据类型进行调整。

我遇到过这种问题,我是这样解决的:

var in_viewport = function(x, y, margin) {
    if(
        x >= cam.x - margin &&
        x <= cam.x + cam.w + margin &&
        y >= cam.y - margin &&
        y <= cam.y + cam.h + margin
    ) {
       return true;
    }

    return false;
};

它可以像这样实现到你的逻辑中:

for(var i = 0; i < game.objects.stars.pool.length; i++) {
    var current = game.objects.stars.pool[i];
    if( in_viewport(current.x, current.y, 100) === true ) {
        game.components.star.apply(i);
        game.mechanics.draw.circle(current.x, current.y, current.r);
    }
}

下面几句解释:

margin参数建议设置为100,有助于平滑"things show up out of the blue"的问题。它只会渲染相机范围外 100 范围内的对象,因此即使您快速移动相机,东西也应该已经在那里,但性能应该非常好。

cam.x, cam.y, cam.w, cam.h inside in_viewport function should be altered to match your camera object naming,如果你已经在相机对象内设置了你的右和下边界,你可以用正确的参数替换 x + wy + h