此demo包含以下内容:
1.通过鼠标选择刚体
2.销毁刚体
3.对刚体设置自定义属性(包括皮肤)
4.循环遍历世界中的所有刚体
5.获取刚体信息
详细的解释请看代码
皮肤下载skin1.swc
package
{
import Box2D.Collision.Shapes.b2PolygonShape;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2Fixture;
import Box2D.Dynamics.b2FixtureDef;
import Box2D.Dynamics.b2World;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
[SWF(width="410", height="480")]
public class Interact extends Sprite {
private var stageWidth:Number = 410; //舞台宽度
private var stageHeight:Number = 480; //舞台高度
private var backgroundColor:uint = 0x333333; //背景色
private var world:b2World; //Box2D世界
private var worldScale:Number = 30; //一米等于30像素
private var timeStep:Number = 1 / 30; //时间步, 世界将在每一个时间步被更新
//只是定义了时间步还不够。在每一步,每一个物理实体(physic entity)根据作用
//于自身的作用力来更新(不包括睡眠状态)。处理这项任务的算法叫约束解算器
//(constraint solver)。它是基于循环每一个约束然后解算来进行的,一次一个。
private var velIterations:int = 10; //速率约束解算器
private var posIterations:int = 10; //位置约束解算器
private var info:TextField; //info实时显示头像的坐标,速度,角度
public function Interact() {
drawBackground();
createTip();
createInfo();
createWorld();
//创建地面
var floorAsset:DisplayObject = new FloorAsset();
createRectBody( {x:floorAsset.width/2, y:stageHeight - floorAsset.height/2,
width:floorAsset.width, height:floorAsset.height,
asset:floorAsset, id:"floor"} );
//创建左边界
createRectBody({x:1, y:stageHeight/2, width:2, height:stageHeight, id:"leftBound"});
//创建右边界
createRectBody({x:stageWidth - 1, y:stageHeight/2, width:2, height:stageHeight, id:"rightBound"});
//创建砖块
var brickAsset:Sprite = new BrickAsset1();
createRectBody({x:175, y:435, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick1"});
brickAsset = new BrickAsset2();
createRectBody({x:265, y:435, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick2"});
brickAsset = new BrickAsset3();
createRectBody({x:220, y:405, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick3"});
brickAsset = new BrickAsset4();
createRectBody({x:220, y:375, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick4"});
brickAsset = new BrickAsset5();
createRectBody({x:205, y:345, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick5"});
brickAsset = new BrickAsset6();
createRectBody({x:220, y:300, width:brickAsset.width, height:brickAsset.height,
asset:brickAsset, type:b2Body.b2_dynamicBody, canDestroy:true, id:"brick6"});
//创建头像
var iconAsset:IconAsset = new IconAsset();
createRectBody({x:220, y:80, width:iconAsset.width, height:iconAsset.height,
asset:iconAsset, type:b2Body.b2_dynamicBody, id:"userIcon"});
addEventListener(Event.ENTER_FRAME,onUpdate);
stage.addEventListener(MouseEvent.CLICK, onStageClick);
}
private function drawBackground():void {
graphics.beginFill(backgroundColor);
graphics.drawRect(0, 0, stageWidth, stageHeight);
graphics.endFill();
}
private function createTip():void {
var tip:TextField = new TextField();
var format:TextFormat = new TextFormat();
format.size = 14;
format.color = 0xFFFFFF;
tip.autoSize = TextFieldAutoSize.LEFT;
tip.defaultTextFormat = format;
tip.text = "砖块可销毁(点击它)";
addChild(tip);
tip.x = (stageWidth - tip.width) / 2;
}
private function createInfo():void {
info = new TextField();
var format:TextFormat = new TextFormat();
format.size = 14;
format.color = 0xFFFFFF;
info.autoSize = TextFieldAutoSize.LEFT;
info.defaultTextFormat = format;
addChild(info);
}
private function createWorld():void {
var gravity:b2Vec2 = new b2Vec2(0, 9.81); //重力
//世界中的刚体静止时,可以允许他们进入睡眠状态,睡眠的刚体无需模拟
var sleep:Boolean = true;
world = new b2World(gravity, sleep);
}
private function onStageClick(event:MouseEvent):void {
var x:Number = mouseX / worldScale;
var y:Number = mouseY / worldScale;
//世界的QueryPoint方法查询世界中所有的夹具,找出在点上的夹具,
//然后如果有夹具在鼠标点击的点上,我们可以说我们点击了一个夹具。
world.QueryPoint(queryCallback, new b2Vec2(x, y));
}
//在鼠标点击的点上的夹具。因为一个点上可以有不止一个的夹具(试
//想一下重叠的staitc类型的刚体),如果你希望检查下一个夹具,那么你需要
//让函数返回true,或者返回false将停止检查。
private function queryCallback(fixture:b2Fixture):Boolean {
var touchedBody:b2Body = fixture.GetBody();
var userData:Object = touchedBody.GetUserData(); //获取自定义的刚体信息
if(userData.canDestroy == true) {
world.DestroyBody(touchedBody); //销毁刚体
removeChild(userData.asset);
}
//我们假设只可以有一个夹具在鼠标点击的点上
//所以return false
return false;
}
private function createRectBody(data:Object):void {
var bodyDef:b2BodyDef = new b2BodyDef(); //刚体定义
if(data.type != undefined) {
bodyDef.type = data.type; //刚体类型默认为静态
}
bodyDef.position.Set(data.x/worldScale, data.y/worldScale);//设置刚体坐标, Box2D坐标用米表示
bodyDef.userData = new Object();
if(data.id != undefined) {
bodyDef.userData.id = data.id;
}
if(data.asset != undefined) {
bodyDef.userData.asset = data.asset;//为刚体设置皮肤
}
if(data.canDestroy != undefined) {
bodyDef.userData.canDestroy = data.canDestroy;//点击时,是否能销毁
}else {
bodyDef.userData.canDestroy = false;
}
var polygonShape:b2PolygonShape = new b2PolygonShape(); //创建多边形
polygonShape.SetAsBox(data.width/2/worldScale, data.height/2/worldScale);//轴对称的矩形, 半宽长和半高长
var fixtureDef:b2FixtureDef = new b2FixtureDef(); //夹具(fixture)用于将形状绑定到刚体上
if(data.density != undefined) { //密度
fixtureDef.density = data.density;
}else {
fixtureDef.density = 1;
}
if(data.restitution != undefined) { //弹性系数
fixtureDef.restitution = data.restitution;
}else {
fixtureDef.restitution = 0.1;
}
if(data.friction != undefined) { //摩擦系数
fixtureDef.friction = data.friction;
}else {
fixtureDef.friction = 0.1;
}
fixtureDef.shape = polygonShape;
var body:b2Body = world.CreateBody(bodyDef); //创建刚体
body.CreateFixture(fixtureDef);
if(data.asset != undefined) {
addChild(data.asset);
data.asset.x = body.GetPosition().x * worldScale;
data.asset.y = body.GetPosition().y * worldScale;
}
}
private function onUpdate(e:Event):void {
world.Step(timeStep, velIterations, posIterations);
world.ClearForces();
//GetBodyList()方法获得世界刚体列表并返回列表的第一个刚体.
//使用GetNext()方法获得列表的下一个刚体,但是如果你的刚
//体已经到达了刚体列表的末端,这时GetNext()方法将返回null
for (var body:b2Body = world.GetBodyList(); body; body = body.GetNext()) {
if(body.GetUserData()) {
var x:Number = body.GetPosition().x * worldScale;
var y:Number = body.GetPosition().y * worldScale;
var angle:Number = body.GetAngle() * 180 / Math.PI; //弧度转为度
if(body.GetUserData().id == "userIcon") {
info.text = "头像刚体的属性\n坐标: ";
info.appendText(x.toFixed(1));
info.appendText(", ");
info.appendText(y.toFixed(1));
info.appendText("\n角度: ");
info.appendText(angle.toFixed(1));
info.appendText("\n速度: ");
//GetLinearVelocity()方法获得刚体中心的线速度,然后返回
//一个b2Vec2对象,它代表水平和垂直速度,单位是米每秒
var v:b2Vec2 = body.GetLinearVelocity();
var vx:Number = v.x * worldScale;
info.appendText(vx.toFixed(1));
info.appendText(", ");
var vy:Number = v.y * worldScale;
info.appendText(vy.toFixed(1));
}
if(body.GetUserData().asset) {
body.GetUserData().asset.x = x;
body.GetUserData().asset.y = y;
body.GetUserData().asset.rotation = angle;
}
}
}
}
}
}