许多物体的碰撞检测

IT小君   2022-01-12T07:02:41

我主要专注于图形方面来创建一个小 2DGame。我看过/看过几个教程,但没有一个是那么令人愉快。我已经有一个玩家(一个方块)在屏幕上移动并与其他方块发生碰撞。重力等也都做了。

如果只有屏幕上看到的那么多物体(30*20),一切都很好。但是,如果我将其增加到 300*300,则程序开始运行非常缓慢,因为它必须检查这么多对象。

我真的不明白像 Minecraft 这样的游戏是如何使用所有这些块的,而且我的程序已经放弃了 300*300 块。

我已经尝试仅在对象可见时检查碰撞,但这会导致程序检查每个对象的可见性,从而导致相同的问题。我究竟做错了什么?帮助表示赞赏。

我将发布一些关于如何处理冲突的代码。

player.collision(player, wall);

public void collision(Tile object1, Tile[] object2){
    collisionCheckUp(object1, object2);
    collisionCheckDown(object1, object2);
    collisionCheckLeft(object1, object2);
    collisionCheckRight(object1, object2);  
}

public void collisionCheckDown(Tile object1, Tile[] object2){

    for (int i = 0; i < Map.tileAmount; i++){
        if(object2[i] != null && object2[i].visible)
        {
            if(object1.isCollidingDown(object2[i])){
                object1.collisionDown = true;
                return;
            }

        }
    }       
    object1.collisionDown = false;
}

public void compileHullDown(){

     collisionHull = new Rectangle((int)x+3, (int)y+3, width-6, height);
}

int wallCount = 0;
    for (int x=0;x<Map.WIDTH;x++) {
        for (int y=0;y<Map.HEIGHT;y++) {

            if (Map.data[x][y] == Map.BLOCKED) {
                wall[wallCount] = new Tile(x * Map.TILE_SIZE, y *  Map.TILE_SIZE);
                wallCount++;
            }
        }
    }
评论(3)
IT小君

优化碰撞检测的常用方法是使用空间分区来分类/管理对象。

该方法的总体思路是,您构建一棵表示空间的树,然后根据对象的位置将对象放入该树中。当你计算碰撞时,你会遍历树。这样,与使用蛮力方法相比,您必须执行的计算量要少得多,因为您将忽略分支中的所有对象,而不是您正在遍历的对象。Minecraft 和类似的可能使用八叉树进行碰撞(也可能用于渲染)。

最常见的空间划分结构是BSP-Treeskd-Trees(一种特殊类型的 BSP-trees)。更简单的方法是在开始时使用统一的空间分区 - 将空间分成轴对齐的两半。

我发现的关于碰撞的最佳资源是这本书它应该澄清你关于这个话题的所有问题。

那就是如果你想做正确的事。如果您想快速完成,您可以只对角色周围的颜色缓冲区进行采样,或者仅在移动方向上采样以确定障碍物是否靠近。

2022-01-12T07:02:41   回复
IT小君

正如 Kostja 提到的,划分空间对您很有用。但是,您将需要使用四叉树而不是八叉树,因为您只在 2D 中而不是 3D 中。这是一篇很好的文章,可以帮助您开始使用 QuadTrees。

2022-01-12T07:02:41   回复
IT小君

您可以将开销减少 4 倍,而不是计算上/下/左/右的碰撞,计算一次碰撞并使用两个对象的相对位置来确定您是否撞到地板、墙壁或天花板. 另一个好主意是只关注附近的物体 - 也许每 0.25 秒一次列出所有可能在接下来的 0.25 秒内碰撞到足够近的物体的列表?

2022-01-12T07:02:41   回复