Exploring destructible terrain with Box2D

An important part of Escape from Enceladus is destroying parts of the game world through various means in order to solve puzzles and find secret passages. It’s absolutely essential that the level engine I build support this very well, and I’m still evaluating if Box2D is up to the task. Today I hacked together a rudimentary test of shooting at walls and making them vanish from the game model:

The green lines around the walls are the debug view of Box2d, showing the loop / chain shapes that bound each connected block of tiles. It would have been much simpler to model each tile in the game world as its own solid body, but because Box2D evaluates each shape independently when modeling collisions, this results in the buggy behavior of a character tripping over an interior vertex of perfectly flat terrain. The solution is to find the bounding box of each connected island of solid tiles and give it to Box2D as a chain shape.

However, as I learned when researching this critical aspect of gameplay, you cannot modify the number of vertices in a Box2D shape without risking crashing the entire engine. This means that I need to destroy and recreate the shape every time it’s modified, which has the potential to be pretty memory / CPU intensive. I had a couple ideas to tackle the issue.

The first was to take the existing shape, expressed as a list of vectors, and permute it to snip out destroyed segments and insert new borders. In practice, this turned out to involve a nightmarish labyrinth of manually coded special cases and nested logic. I decided there must be a better way.

The method used in the above video is to simply redetermine the boundary of the shape or shapes after they have been modified, just as I do when building the level in the first place. I’m more than a little worried that this practice won’t scale, which is why I plan to test it on a very, very large map as soon as I get some of the other bugs ironed out.

Leave a Reply

Your email address will not be published. Required fields are marked *