Understanding how Box2D manages boundaries

Sometimes you may need to determine if your Box2D object has fallen off the screen. This mostly happens in games, where you are going to build something and some pieces may fall down, but obviously you can extend the concept to any application you may write.

There are two “obvious” ways to do it:

1) Checking x and y coordinates of every object… this is the “old school” method… very easy to determine which object is in the visible area and which one got lost into the deep nowhere… but we live in “Web 2.0″ age, and this method is “Web 0.1 pre alpha”…

2) Using sensors placed in the right spots and check if an object touches them… in this case this means the object is outside the screen. Yuou can read more about this method at Erase Box: the tutorial post. Very cool solution, but not what I am going to explain.

3) Using the b2BoundaryListener class – Box2D has a class called b2BoundaryListener that handles objects outside the boundaries. Let’s see some code:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package {
	import flash.display.Sprite;
	import flash.events.Event;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	public class bound extends Sprite {
		var body:b2Body;
		public var m_world:b2World;
		public var m_iterations:int=10;
		public var m_timeStep:Number=1.0/30.0;
		var m_boundaryListener=new b2BoundaryListener();
		var bodyDef:b2BodyDef;
		var boxDef:b2PolygonDef;
		var circleDef:b2CircleDef;
		public function bound() {
			addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-100.0, -100.0);
			worldAABB.upperBound.Set(100.0, 100.0);
			var gravity:b2Vec2=new b2Vec2(0.0,10.0);
			var doSleep:Boolean=true;
			m_world=new b2World(worldAABB,gravity,doSleep);
			m_world.SetBoundaryListener(m_boundaryListener);
			// debug draw start
			var m_sprite:Sprite;
			m_sprite = new Sprite();
			addChild(m_sprite);
			var dbgDraw:b2DebugDraw = new b2DebugDraw();
			var dbgSprite:Sprite = new Sprite();
			m_sprite.addChild(dbgSprite);
			dbgDraw.m_sprite=m_sprite;
			dbgDraw.m_drawScale=30;
			dbgDraw.m_alpha=1;
			dbgDraw.m_fillAlpha=0.5;
			dbgDraw.m_lineThickness=1;
			dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit;
			m_world.SetDebugDraw(dbgDraw);
			// ground
			bodyDef = new b2BodyDef();
			bodyDef.position.Set(4, 12);
			boxDef = new b2PolygonDef();
			boxDef.SetAsOrientedBox(10, 1,new b2Vec2(5, 1.5), Math.PI/32);
			boxDef.friction=0.3;
			boxDef.density=0;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(boxDef);
			body.SetMassFromShapes();
			// circle
			create_circle();
		}
		public function create_circle() {
			bodyDef = new b2BodyDef();
			bodyDef.position.x=2;
			bodyDef.position.y=2;
			circleDef = new b2CircleDef();
			circleDef.radius=2;
			circleDef.density=1.0;
			circleDef.friction=0.5;
			circleDef.restitution=0.2;
			body=m_world.CreateBody(bodyDef);
			body.CreateShape(circleDef);
			body.SetMassFromShapes();
		}
		public function Update(e:Event):void {
			m_world.Step(m_timeStep, m_iterations);
			if (m_boundaryListener.get_contact()) {
				m_boundaryListener.no_contact();
				m_world.DestroyBody(body);
				bodyDef = new b2BodyDef();
				create_circle();
			}
		}
	}
}

As you can see, this is the old “Hello World” with something changed… we have a ball landing on a inclined platform and rolling down to nowhere.

Line 13: declaring the m_boundaryListener variable, b2BoundaryListener type

Line 25: setting the boundary listener

Lines 68-73: If the boundary listener is trigged, remove the ball, create a new one in the same starting place and turn off the trigger

That’s all… now let’s see how did I modify the b2BoundaryListener.as file you can find in Box2D -> Dynamics folder:

/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
 
package Box2D.Dynamics{
 
 
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Dynamics.Contacts.*;
	import Box2D.Dynamics.*;
	import Box2D.Common.Math.*;
	import Box2D.Common.*;
 
 
	/// This is called when a body's shape passes outside of the world boundary.
	public class b2BoundaryListener {
		var contact:Boolean=false;
		/// This is called for each body that leaves the world boundary.
		/// @warning you can't modify the world inside this callback.
		public virtual function Violation(body:b2Body):void {
			contact=true;
		}
		public function get_contact() {
			return (contact);
		}
		public function no_contact() {
			contact=false;
		}
	}
}

As you can see, I simply set the contact variable to true if there is a violation… the remaining functions return contact value or set it to false..

And this is the result:

When the ball disappears, it falls down until it reaches the boundary, then the script destroys it (yes, with no mercy) and creates a new one.

Let’s see what happens from a wider point of view:

As you can see, this is a good method to check for objects out of the boundary with no hassle.

You can change boundary size playing with values at lines 20-21.

Download the full source and enjoy.

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (9 votes, average: 4.00 out of 5)
Loading ... Loading ...
Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.
Be my fan on Facebook and follow me on Twitter! Exclusive content for my Facebook fans and Twitter followers

This post has 13 comments

  1. zap

    on May 19, 2009 at 8:54 am

    Good Job

  2. Quintus Kilsdonk

    on May 20, 2009 at 11:28 am

    w00t
    2de

  3. dim

    on May 20, 2009 at 9:24 pm

    very good, bravo !

  4. A Freelancer’s Flash Bash [2] | Freelance Flash Games News

    on May 22, 2009 at 6:01 pm

    [...] Feronato made a post on understanding Box2D’s boundaries system. As usual, it’s filled with helpful lines upon lines of code so you can follow along with [...]

  5. alex

    on June 9, 2009 at 3:15 pm

    Please I need a tutorial to make a rope in box2d

  6. Jack

    on June 11, 2009 at 4:10 pm

    @alex . Here’s something: http://www.box2d.org/forum/viewtopic.php?f=8&t=1527&start=0 – I had it opened in another tab :P.

    Great post Emanuele . Thanks !

  7. alex

    on June 11, 2009 at 6:59 pm

    Please can you send me the class?? Im beginer and I dont know how to initialize it

    administraor@gmail.com

  8. alex

    on June 13, 2009 at 1:01 am

    please i need help

  9. Coconut

    on June 23, 2009 at 5:46 pm

    Thanks for the example.
    How do you set the bounding boxes to visible as in example2?

  10. Coconut

    on June 23, 2009 at 5:52 pm

    Excuse last question, its the drawFlags.

  11. Bitetti

    on July 21, 2009 at 3:49 pm

    Great article.
    It’s solved my problens of collision
    Very thanks ^_^

    Ps.: only bad thing: “Web 2.0″ not exist. Is a wrong definition of services ^_~

  12. Michael

    on September 23, 2009 at 5:34 am

    This is very helpful for setting up collision detection in world space. I was wondering how would we substitute the world boundary for something like a line goal or box?

  13. Introducing Box2D filtering : Emanuele Feronato

    on October 1, 2009 at 11:15 pm

    [...] following script is the same we saw a Understanding how Box2D manages boundaries but I am using a random filtering to make the ball ignore the ramp, the wall, or none of them. 1 2 [...]