以前做化学课件,发现Flash里处理对象的碰撞是个很麻烦的问题,即使是对于规则的对象,比如某个仪器(滴管,试剂瓶等),也查过很多资料来解决碰撞问题,但都很复杂,看了后一头雾水。一次偶然发现box2dAs3,它竟然能把对象碰撞模拟得如此真实,并且Box2dAs3中处理碰撞并不需要开发者处理,开发者只需要创建一个一个的对象(box2d中称为刚体),它会自动处理每个刚体的碰撞,即物理特性。下面是我的第一篇关于box2dAs3的入门。
package
{
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.events.Event;
/**
* Box2dAs3 Version 2.0.1
* @author ywxgod--http://www.cnblogs.com/ywxgod/
*
*/
[SWF(backgroundColor="333333",frameRate="30",width="550",height="400")]
public class HelloBox2dAs3 extends Sprite
{
private var physcale:Number = 30.0;
private var timeStep:Number = 1 / physcale;
private var iteration:int = 10;
private var body:b2Body;
private var world:b2World;
private const FLOOR_WIDTH:int = 550;
private const FLOOR_HEIGHT:int = 20;
private const WALL_WIDTH:int = 20;
private const WALL_HEIGHT:int = 400;
private var maxBodysNum:int = 50;
private var count:int = 0;
public function HelloBox2dAs3():void
{
init();
}
private function init():void
{
createWorld();
createFloorAndWalls();
showDebuger();
run();
addEventListener(Event.ENTER_FRAME,onFrame);
}
private function createWorld():void
{
var aabb:b2AABB = new b2AABB();
aabb.lowerBound.Set( -100, -100);
aabb.upperBound.Set(100, 100);
var gravity:b2Vec2 = new b2Vec2(0, 9.8);
world = new b2World(aabb, gravity, true);
}
private function createFloorAndWalls():void
{
var floorShapeDef:b2PolygonDef = new b2PolygonDef();
floorShapeDef.density = 0;
floorShapeDef.friction = 0.3;
floorShapeDef.restitution = 0.4;
floorShapeDef.SetAsBox(FLOOR_WIDTH / 2 / physcale, FLOOR_HEIGHT / 2 / physcale);
var floorBodyDef:b2BodyDef = new b2BodyDef();
floorBodyDef.position.Set(FLOOR_WIDTH / 2 / physcale, (WALL_HEIGHT-FLOOR_HEIGHT/2) / physcale);
var floorBody:b2Body = world.CreateBody(floorBodyDef);
floorBody.CreateShape(floorShapeDef);
floorBody.SetMassFromShapes();
var leftWallShapeDef:b2PolygonDef = new b2PolygonDef();
leftWallShapeDef.density = 0;
leftWallShapeDef.friction = 0.3;
leftWallShapeDef.restitution = 0.4;
leftWallShapeDef.SetAsBox(WALL_WIDTH / 2 / physcale, WALL_HEIGHT / 2 / physcale);
var leftWallBodyDef:b2BodyDef = new b2BodyDef();
leftWallBodyDef.position.Set(WALL_WIDTH / 2 / physcale, (WALL_HEIGHT / 2) / physcale);
var leftWallBody:b2Body = world.CreateBody(leftWallBodyDef);
leftWallBody.CreateShape(leftWallShapeDef);
leftWallBody.SetMassFromShapes();
var rightWallShapeDef:b2PolygonDef = new b2PolygonDef();
rightWallShapeDef.density = 0;
rightWallShapeDef.friction = 0.3;
rightWallShapeDef.restitution = 0.4;
rightWallShapeDef.SetAsBox(WALL_WIDTH / 2 / physcale, WALL_HEIGHT / 2 / physcale);
var rightWallBodyDef:b2BodyDef = new b2BodyDef();
rightWallBodyDef.position.Set((FLOOR_WIDTH-WALL_WIDTH / 2) / physcale, (WALL_HEIGHT / 2) / physcale);
var rightWallBody:b2Body = world.CreateBody(rightWallBodyDef);
rightWallBody.CreateShape(rightWallShapeDef);
rightWallBody.SetMassFromShapes();
}
private function createActors(count:int):void
{
var boxShapeDef:b2PolygonDef = new b2PolygonDef();
boxShapeDef.density = 2;
boxShapeDef.friction = 0.3;
boxShapeDef.restitution = 0.4;
boxShapeDef.SetAsBox(40 / 2 / physcale, 15 / 2 / physcale);
var boxShapeBodyDef:b2BodyDef = new b2BodyDef();
boxShapeBodyDef.position.Set((275) / physcale, (-count*15) / physcale);
var boxShapeBody:b2Body = world.CreateBody(boxShapeBodyDef);
boxShapeBody.CreateShape(boxShapeDef);
boxShapeBody.SetMassFromShapes();
}
private function onFrame(e:Event):void
{
world.Step(timeStep, iteration);
if (count--<5&&world.m_bodyCount< maxBodysNum)
{
createActors(count);
count = 5;
}
}
private function showDebuger():void
{
var sprite:Sprite = new Sprite();
addChild(sprite);
var dbg:b2DebugDraw = new b2DebugDraw();
dbg.m_sprite = sprite;
dbg.m_alpha = 0.5;
dbg.m_drawScale = physcale;
dbg.m_drawFlags = b2DebugDraw.e_obbBit;
dbg.m_fillAlpha = 0.5;
world.SetDebugDraw(dbg);
}
private function run():void
{
}
}
}
18行 定义swf文件的舞台背景,帧频,宽度,高度
21-23行 定义物理世界与flash世界中长度单位,box2d模拟频率及迭代次数
50-57行 创建一个物理世界world,所有的刚体都是存在其中,world的作用就像flash中的stage,所有的显示对象都被添加到stage一样。创建world需要三个参数:边界盒,重力加速度,是否休眠。
59-93行 创建地面,墙壁等。
95-108行 创建方形刚体,跟59-93行中唯一不同的地方是密度的赋值。
110-119行 在EnterFrameEvent中创建刚体。
121-132行 利用box2dAs3本身的调试显示函数来显示创建的刚体。因为box2das3中没有显示对象的概念,所以无法像flash添加显示对象到舞台一样去做了。
总结:
1。flash中的长度是以像素为单位,box2d中的长度是以米为单位,且一米等于30个像素。
2。flash中有显示对象,且显示对象都是位于stage上,box2d中有刚体,且刚体都是存在于world中。
3。flash中创建对象是需要制定其宽度和高度,box2d中定义形状只需要其高度宽度的各一半。
4。创建刚体的步骤:
a。定义形状,在形状定义中定义摩擦系数friction,反弹系数restitution,密度density,形状的大小SetAsBox
b。刚体定义,在刚体定义中设置刚体的位置position
c。创建刚体,传入刚体定义,由world来创建刚体
d。创建于刚体关联的形状,传入形状定义,有刚体来创建自己关联的形状。
e。设置质量。
5。设置b2DebugDraw时的参数
a。m_sprite 用来显示刚体的显示对象
b。m_alpha 显示对象的透明度
c。m_drawScale 放大系数,这个只应该跟长度单位相同,否则显示的刚体将会只有原来的1/30。
d。m_fillAlpha 绘制刚体时的填充色透明度。
e。m_drawFlags 标志,告诉b2DebugDraw要绘制刚体哪些相关属性,具体值为b2DebugDraw.e_obbBit,b2DebugDraw.e_aabbBit,b2DebugDraw.e_centerOfMassBit等,也可以是几个值的和。