Java Box2D中的碰撞检测

Java Box2D中的碰撞检测,java,algorithm,box2d,collision-detection,Java,Algorithm,Box2d,Collision Detection,所以我在游戏中使用Box2D进行碰撞检测。我有一个包含地形信息的tilemap:现在它只是一个char[][],包含道路或草地。现在,在每一层的开始,我想创建矩形来描述不同的地形,但我想对这些矩形进行优化,显然这需要一个相当复杂的算法 我的第一种方法是在关卡开始时为地图中的每个平铺创建一个单独的地形。FPS减少到5 我的第二个想法是,当玩家沿着地图移动时,简单地为地形创建不同的矩形,删除看不见的矩形。虽然它仍然会有很多矩形,但会少很多 我还没有尝试过第二种方法,但我想知道:有没有简单的方法可以让

所以我在游戏中使用Box2D进行碰撞检测。我有一个包含地形信息的tilemap:现在它只是一个char[][],包含道路或草地。现在,在每一层的开始,我想创建矩形来描述不同的地形,但我想对这些矩形进行优化,显然这需要一个相当复杂的算法

我的第一种方法是在关卡开始时为地图中的每个平铺创建一个单独的地形。FPS减少到5

我的第二个想法是,当玩家沿着地图移动时,简单地为地形创建不同的矩形,删除看不见的矩形。虽然它仍然会有很多矩形,但会少很多

我还没有尝试过第二种方法,但我想知道:有没有简单的方法可以让我有效地使用大型tilemap对地形执行碰撞检测


谢谢。

尝试组合瓷砖。例如,如果16个平铺有16个矩形碰撞体积,则如下所示

* * * *
* * * *
* * * *
* * * *
显然,您可以将这些瓷砖组合成一个大矩形

现在,如果你有奇怪排列的瓷砖,事情会变得更困难,也许像这样

**---
****-
*--**
-*-*-
我最近在游戏中使用and解决了这个问题。清理和修剪不是绝对必要的,它是一种优化

将方形平铺划分为更大的矩形,然后迭代四叉树生成的矩形,如果它们具有相同的宽度,则将它们合并,然后再次迭代并按相似的高度将它们合并。重复此操作,直到无法再组合它们,然后生成碰撞体积

我问了一个更理想的降价方案。我可能不会实现它,因为它听起来很难,而且我目前的方法运行良好

一些代码:

do {
    lastCompressSize = currentOutput;
    this.runHorizontalCompression(this.output1, this.output2);
    this.output1.clear();
    this.runVerticalCompression(this.output2, this.output1);
    this.output2.clear();
    currentOutput = this.output1.size;
    iterations += 1;
}while (lastCompressSize > currentOutput);

public void runHorizontalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.xAxisSort);
    int x2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        x2 = newRect.x + newRect.width;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (x2 == r2.x && r2.y == newRect.y
                    && r2.height == newRect.height) {
                newRect.width += r2.width;
                x2 = newRect.x + newRect.width;
                input.removeIndex(j);
                j -= 1;
            } else if (x2 < r2.x)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}

public void runVerticalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.yAxisSort);
    int y2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        y2 = newRect.y + newRect.height;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (y2 == r2.y && r2.x == newRect.x
                    && r2.width == newRect.width) {
                newRect.height += r2.height;
                y2 = newRect.y + newRect.height;
                input.removeIndex(j);
                j -= 1;
            } else if (y2 < r2.y)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}

尝试组合瓷砖。例如,如果16个平铺有16个矩形碰撞体积,则如下所示

* * * *
* * * *
* * * *
* * * *
显然,您可以将这些瓷砖组合成一个大矩形

现在,如果你有奇怪排列的瓷砖,事情会变得更困难,也许像这样

**---
****-
*--**
-*-*-
我最近在游戏中使用and解决了这个问题。清理和修剪不是绝对必要的,它是一种优化

将方形平铺划分为更大的矩形,然后迭代四叉树生成的矩形,如果它们具有相同的宽度,则将它们合并,然后再次迭代并按相似的高度将它们合并。重复此操作,直到无法再组合它们,然后生成碰撞体积

我问了一个更理想的降价方案。我可能不会实现它,因为它听起来很难,而且我目前的方法运行良好

一些代码:

do {
    lastCompressSize = currentOutput;
    this.runHorizontalCompression(this.output1, this.output2);
    this.output1.clear();
    this.runVerticalCompression(this.output2, this.output1);
    this.output2.clear();
    currentOutput = this.output1.size;
    iterations += 1;
}while (lastCompressSize > currentOutput);

public void runHorizontalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.xAxisSort);
    int x2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        x2 = newRect.x + newRect.width;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (x2 == r2.x && r2.y == newRect.y
                    && r2.height == newRect.height) {
                newRect.width += r2.width;
                x2 = newRect.x + newRect.width;
                input.removeIndex(j);
                j -= 1;
            } else if (x2 < r2.x)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}

public void runVerticalCompression(Array<SimpleRect> input,
        Array<SimpleRect> output) {
    input.sort(this.yAxisSort);
    int y2 = -1;
    final SimpleRect newRect = this.rectCache.retreive();
    for (int i = 0; i < input.size; i++) {
        SimpleRect r1 = input.get(i);
        newRect.set(r1);
        y2 = newRect.y + newRect.height;
        for (int j = i + 1; j < input.size; j++) {
            SimpleRect r2 = input.get(j);
            if (y2 == r2.y && r2.x == newRect.x
                    && r2.width == newRect.width) {
                newRect.height += r2.height;
                y2 = newRect.y + newRect.height;
                input.removeIndex(j);
                j -= 1;
            } else if (y2 < r2.y)
                break;
        }
        SimpleRect temp = this.rectCache.retreive().set(newRect);
        output.add(temp);
    }
}

瓷砖地图有多大?我已经完成了大约1000x1000个瓷砖。只需在Box2D中一次添加所有瓷砖?哇,真令人印象深刻。我使用的是微不足道的100x100。您可以使用shape类的重叠方法。那不是它叫什么,但我忘了它叫什么了。它在javadoc中表示形状。您使用java吗?我有一些很好的代码可以给你合并冲突量。让我发布一个答案…我没有发布我的代码,因为它凌乱。如果您需要澄清,请告诉我。瓷砖地图有多大?我已经完成了大约1000x1000个瓷砖。只需在Box2D中一次添加所有瓷砖?哇,真令人印象深刻。我使用的是微不足道的100x100。您可以使用shape类的重叠方法。那不是它叫什么,但我忘了它叫什么了。它在javadoc中表示形状。您使用java吗?我有一些很好的代码可以给你合并冲突量。让我发布一个答案…我没有发布我的代码,因为它凌乱。如果你需要澄清,请告诉我。所以在这之前我对四叉树做了一些研究,我还想实现放大/缩小功能,我有点困惑如何使用扫描和修剪创建矩形。“扫描和修剪”似乎适用于碰撞检测,我不希望这些矩形重叠。它们将是相邻的,正如您在问题中所发布的。我在这里遗漏了什么?在运行四叉树之后,您将有一堆矩形。这些矩形都不会重叠,但有些是相邻的。“扫描”和“修剪”按X轴对矩形排序,然后按Y轴对矩形排序,以快速确定矩形是否处于碰撞状态。如果矩形共享一条边,可以执行相同的操作来快速确定它们是否相邻。这就是我的意思。按X和y值对四叉树输出进行排序,这样只会更快地比较相邻的矩形。我已经发布了我的扫描和修剪代码。我有一些奇怪的东西,比如我缓存矩形以避免产生不必要的垃圾,因为这只会做一次,不会重复。现在我已经为您完成了大约50%的工作:。只要实现四叉树,你就可以自由回家了@USER1264811所以在这之前我对四叉树做了一点研究,我还想实现一个放大/缩小功能,我有点困惑我是如何
我们将使用扫描和修剪来创建矩形。“扫描和修剪”似乎适用于碰撞检测,我不希望这些矩形重叠。它们将是相邻的,正如您在问题中所发布的。我在这里遗漏了什么?在运行四叉树之后,您将有一堆矩形。这些矩形都不会重叠,但有些是相邻的。“扫描”和“修剪”按X轴对矩形排序,然后按Y轴对矩形排序,以快速确定矩形是否处于碰撞状态。如果矩形共享一条边,可以执行相同的操作来快速确定它们是否相邻。这就是我的意思。按X和y值对四叉树输出进行排序,这样只会更快地比较相邻的矩形。我已经发布了我的扫描和修剪代码。我有一些奇怪的东西,比如我缓存矩形以避免产生不必要的垃圾,因为这只会做一次,不会重复。现在我已经为您完成了大约50%的工作:。只要实现四叉树,你就可以自由回家了@用户1264811