仅在可见区域绘制 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 + w
和 y + h
。
我正在开发简单的迷你游戏,我开始注意到一些性能下降。游戏的制作方式是您拥有 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 + w
和 y + h
。