Fork me on GitHub

Box2dの自定义多边形

注:点击鼠标添加Body,R键清空Body

  原来博客园要注册才能看到swf的,附有截图

package 
{
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2CircleDef;
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Common.Math.b2Math;
import Box2D.Common.Math.b2Vec2;
import Box2D.Common.Math.b2XForm;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.ui.Keyboard;
import ipk.bmpd.CutCtrl;
/**
* ...
* @description HelloWorldの多边形
* @author ispooky
* @date 2010.11.09
*
* @see
http://ispooky.cnblogs.com
*/
public class PolygonsApp extends Sprite
{
public static const ITERATIONS :int = 30;
public static const TIME_STEP :Number = 1 / 30;
public static const RATIO :int = 30;

private static var world :b2World;
private static var spriteToDrawOn :Sprite;

public function PolygonsApp()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);

initB2D();
stage.addEventListener(MouseEvent.CLICK, onClickHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
}

private function onKeyDownHandler(e:KeyboardEvent):void
{
if (e.keyCode == 82/*R*/)
{
/////////////////////////////
// 销毁Body
/////////////////////////////
for (var bb:b2Body = world.m_bodyList; bb; bb = bb.m_next)
{
if (bb.m_userData is Sprite)
{
removeChild(bb.m_userData);
world.DestroyBody(bb);
}
}
}
}

private function onClickHandler(e:MouseEvent):void
{
if (world == null) return;
createPolygon();
}

private function initB2D():void
{
addEventListener(Event.ENTER_FRAME, onLoopHandler, false, 0, true);
createWorld();
//showDebug();
createGrounds();
createPolygon();
createPolygon();
createPolygon();
}

/**
* 添加Body
* @param _type
*/
private function createPolygon(_type:int = -1):void
{
var bodyDef:b2BodyDef = new b2BodyDef();
var boxDef:b2PolygonDef = new b2PolygonDef();
var circleDef:b2CircleDef = new b2CircleDef();
var body:b2Body;
var type:int
if (_type == -1)
{
var tmp_arr:Array = [0, 3, 4, 6, 8];
type = tmp_arr[int(Math.random() * 5)];
}else
{
type = _type;
}

var skin:Sprite = new Sprite();
var tmp_asset:Bitmap;
var radius:int;
var i:int;
var tmp_radius:int = Math.random() * 40 + 30;
var start_pos:Point = new Point(Math.random() * 100 - 50 + 275, Math.random() * 100 - 50 -100);

switch(type)
{
case 0:
bodyDef.position.Set(start_pos.x / RATIO, start_pos.y / RATIO);
radius = int(Math.random() * 25) + 10;
circleDef.radius = radius / RATIO;
circleDef.density = 1;
circleDef.friction = 0.2;
circleDef.restitution = 0.3;
tmp_asset = getAssets(0, radius);
tmp_asset.x = -tmp_asset.width * 0.5;
tmp_asset.y = -tmp_asset.height * 0.5;
skin.addChild(tmp_asset);
bodyDef.userData = skin;
addChild(bodyDef.userData);
body = world.CreateBody(bodyDef);
body.CreateShape(circleDef);
body.SetMassFromShapes();
break;
case 3:
createPolygonTypeOf(start_pos.x, start_pos.y, 3, tmp_radius);
break;
case 4:
createPolygonTypeOf(start_pos.x, start_pos.y, 4, tmp_radius);
break;
case 5:
createPolygonTypeOf(start_pos.x, start_pos.y, 5, tmp_radius);
break;
case 6:
createPolygonTypeOf(start_pos.x, start_pos.y, 6, tmp_radius);
break;
case 7:
createPolygonTypeOf(start_pos.x, start_pos.y, 7, tmp_radius);
break;
case 8:
createPolygonTypeOf(start_pos.x, start_pos.y, 8, tmp_radius);
break;
}
}

/**
* 创建正多边形Body
* @param xpos
* @param ypos
* @param vertexCount
* @param radius
*/
private function createPolygonTypeOf(xpos:Number, ypos:Number, vertexCount:int, radius:Number):void
{
var boxDef:b2PolygonDef = new b2PolygonDef();
boxDef.vertexCount = vertexCount;
var angle:Number = Math.PI * 2 / vertexCount;
var radius:Number = radius / RATIO;
for (var i:int = 0; i < vertexCount; i++)
{
var dx:Number = radius * Math.cos(angle * i);
var dy:Number = radius * Math.sin(angle * i);
boxDef.vertices[i] = b2Math.b2MulX(new b2XForm(),new b2Vec2(dx, dy));
}
boxDef.density = 2;
boxDef.friction = 0.3;
boxDef.restitution = 0.3;

var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.angle = Math.random() * 360;
bodyDef.position.Set(xpos / RATIO, ypos / RATIO);

var skin:Sprite = new Sprite();
var tmp_asset:Bitmap;
switch(vertexCount)
{
case 3:
tmp_asset = getAssets(vertexCount, radius * RATIO);
tmp_asset.x = -(tmp_asset.width - radius * RATIO);
tmp_asset.y = -tmp_asset.height * 0.5;
skin.addChild(tmp_asset);
break;
case 4:
tmp_asset = getAssets(vertexCount, radius * RATIO);
tmp_asset.x = -tmp_asset.width*0.5;
tmp_asset.y = -tmp_asset.height * 0.5;
skin.addChild(tmp_asset);
break;
case 6:
tmp_asset = getAssets(vertexCount, radius * RATIO);
tmp_asset.x = -tmp_asset.width*0.5;
tmp_asset.y = -tmp_asset.height * 0.5;
skin.addChild(tmp_asset);
break;
case 8:
tmp_asset = getAssets(vertexCount, radius * RATIO);
tmp_asset.x = -tmp_asset.width*0.5;
tmp_asset.y = -tmp_asset.height * 0.5;
skin.addChild(tmp_asset);
break;
}



bodyDef.userData = skin;
addChild(bodyDef.userData);

var body:b2Body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);
body.SetMassFromShapes();
}

/**
* 创建地板
*/
private function createGrounds():void
{
var bodyDef:b2BodyDef = new b2BodyDef();
var boxDef:b2PolygonDef = new b2PolygonDef();
var body:b2Body;

bodyDef.position.Set(275 / RATIO, 360 / RATIO);
boxDef.SetAsBox(900 / 2 / RATIO, 30 / 2 / RATIO);
boxDef.density = 0;
boxDef.friction = 0.3;
boxDef.restitution = 0.2;

body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);

boxDef.SetAsOrientedBox(30 / 2 / RATIO, 90 / 2 / RATIO, new b2Vec2( -200 / RATIO, -60 / RATIO), 0);
body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);

boxDef.SetAsOrientedBox(30 / 2 / RATIO, 90 / 2 / RATIO, new b2Vec2( 200 / RATIO, -60 / RATIO), 0);
body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);

boxDef.SetAsOrientedBox(30 / 2 / RATIO, 45 / 2 / RATIO, new b2Vec2( -435 / RATIO, -37.5 / RATIO), 0);
body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);

boxDef.SetAsOrientedBox(30 / 2 / RATIO, 45 / 2 / RATIO, new b2Vec2( 435 / RATIO, -37.5 / RATIO), 0);
body = world.CreateBody(bodyDef);
body.CreateShape(boxDef);
}

/**
* 显示Debug图
*/
private function showDebug():void
{
spriteToDrawOn = new Sprite();
addChild(spriteToDrawOn);
var dbgDraw:b2DebugDraw = new b2DebugDraw();
dbgDraw.m_sprite = spriteToDrawOn;
dbgDraw.m_drawScale = RATIO;
dbgDraw.m_fillAlpha = 0.6;
dbgDraw.m_lineThickness = 1.0;
dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;

world.SetDebugDraw(dbgDraw);
}

/**
* 创建物理空间
*/
private function createWorld():void
{
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set( -3000 / RATIO, -3000 / RATIO);
worldAABB.upperBound.Set(3000 / RATIO, 3000 / RATIO);

var gravity:b2Vec2 = new b2Vec2(0, 10);
var doSleep:Boolean = true;

world = new b2World(worldAABB, gravity, doSleep);
}

/**
* 刷新物理空间
* @param e
*/
private function onLoopHandler(e:Event):void
{
if (world == null) return;
world.Step(TIME_STEP, ITERATIONS);
for (var bb:b2Body = world.m_bodyList; bb; bb = bb.m_next)
{
if (bb.m_userData is Sprite)
{
bb.m_userData.x = bb.GetPosition().x * RATIO;
bb.m_userData.y = bb.GetPosition().y * RATIO;
bb.m_userData.rotation = bb.GetAngle() * (180 / Math.PI);
}
}
}

/**
* 获取贴图
* @param type
* @param radius
* @return
*/
private function getAssets(type:int = 0, radius:int = 20):Bitmap
{

var target_mc:Sprite = new Sprite();
target_mc.visible = false;
addChild(target_mc);
var tmp_bmpd:BitmapData = new Alsace_Pic();
var tmp_bmp:Bitmap = new Bitmap(tmp_bmpd);
target_mc.addChild(tmp_bmp);
var tmp_mc:Sprite = new Sprite();
tmp_mc.visible = false;
tmp_mc.x = target_mc.x;
tmp_mc.y = target_mc.y;
addChild(tmp_mc);
var new_bmp:Bitmap;

var i:int;
var pos:Point = new Point(Math.random() * 600 - 300 + 720, Math.random() * 200 - 100 + 450);
tmp_mc.graphics.clear();
tmp_mc.graphics.beginFill(0x900000);
switch(type)
{
case 0:
tmp_mc.graphics.drawCircle(pos.x, pos.y, radius);
tmp_mc.graphics.endFill();

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());

break;

case 3:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 3; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 3 * i), pos.y + radius * Math.sin(Math.PI * 2 / 3 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
case 4:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 4; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 4 * i), pos.y + radius * Math.sin(Math.PI * 2 / 4 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
case 5:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 5; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 5 * i), pos.y + radius * Math.sin(Math.PI * 2 / 5 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
case 6:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 6; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 6 * i), pos.y + radius * Math.sin(Math.PI * 2 / 6 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
case 7:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 7; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 7 * i), pos.y + radius * Math.sin(Math.PI * 2 / 7 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
case 8:
tmp_mc.graphics.moveTo(pos.x + radius, pos.y);
for (i = 1; i < 8; i++)
{
tmp_mc.graphics.lineTo(pos.x + radius * Math.cos(Math.PI * 2 / 8 * i), pos.y + radius * Math.sin(Math.PI * 2 / 8 * i));
}

new_bmp = new Bitmap(CutCtrl.cutOutSuper(target_mc, tmp_mc).clone());
break;
}
tmp_bmpd.dispose();
removeChild(tmp_mc);
tmp_mc = null;
removeChild(target_mc);
target_mc = null;
return new_bmp;
}

}

}



posted on 2012-03-14 11:52  pengyingh  阅读(1160)  评论(0编辑  收藏  举报

导航