Talking about Actionscript 3, Box2D and Flash.
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:
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.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.