简体   繁体   English

Box2D中的碰撞检测

[英]Collision Detection in Box2D

So I'm using Box2D for collision detection in a game. 所以我在游戏中使用Box2D进行碰撞检测。 I have a tilemap that contains information on the terrain: for now it's just a char[][] that has either road or grass. 我有一个图块地图,其中包含有关地形的信息:目前,这只是一个具有道路或草地的char [] []。 Now, at the start of each level I wanted to create rectangles to describe the different terrains, but I wanted these rectangles to be optimized and apparently that takes quite an algorithm. 现在,在每个级别的开始,我想创建一个矩形来描述不同的地形,但是我希望这些矩形得到优化,并且显然需要相当多的算法。

My first approach was to create an individual terrain for EVERY tile in the map at the start of the level. 我的第一种方法是在关卡开始时为地图中的每个图块创建一个单独的地形。 The FPS was reduced to 5. FPS降至5。

My second idea was to simply create the different rectangles for terrains as the player moved along the map, deleting the rectangles that were out of view. 我的第二个想法是在玩家沿着地图移动时,简单地为地形创建不同的矩形,删除看不见的矩形。 Although it would still be a lot of rectangles, it would be considerably less. 尽管仍然会有很多矩形,但是会少得多。

I haven't attempted the second method yet, but I want to know: is there any easy way for me to efficiently perform collision detection against terrain with a large tilemap? 我还没有尝试过第二种方法,但是我想知道:对我来说,有没有一种简单的方法可以有效地对具有大图块贴图的地形进行碰撞检测?

Thanks. 谢谢。

Try combining tiles. 尝试结合瓷砖。 For example, if you have 16 rectangular collision volumes for 16 tiles like so... 例如,如果您有16个图块的16个矩形碰撞体积,例如...

* * * *
* * * *
* * * *
* * * *

You can obviously combine these tiles into one large rectangle. 您显然可以将这些图块组合成一个大矩形。

Now, things get more difficult if you have tiles in a weird arrangement, maybe like this... 现在,如果您将瓷砖排列成奇怪的形状,事情就会变得更加困难,也许像这样……

**---
****-
*--**
-*-*-

I just recently solved this problem in my game using a quad tree and sweep and prune . 我最近刚刚在游戏中使用四叉树清扫和修剪功能解决了这个问题。 (Sweep and prune isn't strictly necessary, its an optimization.) (严格修剪和修剪不是必需的,这是一种优化。)

Quad tree partitions your square tiles into bigger rectangles, then you iterate over the rectangles the quad tree produces, and combine them if they have the same width, then iterate over them again and combine them by similar heights. 四叉树将方形图块划分为更大的矩形,然后遍历四叉树生成的矩形,如果宽度相同,则将其合并,然后再次遍历它们,并以相似的高度合并。 Repeat until you can't combine them anymore, then generate your collision volumes. 重复直到无法再合并它们,然后生成碰撞体积。

Here's a link to a question I asked about a more optimal reduction. 这是我提出的有关最佳还原的问题的链接 I probably won't implement this as it sounds difficult, and my current approach is working well. 听起来很困难,我可能不会实现,而我目前的方法运行良好。

Some code: 一些代码:

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM