Javascript 提高碰撞检测的效率

Javascript 提高碰撞检测的效率,javascript,html5-canvas,collision-detection,tile,Javascript,Html5 Canvas,Collision Detection,Tile,我正在开发一个HTML5画布游戏,其中地图是由10px的瓷砖随机生成的,玩家可以在上面挖掘和构建。瓷砖存储在一个对象数组中,一个小地图包含大约23000个瓷砖。我的碰撞检测功能会在每次运行时(使用requestAnimationFrame())根据所有非空中平铺检查玩家的位置,它工作得很好,但我觉得它需要大量的CPU。碰撞功能如下(代码来自在线教程): 函数colCheck(shapeA,shapeB){ 变量vX=(shapeA.x+(shapeA.width/2))-(shapeB.x+(s

我正在开发一个HTML5画布游戏,其中地图是由10px的瓷砖随机生成的,玩家可以在上面挖掘和构建。瓷砖存储在一个对象数组中,一个小地图包含大约23000个瓷砖。我的碰撞检测功能会在每次运行时(使用
requestAnimationFrame()
)根据所有非空中平铺检查玩家的位置,它工作得很好,但我觉得它需要大量的CPU。碰撞功能如下(代码来自在线教程):

函数colCheck(shapeA,shapeB){
变量vX=(shapeA.x+(shapeA.width/2))-(shapeB.x+(shapeB.width/2)),
vY=(shapeA.y+(shapeA.height/2))-(shapeB.y+(shapeB.height/2)),
宽度=(shapeA.width/2)+(shapeB.width/2),
hHeights=(shapeA.height/2)+(shapeB.height/2),
colDir=null;
//如果x和y向量小于半宽或半高,则它们必须位于对象内部,从而导致碰撞
if(Math.abs(vX)=oY){
如果(vY>0){
colDir=“t”;
形状a.y+=oY;
}否则{
colDir=“b”;
shapeA.y-=oY;
}
}否则{
如果(vX>0){
colDir=“l”;
shapeA.x+=oX;
}否则{
colDir=“r”;
shapeA.x-=oX;
}
}
}
返回colDir;
};
然后,在我的更新函数中,我使用player和tiles作为参数运行此函数:

for (var i = 0; i < tiles.length; i++) {
    //the tiles tag attribute determines rendering colour and how the player can interact with it ie. dirt, rock, etc. 
    //anything except "none" is solid and therefore needs collision
    if (tiles[i].tag !== "none") {
        dir = colCheck(player, tiles[i]);
        if (dir === "l"){
            player.velX = 0;
            player.jumping = false;
        } else if  (dir === "r") {
            player.velX = 0;
            player.jumping = false;
        } else if (dir === "b") {
            player.grounded = true;
            player.jumping = false;
        } else if (dir === "t") {
            player.velY *= -0.3;
        }
    }
};
for(变量i=0;i
所以我想知道的是,如果我只使用类似于
Math.abs(tiles[I].x-player.x)<100
y
的条件检查离播放器一定距离内的tile,这是否应该提高代码的效率,因为它将针对更少的分片检查冲突,还是检查额外参数的效率较低

如果这在没有测试的情况下很难说,那么我如何才能找到我的代码运行得有多好呢

但我觉得这是CPU密集型的

CPU的目的是做很多事情非常快。有数学来决定你的算法的效率,而你当前的实现似乎是O(n)。如果将平铺的数量减少到一个恒定的数字,则可以实现O(1),这更好,但对应用程序来说可能不太明显。要实现O(1),您必须保留X个最近分片的索引,并在最近分片更改时增量更新索引。也就是说,如果玩家向右移动,您将修改索引,以便删除最左边的一列磁贴,并在右侧获得一列新的磁贴。检查冲突时,只需在索引中迭代固定数量的分幅,而不是整个分幅集

…这是否应该提高代码的效率,因为它将针对更少的分片检查冲突,还是检查额外参数的效率较低

回答这个问题的最好方法是使用探查器,但我希望它能提高性能,尤其是在较大的地图上。这将是一个O(n)解决方案,因为您仍在迭代整个磁贴集,您可以想象,当磁贴集接近无穷大时,性能将再次开始下降。您提出的解决方案可能是我上面建议的O(1)解决方案之间的一个很好的折衷方案

您不想做的事情是过早地优化代码。当您实际遇到性能问题时,最好进行优化,并且您应该系统地进行优化,以使您的成本得到最大的回报。换句话说,即使您确实存在性能问题,碰撞检测也可能不是问题的根源

我怎样才能找到我的代码运行得有多好


优化代码的最佳方法是检查和测量代码的哪些部分是CPU最密集的部分。当您发现代码的哪一部分太慢时,您可以自己找出解决方案,或者直接询问一个非常具体的问题,如何改进性能不佳的代码部分,并包括您的探查器信息和相关的代码部分。

针对Samuel建议我使用探查器的回答:

使用阵列中约23000个瓷砖组成的地图: 原始冲突代码的运行时间为48%。通过将
if(tiles[i].tag!==“none”)
更改为以下值,用于检查碰撞的时间量下降到5%

if (tiles[i].tag !== "none" 
    && Math.abs(tiles[i].x - player.x) < 200 
    && Math.abs(tiles[i].y - player.y) < 200)
if(tiles[i]。标记!=“无”
&&Math.abs(tiles[i].x-player.x)<200
&&Math.abs(tiles[i].y-player.y)<200)
地图由约180000块瓷砖组成: 最初的冲突代码在60-65%的时间内运行,游戏性能太低,无法玩。在更新的代码中,碰撞功能只运行了0.5%的时间,但性能仍然很低,因此我假设,即使检查碰撞的瓷砖较少,但仍有太多瓷砖导致
if (tiles[i].tag !== "none" 
    && Math.abs(tiles[i].x - player.x) < 200 
    && Math.abs(tiles[i].y - player.y) < 200)