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/1Kfq
*/
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="0x000000")]
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);
}
//周囲
{
//D
CreateCollision_Box(
VIEW_W/2,//X
VIEW_H - 30,//Y
VIEW_W,//W
10,//H
0,//Rot
true//IsFix
);
//L
CreateCollision_Box(
30,//X
VIEW_H/2,//Y
10,//W
VIEW_H,//H
0,//Rot
true//IsFix
);
//R
CreateCollision_Box(
VIEW_W - 30,//X
VIEW_H/2,//Y
10,//W
VIEW_H,//H
0,//Rot
true//IsFix
);
}
//段差
{
CreateCollision_Box(
VIEW_W*1/4,//X
VIEW_H*3/4,//Y
VIEW_W/4,//W
10,//H
0,//Rot
true//IsFix
);
CreateCollision_Box(
VIEW_W*2/4,//X
VIEW_H*2/4,//Y
VIEW_W/4,//W
10,//H
0,//Rot
true//IsFix
);
CreateCollision_Box(
VIEW_W*3/4,//X
VIEW_H*1/4,//Y
VIEW_W/4,//W
10,//H
0,//Rot
true//IsFix
);
}
//▽
{
//普通に逆三角形を作り、その下に見えないおもりを付ける
var Rad:Number = 30;
var X:Number = VIEW_W*3/4;
var Y:Number = 0;
CreateCollision_Delta(X, Y, Rad);
}
//Daruma
{
CreateCollision_Daruma(VIEW_W*2/4, VIEW_W*1/4, 20);
}
//Mouse
{
CreateCollision_MouseSphere(
10
);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
}
//Create : Collision : Box
public function CreateCollision_Box(in_X:int, in_Y:int, in_W:int, in_H:int, in_Rot:Number = 0, in_FixFlag:Boolean = false):void{
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xDDDDDD);
sprite.graphics.drawRect(-in_W/2, -in_H/2, in_W, in_H);
sprite.graphics.endFill();
sprite.filters = [new GlowFilter(0x0088FF)];
addChild(sprite);
}
//Shape Def
var shapeDef:b2PolygonDef;
{
shapeDef = new b2PolygonDef();
shapeDef.SetAsBox(IMAGE_to_PHYS(in_W/2), IMAGE_to_PHYS(in_H/2));
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;
}
}
//Create : Collision : Sphere
public function CreateCollision_Sphere(in_X:int, in_Y:int, in_R:int, in_FixFlag:Boolean = false):void{
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xDDDDDD);
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);
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));
}
//Body
var body:b2Body;
{
body = m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
body.SetMassFromShapes();
body.m_userData = sprite;
}
}
//Create : Collision : Delta
public function CreateCollision_Delta(in_X:int, in_Y:int, in_R:int):void{
var W:Number = in_R/2;
var H:Number = in_R * Math.sqrt(3)/2;
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xDDDDDD);
sprite.graphics.moveTo(0,0);
sprite.graphics.lineTo(-W,-H);
sprite.graphics.lineTo( W,-H);
sprite.graphics.lineTo(0,0);
sprite.graphics.endFill();
//sprite.graphics.beginFill(0xFF0000);
//sprite.graphics.drawCircle(0, 10, 10);
//sprite.graphics.endFill();
sprite.filters = [new GlowFilter(0x00FF88)];
addChild(sprite);
}
//Shape Def
var shapeDef:b2PolygonDef;
{
shapeDef = new b2PolygonDef();
shapeDef.vertexCount = 3;
shapeDef.vertices[0].Set(0, 0);
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.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;
}
//Weight : Shape
var shapeDef_Weight:b2CircleDef;
{
shapeDef_Weight = new b2CircleDef();
shapeDef_Weight.density = 50;//Weight
shapeDef_Weight.radius = IMAGE_to_PHYS(10);
shapeDef_Weight.localPosition.y = IMAGE_to_PHYS(10);
//他のコリジョンとはぶつからないようにする
shapeDef_Weight.filter.categoryBits = 0x0000;
//追加
body.CreateShape(shapeDef_Weight);
body.SetMassFromShapes();
}
}
//Create : Collision : Daruma
public function CreateCollision_Daruma(in_X:int, in_Y:int, in_R:int, in_FixFlag:Boolean = false):void{
const HeadRatio:Number = 0.8;
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xDDDDDD);
sprite.graphics.drawCircle(0,0, in_R);
sprite.graphics.endFill();
sprite.graphics.beginFill(0xDDDDDD);
sprite.graphics.drawCircle(0,-(1+HeadRatio)*in_R, in_R*HeadRatio);
sprite.graphics.endFill();
sprite.filters = [new GlowFilter(0xFF2222)];
addChild(sprite);
}
//Shape Def
var shapeDef:b2CircleDef;
{
shapeDef = new b2CircleDef();
shapeDef.radius = IMAGE_to_PHYS(in_R);
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));
}
//Body
var body:b2Body;
{
body = m_Box2D_World.CreateBody(bodyDef);
body.CreateShape(shapeDef);
//body.SetMassFromShapes();
body.m_userData = sprite;
}
//Head
{
shapeDef.radius = IMAGE_to_PHYS(HeadRatio*in_R);
shapeDef.localPosition.y = IMAGE_to_PHYS(-(1+HeadRatio)*in_R);
body.CreateShape(shapeDef);
//body.SetMassFromShapes();
}
//Weight : Shape
var shapeDef_Weight:b2CircleDef;
{
shapeDef_Weight = new b2CircleDef();
shapeDef_Weight.density = 50;//Weight
shapeDef_Weight.radius = IMAGE_to_PHYS(10);
shapeDef_Weight.localPosition.y = IMAGE_to_PHYS(10);
//他のコリジョンとはぶつからないようにする
shapeDef_Weight.filter.categoryBits = 0x0000;
//追加
body.CreateShape(shapeDef_Weight);
body.SetMassFromShapes();
}
}
//Create : Collision : Sphere for Mouse
public function CreateCollision_MouseSphere(in_R:int):void{
//Image
var sprite:Sprite;
{
sprite = new Sprite();
sprite.graphics.beginFill(0xDDDDDD);
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 = 1;//tekitou
}
//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;
}
}
}
}
}