Box2D試作:シロクロ フィジックス
シロクロシリーズをBox2Dオンリーで実現するためのテスト。
/**
* Copyright o_healer ( http://wonderfl.net/user/o_healer )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/iix4
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
//Box2D
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0xFFFFFF")]
public class GameMain extends Sprite {
//==Const==
//画面サイズ
static public const VIEW_W:int = 465;
static public const VIEW_H:int = 465;
//重力
static public const GRAVITY:Number = 9.8;
//Box2Dと実際の表示の比率(Box2Dに大きすぎる値を入れると上手く動かなかったりする)
static public const PHYS_SCALE:Number = 10;
static public function PHYS_to_IMAGE(in_Val:Number):Number{return in_Val * PHYS_SCALE;}
static public function IMAGE_to_PHYS(in_Val:Number):Number{return in_Val / PHYS_SCALE;}
//Box2Dの画面外の余白
static public const BOX2D_RANGE_OFFSET:int = 100;
//==Var==
//Box2D
public var m_Box2D_World:b2World;
//マウスで動かせる球
public var m_MouseBallBody:b2Body;
public var m_MouseJoint:b2MouseJoint;
//==Function==
//Init
public function GameMain(){
//Box2D
{
//考慮する領域
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(-BOX2D_RANGE_OFFSET));
worldAABB.upperBound.Set(IMAGE_to_PHYS(VIEW_W+BOX2D_RANGE_OFFSET), IMAGE_to_PHYS(VIEW_H+BOX2D_RANGE_OFFSET));
//重力ベクトル
var gravity:b2Vec2 = new b2Vec2(0.0, GRAVITY);
//Sleep
var useSleep:Boolean = true;
//物理world
m_Box2D_World = new b2World(worldAABB, gravity, useSleep);
}
var w:Number = VIEW_W;
{
w /= Math.sqrt(2);
var OuterBox:b2Body = CreateCollision_Box(
VIEW_W/2,//X
VIEW_H/2,//Y
w,//W
w,//H
0,//Rot
0x01,//Category:In
0x02,//Category:Out
false//IsFix
);
var Fulcrum:b2Body = CreateCollision_Box(
VIEW_W/2,//X
VIEW_H/2,//Y
8,//W
8,//H
0,//Rot
0x00,//Category:In
0x00,//Category:Out
true//IsFix
);
var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();
jointDef.Initialize(OuterBox, Fulcrum, Fulcrum.GetWorldCenter());
// jointDef.maxMotorTorque = 1000000;
// jointDef.motorSpeed = 0.2;
// jointDef.enableMotor = true;
m_Box2D_World.CreateJoint(jointDef);
}
{
w /= Math.sqrt(2);
CreateCollision_Delta(
VIEW_W/2,//X
VIEW_H/2,//Y
w,//W
0,//Rot
0x02,//Category:In
0x04,//Category:Out
false//IsFix
);
w /= 2;
}
//*
{
w /= Math.sqrt(2);
CreateCollision_Box(
VIEW_W/2,//X
VIEW_H/2,//Y
w,//W
w,//H
0,//Rot
0x14,//Category:In
0x08,//Category:Out
false//IsFix
);
}
//*/
//*
//周囲
{
//U
CreateCollision_Box(
VIEW_W/2,//X
-5,//Y
VIEW_W,//W
10,//H
0,//Rot
0x10,//Category:In
0x00,//Category:Out
true//IsFix
);
//D
CreateCollision_Box(
VIEW_W/2,//X
VIEW_H + 5,//Y
VIEW_W,//W
10,//H
0,//Rot
0x10,//Category:In
0x00,//Category:Out
true//IsFix
);
//L
CreateCollision_Box(
-5,//X
VIEW_H/2,//Y
10,//W
VIEW_H,//H
0,//Rot
0x10,//Category:In
0x00,//Category:Out
true//IsFix
);
//R
CreateCollision_Box(
VIEW_W + 5,//X
VIEW_H/2,//Y
10,//W
VIEW_H,//H
0,//Rot
0x10,//Category:In
0x00,//Category:Out
true//IsFix
);
}
//*/
//Mouse
{
CreateCollision_MouseSphere(
10
);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
/*
//Debug
{
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = this;
debugDraw.m_drawScale = PHYS_SCALE;
debugDraw.m_fillAlpha = 1;
debugDraw.m_lineThickness = 1;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
m_Box2D_World.SetDebugDraw(debugDraw);
}
//*/
}
//Create : Collision : Box
public function CreateCollision_Box(in_X:int, in_Y:int, in_W:int, in_H:int, in_Rot:Number = 0, in_Filter_In:uint = 0x01, in_Filter_Out:uint = 0xFF, in_FixFlag:Boolean = false):b2Body{
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0x000000);
sprite.graphics.drawRect(-in_W/2, -in_H/2, in_W, in_H);
sprite.graphics.endFill();
addChild(sprite);
}
//Shape Def
var shapeDef:b2PolygonDef;
{
shapeDef = new b2PolygonDef();
shapeDef.SetAsBox(IMAGE_to_PHYS(in_W/2), IMAGE_to_PHYS(in_H/2));
shapeDef.filter.categoryBits = in_Filter_In;
shapeDef.filter.maskBits = in_Filter_In;
if(in_FixFlag){
shapeDef.density = 0;//Fix
}else{
shapeDef.density = 1;//tekitou
}
}
//Body Def
var bodyDef:b2BodyDef;
{
bodyDef = new b2BodyDef();
bodyDef.position.Set(IMAGE_to_PHYS(in_X), IMAGE_to_PHYS(in_Y));
bodyDef.angle = in_Rot;
}
//Body
var body:b2Body;
{
body = m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
body.SetMassFromShapes();
body.m_userData = sprite;
}
//枠
{
//Shape Def
var shapeDef_Frame:b2PolygonDef;
{
shapeDef_Frame = new b2PolygonDef();
shapeDef_Frame.filter.categoryBits = in_Filter_Out;
shapeDef_Frame.filter.maskBits = in_Filter_Out;
if(in_FixFlag){
shapeDef_Frame.density = 0;//Fix
}else{
shapeDef_Frame.density = 0.001;//tekitou
}
// shapeDef_Frame.SetAsBox(IMAGE_to_PHYS(in_W/2), IMAGE_to_PHYS(in_H/2));
}
var Offset:int = 10;
var center:b2Vec2 = new b2Vec2();
for(var i:int = 0; i < 4; i++){
var angle:Number = 2*Math.PI * i/4;
center.x = IMAGE_to_PHYS(in_W/2+Offset)*Math.sin(angle);
center.y = IMAGE_to_PHYS(in_H/2+Offset)*Math.cos(angle);
if((i&1) == 0){
shapeDef_Frame.SetAsOrientedBox(IMAGE_to_PHYS(in_W/2), IMAGE_to_PHYS(Offset), center, angle);
}else{
shapeDef_Frame.SetAsOrientedBox(IMAGE_to_PHYS(in_H/2), IMAGE_to_PHYS(Offset), center, angle);
}
body.CreateShape(shapeDef_Frame);
}
}
body.SetMassFromShapes();
return body;
}
//Create : Collision : Delta
public function CreateCollision_Delta(in_X:int, in_Y:int, in_R:int, in_Rot:Number = 0, in_Filter_In:uint = 0x01, in_Filter_Out:uint = 0xFF, in_FixFlag:Boolean = false):b2Body{
// var W:Number = in_R/2 * Math.cos(Math.PI/6);
// var H:Number = in_R/2 * Math.sin(Math.PI/6);
// var H_Max:Number = in_R/2;
var R:Number;
//Image
var sprite:Sprite;
{
R = in_R/2;
sprite = new Sprite();
sprite.graphics.beginFill(0xFFFFFF);
// sprite.graphics.moveTo( 0, H_Max);
// sprite.graphics.lineTo(-W,-H);
// sprite.graphics.lineTo( W,-H);
// sprite.graphics.lineTo( 0, H_Max);
sprite.graphics.moveTo(R*Math.cos(Math.PI*0/3), R*Math.sin(Math.PI*0/3));
sprite.graphics.lineTo(R*Math.cos(Math.PI*2/3), R*Math.sin(Math.PI*2/3));
sprite.graphics.lineTo(R*Math.cos(Math.PI*4/3), R*Math.sin(Math.PI*4/3));
sprite.graphics.lineTo(R*Math.cos(Math.PI*0/3), R*Math.sin(Math.PI*0/3));
sprite.graphics.endFill();
//sprite.graphics.beginFill(0xFF0000);
//sprite.graphics.drawCircle(0, 10, 10);
//sprite.graphics.endFill();
addChild(sprite);
}
//Shape Def
var shapeDef:b2PolygonDef;
{
R = IMAGE_to_PHYS(in_R/2);
shapeDef = new b2PolygonDef();
shapeDef.vertexCount = 3;
// shapeDef.vertices[0].Set(0, IMAGE_to_PHYS(H_Max));
// shapeDef.vertices[1].Set(IMAGE_to_PHYS(-W), IMAGE_to_PHYS(-H));
// shapeDef.vertices[2].Set(IMAGE_to_PHYS( W), IMAGE_to_PHYS(-H));
shapeDef.vertices[0].Set(R*Math.cos(Math.PI*0/3), R*Math.sin(Math.PI*0/3));
shapeDef.vertices[1].Set(R*Math.cos(Math.PI*2/3), R*Math.sin(Math.PI*2/3));
shapeDef.vertices[2].Set(R*Math.cos(Math.PI*4/3), R*Math.sin(Math.PI*4/3));
shapeDef.filter.categoryBits = in_Filter_In;
shapeDef.filter.maskBits = in_Filter_In;
if(in_FixFlag){
shapeDef.density = 0;//Fix
}else{
shapeDef.density = 1;//tekitou
}
}
//Body Def
var bodyDef:b2BodyDef;
{
bodyDef = new b2BodyDef();
bodyDef.position.Set(IMAGE_to_PHYS(in_X), IMAGE_to_PHYS(in_Y));
//bodyDef.angle = 0;
}
//Body
var body:b2Body;
{
body = m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
body.SetMassFromShapes();
body.m_userData = sprite;
}
//枠
{
//Shape Def
var shapeDef_Frame:b2PolygonDef;
{
shapeDef_Frame = new b2PolygonDef();
shapeDef_Frame.filter.categoryBits = in_Filter_Out;
shapeDef_Frame.filter.maskBits = in_Filter_Out;
if(in_FixFlag){
shapeDef_Frame.density = 0;//Fix
}else{
shapeDef_Frame.density = 0.001;//tekitou
}
// shapeDef_Frame.SetAsBox(IMAGE_to_PHYS(in_W/2), IMAGE_to_PHYS(in_H/2));
}
var Offset:int = 10;
R = in_R/2 * Math.sin(Math.PI/6) + Offset;
var W:Number = in_R/2 * Math.cos(Math.PI/6);
var center:b2Vec2 = new b2Vec2();
for(var i:int = 0; i < 3; i++){
var angle:Number = 2*Math.PI * (i+0.5)/3;
center.x = IMAGE_to_PHYS(R)*Math.cos(angle);
center.y = IMAGE_to_PHYS(R)*Math.sin(angle);
shapeDef_Frame.SetAsOrientedBox(IMAGE_to_PHYS(Offset), IMAGE_to_PHYS(W), center, angle);
body.CreateShape(shapeDef_Frame);
}
}
body.SetMassFromShapes();
return body;
}
//Create : Collision : Sphere for Mouse
public function CreateCollision_MouseSphere(in_R:int):void{
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xFF0000);
sprite.graphics.drawCircle(0,0, in_R);
sprite.graphics.endFill();
addChild(sprite);
}
//Shape Def
var shapeDef:b2CircleDef;
{
shapeDef = new b2CircleDef();
shapeDef.radius = IMAGE_to_PHYS(in_R);
shapeDef.density = 10;//tekitou
shapeDef.filter.categoryBits = 0x10;
shapeDef.filter.maskBits = 0x10;
}
//Body Def
var bodyDef:b2BodyDef;
{
bodyDef = new b2BodyDef();
bodyDef.position.Set(IMAGE_to_PHYS(VIEW_W/2), IMAGE_to_PHYS(VIEW_H/2));
}
//Body
/*
var body:b2Body;
{
body = m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
body.SetMassFromShapes();
body.m_userData = sprite;
}
/*/
{
m_MouseBallBody = m_Box2D_World.CreateBody(bodyDef);
m_MouseBallBody.CreateShape(shapeDef);
m_MouseBallBody.SetMassFromShapes();
m_MouseBallBody.m_userData = sprite;
}
//*/
//Joint
{
var mjd:b2MouseJointDef = new b2MouseJointDef();
mjd.body1 = m_Box2D_World.GetGroundBody();
mjd.body2 = m_MouseBallBody;
//mjd.target.Set(IMAGE_to_PHYS(mouseX), IMAGE_to_PHYS(mouseY));
mjd.target.Set(bodyDef.position.x, bodyDef.position.y);
mjd.maxForce = 300.0 * m_MouseBallBody.GetMass();
mjd.timeStep = 1.0/30.0;
m_MouseJoint = m_Box2D_World.CreateJoint(mjd) as b2MouseJoint;
}
}
//Update
public function Update(e:Event=null):void{
//今回進める時間
var DeltaTime:Number = 1.0/30.0;
//マウスのところに移動
/*
m_MouseBallBody.SetXForm(new b2Vec2(IMAGE_to_PHYS(mouseX), IMAGE_to_PHYS(mouseY)), 0);
m_MouseBallBody.SetLinearVelocity(new b2Vec2(0,0));
//*/
/*
var gap:b2Vec2 = m_MouseBallBody.GetPosition();
gap.x = (IMAGE_to_PHYS(mouseX) - gap.x) / DeltaTime;
gap.y = (IMAGE_to_PHYS(mouseY) - gap.y) / DeltaTime;
m_MouseBallBody.SetLinearVelocity(gap);
//*/
//*
m_MouseJoint.SetTarget(new b2Vec2(IMAGE_to_PHYS(mouseX), IMAGE_to_PHYS(mouseY)));
//*/
//物理エンジンをDeltaTimeだけ進める
m_Box2D_World.Step(DeltaTime, 10);
/*
//ぶつかっているものを見つけて、対応関数を呼ぶ
for(var iter:b2Contact = m_Box2D_World.GetContactList(); iter != null; iter = iter.GetNext()){
if(iter.GetManifoldCount() == 0){
continue;
}
var Obj1:IObject = iter.GetShape1().m_body.m_userData as IObject;
var Obj2:IObject = iter.GetShape2().m_body.m_userData as IObject;
var Nrm:b2Vec2 = iter.GetManifolds()[0].normal;
Obj1.OnContact_Common(Obj2, Nrm.x, Nrm.y);
Obj2.OnContact_Common(Obj1, -Nrm.x, -Nrm.y);
Obj1.OnContact(Obj2, Nrm.x, Nrm.y);
Obj2.OnContact(Obj1, -Nrm.x, -Nrm.y);
}
//*/
//Spriteへの位置の反映
for (var bb:b2Body = m_Box2D_World.m_bodyList; bb; bb = bb.m_next) {
if(bb.m_userData != null){
bb.m_userData.x = PHYS_to_IMAGE(bb.GetPosition().x);
bb.m_userData.y = PHYS_to_IMAGE(bb.GetPosition().y);
//bb.m_userData.m_VX = PHYS_to_IMAGE(bb.m_linearVelocity.x);
//bb.m_userData.m_VY = PHYS_to_IMAGE(bb.m_linearVelocity.y);
bb.m_userData.rotation = bb.GetAngle() * 180/Math.PI;
}
}
}
}
}