平铺引擎碰撞优化

时间:2014-09-29 02:59:38

标签: c# optimization xna game-engine monogame

好吧,今天我决定尝试进一步优化我的磁贴引擎的碰撞检测代码。

这就是我所做的:

Circle类检查范围内是否有点。如果有,则检查播放器和磁贴之间的冲突。

代码:

        int tileWidth = 128;
        int tileHeight = 128;

        int[,] Layer3 = { 1, 1, 1, etc... };

        int tileMapWidth = Layer3.GetLength(1);
        int tileMapHeight = Layer3.GetLength(0);

        Rectangle tile, tile2;

        for (int x = 0; x < tileMapWidth; x++)
        {
            for (int y = 0; y < tileMapHeight; y++)
            {
                int wallIndex = Layer3[y, x];

                if (wallIndex == 1) //Full-sized Tile Collision (128 x 128)
                {
                    if (collisionCircle.Contains(new Vector2(x * tileWidth + (tileWidth / 2) + (int)Player.camera.Position.X,
                                                             y * tileHeight + (tileHeight / 2) + (int)Player.camera.Position.Y))) //+ tile / 2 is for centering the point
                    {
                        tile = new Rectangle(x * tileWidth + (int)Player.camera.Position.X, y * tileHeight + (int)Player.camera.Position.Y, tileWidth, tileHeight);
                        Collide(tile);
                    }
                }
            }
        }

这将检查整个第3层是否有&#34; 1&#34;。如果有,请指定矩形,如果点位于碰撞半径内,则检查碰撞。

另外,我检查了这段代码(使用绘制方法),我知道它正常工作,至少是行为。

我添加了大约120,000(32 x 3888)个磁贴,试图让它延迟,在代码之前,它稍微滞后了。但是在我添加代码后,它更加滞后。

我认为,因为它只检查半径范围内的瓷砖(点)之间的碰撞,它甚至不会远程滞后,但事实并非如此......

关于如何优化这一点的任何帮助/想法都会很棒。

非常感谢, Shyy

编辑:

Cirlce.Contains()代码:

    public bool Contains(Vector2 Point)
    {
        return ((Point - position).Length() <= radius);
    }

我使用了一个圆圈,因为我听说它比使用矩形更快。

2 个答案:

答案 0 :(得分:1)

另一种可能的优化是代替 return ((Point - position).Length() <= radius); 使用 return ((Point - position).LengthSquared() <= radius * radius);

这更快,因为Vector2.Length()必须执行昂贵的平方根操作。 Vector2.LengthSquared()不必执行那么慢的操作。半径必须与自身相乘,以考虑矢量平方的长度。

听起来你正在尝试确定哪些瓷砖不需要用来与玩家发生碰撞。您可以做的另一个优化是,如果(X = 5,Y = 5)的图块位于播放器的上方和左侧,则您不需要在(X = 4,Y = 4)处检查图块。类似地,如果(X = 5,Y = 5)低于和向右,则(X = 6,Y = 6)也保证太远。尝试确定何时通过播放器,不再需要检查碰撞。

答案 1 :(得分:0)

我建议仅在屏幕上的可见平铺上循环,以使用移动偏移检查碰撞。 我会尝试一些东西......

for x as integer = 0 + offSetX to tilesInWidth + offSetX
   for y as integer = 0 + offSetY to tilesInHeight + offSetY
      if player.insideCircle(player.position, radius) '
         object = layer(y,x);
         if player.collideWith(object) then Collide()
      end if
   next
next