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.
Sep 16: Updated RUBE sample loader for Cocos2d v2.
Aug 12: RUBE loader for Nape by Zeh Fernando
Aug 7: Added RUBE sample loader for SFML.
Jul 30: Try my MiniLD 7dRTS entry.
Jul 24: Added physics-driven particles tutorial.
Jul 20: New blog post: rendering solid ground (as in Downhill Supreme)
Jul 18: R.U.B.E v1.4 released. Command-line interface for batch jobs, hotkeys for scripts, better script management.
May 22: Downhill Supreme is out now! (iOS)
Apr 2: R.U.B.E v1.3 released. Collision bitplane editing, Cocos2d-iphone loader, usability improvements.
Mar 11: R.U.B.E v1.2 released. Now supports weld, friction, motor joints and automatic image reloading.
Mar 10: RUBE loader for libGDX by Tim Scott
Jan 28: New blog post: a functional combustion engine!
Jan 22: New blog post: wind tunnel
Jan 20: Added explosions tutorial.
Jan 16: Added buoyancy tutorial.
Jan 16: AndEngine sample project to load RUBE scene by Bart Hirst
Jan 14: R.U.B.E v1.1 released, now supports custom properties.
Jan 1: All basic tutorials are now available in Chinese at ohcoder.com Huge thankyou to @OhCoder!
2012
Dec 23: Discussion forums have been set up
Dec 4: R.U.B.E v1.0 is ready !
Dec 2: YouTube video: Box2D pendulum clock
Nov 26: New blog post: rocket platform thingy
Nov 25: Video of R.U.B.E scenes in Chipmunk.
Nov 23: A sample project to load R.U.B.E scenes into Chipmunk physics! Details here.
Nov 14: An XCode sample project to load R.U.B.E scenes on iOS is now available. Details here.
Nov 11: A Java version of b2dJson is now available, based on JBox2D.
Nov 6: A Javascript version of b2dJson based on box2dweb is now available. Demo here!
Nov 2: The full specification of the JSON format used by b2dJson can be found here: b2dJson file structure
Oct 28: YouTube video: 2-minute ragdoll in R.U.B.E Box2D editor
Sep 29: YouTube video: R.U.B.E Box2D editor usage example

Box2D C++ tutorials - Explosions

Last edited: July 14 2013


Halt! You should have a good understanding of
the basic tutorials before venturing further.


Explosions


This topic will look at a few ways to do explosions in Box2D. This makes use of a variety of techniques already covered in other topics, so here we'll focus on broader design aspects and the pros and cons of each method rather than look at the 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 falling out anyway.

Simulating an explosion comes down to finding out what bodies are in the vicinity of the blast and applying an impulse to push them away from the blast location. In this topic we will look at three methods of varying complexity:
  • Proximity - find bodies in range
  • Raycast - find bodies in range and line-of-sight
  • Particles - spray a bunch of small bodies outward from the blast location
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 of each method: Explosions

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 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
2
3
4
5
6
7
8
9
10
  void applyBlastImpulse(b2Body* body, b2Vec2 blastCenter, b2Vec2 applyPoint, float blastPower) {
      b2Vec2 blastDir = applyPoint - blastCenter;
      float distance = blastDir.Normalize();
      //ignore bodies exactly at the blast point - blast direction is undefined
      if ( distance == 0 )
          return;
      float invDistance = 1 / distance;
      float impulseMag = blastPower * invDistance * invDistance;
      body->ApplyLinearImpulse( impulseMag * blastDir, applyPoint );
  }
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  //find all bodies with fixtures in blast radius AABB
  MyQueryCallback queryCallback; //see "World querying topic"
  b2AABB aabb;
  aabb.lowerBound = center - b2Vec2( blastRadius, blastRadius );
  aabb.upperBound = center + b2Vec2( blastRadius, blastRadius );
  m_world->QueryAABB( &queryCallback, aabb );
  
  //check which of these bodies have their center of mass within the blast radius
  for (int i = 0; i < queryCallback.foundBodies.size(); i++) {
      b2Body* body = queryCallback.foundBodies[i];
      b2Vec2 bodyCom = body->GetWorldCenter();
      
      //ignore bodies outside the blast range
      if ( (bodyCom - center).Length() >= m_blastRadius )
          continue;
          
      applyBlastImpulse(body, center, bodyCom, blastPower );
  }
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: Explosions 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: Explosions 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: Explosions 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
2
3
4
5
6
7
8
9
10
11
  for (int i = 0; i < numRays; i++) {
      float angle = (i / (float)numRays) * 360 * DEGTORAD;
      b2Vec2 rayDir( sinf(angle), cosf(angle) );
      b2Vec2 rayEnd = center + blastRadius * rayDir;
  
      //check what this ray hits
      RayCastClosestCallback callback;//basic callback to record body and hit point
      m_world->RayCast(&callback, center, rayEnd);
      if ( callback.m_body ) 
          applyBlastImpulse(callback.body, center, callback.point, (m_blastPower / (float)numRays));
  }
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: Explosions 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: Explosions 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. Explosions 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  for (int i = 0; i < numRays; i++) {
      float angle = (i / (float)numRays) * 360 * DEGTORAD;
      b2Vec2 rayDir( sinf(angle), cosf(angle) );
  
      b2BodyDef bd;
      bd.type = b2_dynamicBody;
      bd.fixedRotation = true; // rotation not necessary
      bd.bullet = true; // prevent tunneling at high speed
      bd.linearDamping = 10; // drag due to moving through air
      bd.gravityScale = 0; // ignore gravity
      bd.position = center; // start at blast center
      bd.linearVelocity = blastPower * rayDir;
      b2Body* body = m_world->CreateBody( &bd );
  
      b2CircleShape circleShape;
      circleShape.m_radius = 0.05; // very small
  
      b2FixtureDef fd;
      fd.shape = &circleShape;
      fd.density = 60 / (float)numRays; // very high - shared across all particles
      fd.friction = 0; // friction not necessary
      fd.restitution = 0.99f; // high restitution to reflect off obstacles
      fd.filter.groupIndex = -1; // particles should not collide with each other
      body->CreateFixture( &fd );
  }
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: Explosions 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++). Explosions 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. Explosions

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