Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

9/4/2020 Explosions - Box2D tutorials - iforce2d

iforce2d <# insert awesome header graphics #>

Crushing immovable objects since 2011

Box2D tutorials | Cocos2d-x resources | Box2D JSON loader | R.U.B.E Box2D editor | R.U.B.E free | My apps | Blog ! | 日本語はこちら | Box2D中文教程

News Mar 20: R.U.B.E v1.7 released. Instanciable objects!


Feb 21: Added RUBE sample loader for Cocos2d-X v3.4.
Feb 17: Funny Fists released in iOS App store and Google Play store. (YouTube video)
2014
May 25: R.U.B.E v1.6 released. Samplers!
May 12: "On-the-fly" resource updating for Cocos2d-x
Apr 22: New blog post: Inverted pendulum control
Apr 7: On-screen logging class for Cocos2d-x
Mar 22: Downhill Supreme 2 released for iOS and Android
Jan 2: YouTube video: Making soft-body wheels in RUBE
2013
Oct 6: Check out Supplyfront RTS, my 7dRTS entry continued.
Sep 26: R.U.B.E v1.5 released. Customizable item labels, snap-to-grid, export filtering, full-text help search.
Sep 18: Added RUBE sample loader for Cocos2d-X.
More...

Box2D tutorial topics


Box2D C++ tutorials - Explosions
Last edited: July 14 2013
Introduction
Setting up (Linux)
Setting up (Windows)
Halt! You should have a good understanding of
Setting up (Mac OSX) the basic tutorials before venturing further.
Testbed structure
Making a test
Bodies
Fixtures
Explosions
World settings This topic will look at a few ways to do explosions in Box2D. This makes use of a variety of techniques already covered in
Forces and impulses other topics, so here we'll focus on broader design aspects and the pros and cons of each method rather than look at the
Custom gravity actual coding in detail. By now your brain is probably so full of Box2D info that you have to wear earplugs to keep it from
Moving at constant speed falling out anyway.
Rotating to a given angle
Simulating an explosion comes down to finding out what bodies are in the vicinity of the blast and applying an impulse to
Jumping push them away from the blast location. In this topic we will look at three methods of varying complexity:
Using debug draw
Drawing your own objects Proximity - find bodies in range
Raycast - find bodies in range and line-of-sight
User data Particles - spray a bunch of small bodies outward from the blast location
Anatomy of a collision
Collision callbacks Actually, in the last of these methods we don't need to find what bodies are in range because the phyics engine does the work
for us. Let's take a look at each of these in more detail. We will use this test scene to expose the strengths and weaknesses
Collision filtering
of each method:
Sensors
Ray casting
World querying
Removing bodies safely
The 'can I jump' question
Ghost vertices
Joints - overview
Joints - revolute
Joints - prismatic

FAQ / gotchas

Tutorial source code

Advanced topics

Conveyor belts
Projected trajectory
Sticky projectiles
Hovercar suspension
Top-down car physics
One-way walls
Buoyancy
Explosions
Physics-driven particles

Other topics

Setting up (iPhone) Applying a blast impulse

For this topic I did not get too technical with any formulas for how pressure (and therefore impulse) changes relative to the
distance from the blast point, but we know that the area of a circle increases relative to the square of the radius. An

https://www.iforce2d.net/b2dtut/explosions 1/6
9/4/2020 Explosions - Box2D tutorials - iforce2d
explosion causes a finite amount of gas to expand until the pressure with the surrounding air is equalized, which will be when
it takes up the same volume (area for 2d). So the pressure should decrease inversely to the square of the radius... okay
maybe I did get a little technical.

Anyway, we could put this in a function like:

1 void applyBlastImpulse(b2Body* body, b2Vec2 blastCenter, b2Vec2 applyPoint, float blastPower) {


2 b2Vec2 blastDir = applyPoint - blastCenter;
3 float distance = blastDir.Normalize();
4 //ignore bodies exactly at the blast point - blast direction is undefined
5 if ( distance == 0 )
6 return;
7 float invDistance = 1 / distance;
8 float impulseMag = blastPower * invDistance * invDistance;
9 body->ApplyLinearImpulse( impulseMag * blastDir, applyPoint );
10 }

There are some other considerations to take into account, such as limiting the impulse to a maximum value etc, but these
have been left out here for clarity. Check the source code below for details.

Proximity method

The simplest approach is to find all bodies within a certain distance of the blast location. To define this a little more, we want
bodies with their center of mass within range. We can use an area query to efficiently find all bodies with a fixture in the area
around the blast point, and then do a simple distance check to see if their center of mass is close enough.

1 //find all bodies with fixtures in blast radius AABB


2 MyQueryCallback queryCallback; //see "World querying topic"
3 b2AABB aabb;
4 aabb.lowerBound = center - b2Vec2( blastRadius, blastRadius );
5 aabb.upperBound = center + b2Vec2( blastRadius, blastRadius );
6 m_world->QueryAABB( &queryCallback, aabb );
7
8 //check which of these bodies have their center of mass within the blast radius
9 for (int i = 0; i < queryCallback.foundBodies.size(); i++) {
10 b2Body* body = queryCallback.foundBodies[i];
11 b2Vec2 bodyCom = body->GetWorldCenter();
12
13 //ignore bodies outside the blast range
14 if ( (bodyCom - center).Length() >= m_blastRadius )
15 continue;
16
17 applyBlastImpulse(body, center, bodyCom, blastPower );
18 }

Now let's look at the results this gives us. Here is a screenshot showing which bodies in the test scene will be given an
impulse by this method:

This is a pretty good start, but there are a few problems. The most obvious is that the blast can travel through the platforms,
the ground, and other obstructing objects. Another problem is that the large body on the far left is in the blast range but it is
not affected because its center of mass is not close enough. How about this:

https://www.iforce2d.net/b2dtut/explosions 2/6
9/4/2020 Explosions - Box2D tutorials - iforce2d

The objects on each side of the explosion have the same mass, and they also present the same surface area to the blast, but
those on the right will collect four times as much impulse. One more:

These two frames are from just before and just after the blast impulse is applied. Because the impulse is applied at the center
of mass of the bodies, no torque is caused which looks odd. Still, a simple implementation like this would be fine for many
situations.

Raycast method

We can improve on this substantially by using raycasts to find which bodies to interact with instead of a simple distance
check. Check out the topic on ray casting and the related section in the world querying topic for implementation details.

1 for (int i = 0; i < numRays; i++) {


2 float angle = (i / (float)numRays) * 360 * DEGTORAD;
3 b2Vec2 rayDir( sinf(angle), cosf(angle) );
4 b2Vec2 rayEnd = center + blastRadius * rayDir;
5
6 //check what this ray hits
7 RayCastClosestCallback callback;//basic callback to record body and hit point
8 m_world->RayCast(&callback, center, rayEnd);
9 if ( callback.m_body )
10 applyBlastImpulse(callback.body, center, callback.point, (m_blastPower / (float)numRays));
11 }

Notice we divide the blast magnitude by the number of rays - this is just to make it easier to adjust the number of rays and
without changing the overall blast effect. Let's see how this goes in the test scene with 32 rays:

https://www.iforce2d.net/b2dtut/explosions 3/6
9/4/2020 Explosions - Box2D tutorials - iforce2d
Good, no magical blasting through solid walls anymore, so the boxes above the platforms are correctly not affected. The
second case is also much improved because the surface area of each side is taken into account:

Finally, because the impulses are being applied at non-symmetrical points where rays intersect the fixtures, they tend to
cause some torque to spin the bodies in a more interesting way.

The number of rays can be adjusted to allow the blast to reach between smaller gaps, and to balance CPU usage with the
quality of result.

Particle method

The last method we'll try in this topic is somewhat different to the first two. Instead of checking what bodies are around the
blast point, we'll just create a bunch of small bodies to simulate quickly expanding air particles, and let them fly. This is a
closer simulation of what actually happens in an explosion so we can expect it to look more realistic.

Not only does this method gives great results, but it's also easy to implement because most of the work is done by the
physics engine. On the other hand, more work done by the engine means more CPU time used. Here is a typical example of
how you might set up these particle bodies:

1 for (int i = 0; i < numRays; i++) {


2 float angle = (i / (float)numRays) * 360 * DEGTORAD;
3 b2Vec2 rayDir( sinf(angle), cosf(angle) );
4
5 b2BodyDef bd;
6 bd.type = b2_dynamicBody;
7 bd.fixedRotation = true; // rotation not necessary
8 bd.bullet = true; // prevent tunneling at high speed
9 bd.linearDamping = 10; // drag due to moving through air
10 bd.gravityScale = 0; // ignore gravity
11 bd.position = center; // start at blast center
12 bd.linearVelocity = blastPower * rayDir;
13 b2Body* body = m_world->CreateBody( &bd );
14
15 b2CircleShape circleShape;
16 circleShape.m_radius = 0.05; // very small
17
18 b2FixtureDef fd;
19 fd.shape = &circleShape;
20 fd.density = 60 / (float)numRays; // very high - shared across all particles
21 fd.friction = 0; // friction not necessary
22 fd.restitution = 0.99f; // high restitution to reflect off obstacles
23 fd.filter.groupIndex = -1; // particles should not collide with each other
24 body->CreateFixture( &fd );
25 }

That's a lot of code just to create a body and add a fixture! But most of it is simply setting the necessary properties, because
unlike most situations we have seen so far, many of the default properties are not what we want. The comments there should
be self-explanatory... some things such as the friction and fixed rotation are not strictly necessary, but since there will be a lot
of these particles it may help to do anything we can to reduce the calculation required for each of them.

The effects of this are difficult to show in static screenshots, so here is an animated gif showing the trail left by each particle.
This shows 24 frames after the explosion, or about half a second:

https://www.iforce2d.net/b2dtut/explosions 4/6
9/4/2020 Explosions - Box2D tutorials - iforce2d

It's quite obvious that this method has all the advantages of the raycast method, plus a few more. Now we have a real blast
'wave' that reflects off obstacles, allowing the energy of the explosion to correctly get around corners, as in the case of the
underground tunnel, and the diagonal plate beside the upper platform. This scattering of energy helps give the impression
that the explosion is actually a physical space-occupying presence rather than the telekinetic impulse we have with the other
methods. It also gives us something to base rendering (smoke textures etc) on.

You can vary the weight of the particles, their initial velocity, linear damping, restitution, and of course the number of them,
to get just the right feel. The particles require some management to clear them after the explosion is finished, but it's not a
lot of work. The only real drawback to this method is the CPU time required. Mobile devices may struggle a little with multiple
explosions of a high number of particles, but for regular computers even 100 or more (128 in the screenshot below) is not a
problem (at least with C++).

Another nice side-effect is that the energy from the blast does not affect everything instantaneously - it takes a tiny bit
longer for the particles to reach objects that are further from the blast center. It's only a few milliseconds of difference but
those milliseconds do seem to add a touch of realism. For instance looking at the block stack immediately to the right of the
explosion center, we can see the blast work its way up the stack over a few timesteps.

Finally, this method ensures that in tight spaces the expected energy does not just disappear. The particles can bounce
around and hit many different surfaces before they dissipate.

https://www.iforce2d.net/b2dtut/explosions 5/6
9/4/2020 Explosions - Box2D tutorials - iforce2d

Source code

Here is the source code for those who would like to try it out for themselves. This is a 'test' for the testbed, based on Box2D
v2.3.0.

Testbed test: iforce2d_Explosions.zip

Linux 32-bit binary


Linux 64-bit binary
Windows binary
MacOSX binary

RUBE file for the test scene: explosionsRUBEScene.zip

YouTube video

Not seeing the any comments below? Try changing the 'https' in the page URL to just 'http'
Click here: http://www.iforce2d.net/b2dtut/explosions

Want to promote your Box2D game here for free?


Contact gmail 'iforce2d'
If you find this site useful please consider supporting it :)

https://www.iforce2d.net/b2dtut/explosions 6/6

You might also like