wonderfl用Box2Dテンプレートを作ってみたい。Ver0.1
wonderfl用Box2Dテンプレートを作ってみたい。Ver0.1
最近少し忙しいのでちょこちょことやる予定。
Box2Dはいろいろ手続きが面倒すぎるので、楽しいところだけ弄れるようにしたい。
ここを大いに参考にしてるというか、ほぼそのまま・・・。
でも、ここからいろいろ拡張していきたい。できるのかは知らないけれど。
http://hokori.net/2009/02/18/box2dflashas3_base/
package
{
import flash.display.Sprite;
import Box2D.Collision.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Collision.Shapes.*;
import flash.events.Event;
/**
* wonderfl用Box2Dテンプレートを作ってみたい。Ver0.1
*
* 最近少し忙しいのでちょこちょことやる予定。
* Box2Dはいろいろ手続きが面倒すぎるので、楽しいところだけ弄れるようにしたい。
*
* ここを大いに参考にしてるというか、ほぼそのまま・・・。
* でも、ここからいろいろ拡張していきたい。できるのかは知らないけれど。
* http://hokori.net/2009/02/18/box2dflashas3_base/
*/
[SWF(width=465,height=465,frameRate=60,backgroundColor=0x000000)]
public class Test extends Sprite
{
//固定プロパティ
private var _world:b2World;
private var _catalystObj:B2DCatalyst;
//設定用プロパティ
private const WIDTH:Number = 465;
private const HEIGHT:Number = 465;
private var _fps:Number = 60;
private var _timeStep:Number = 1.0 / _fps;
private var _scale:Number = 100;
private var _gravity:Number = 10;
//各自追加プロパティ
private var cnt:Number = 0;
public function Test()
{
init();
}
private function init():void {
_catalystObj = new B2DCatalyst(true, _fps, _scale, _gravity);
this.addChild(_catalystObj);
_world = _catalystObj.world;
////////////////////////////////////////////////
//////////// 以下、設定用コード ////////////
////////////////////////////////////////////////
//床を作成
_catalystObj.makeB2BodyBox(465, 30, 0, 435, 0, 0, 0.5, 0.5);
////////////////////////////////////////////////
//////////// 以上、設定用コード ////////////
////////////////////////////////////////////////
_catalystObj.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
private function onEnterFrameHandler(e:Event):void
{
_world.Step(_timeStep, 10);
////////////////////////////////////////////////
//////////// 以下、描画更新用コード ////////////
////////////////////////////////////////////////
if (cnt == 30) {
create();
cnt = 0;
} else {
cnt++;
}
////////////////////////////////////////////////
//////////// 以上、描画更新用コード ////////////
////////////////////////////////////////////////
//画面外に行ったオブジェクトを削除する
var marginX:Number = 50;
var marginY:Number = 50;
for (var b:b2Body = _world.GetBodyList(); b; b = b.GetNext()) {
var xPos:Number = b.GetWorldCenter().x * _scale;
var yPos:Number = b.GetWorldCenter().x * _scale;
if (xPos > WIDTH + marginX || xPos < -marginX || yPos > HEIGHT + marginY || yPos < -marginY){
_world.DestroyBody(b);
}
}
}
private function create():void {
_catalystObj.makeB2BodyCircle(50, Math.random() * 465, 0, 1, 0.2, 0.5);
_catalystObj.makeB2BodyBox(50, 50, Math.random() * 465, 0, Math.random() * Math.PI * 2, 1, 0.2, 0.5);
}
}
}
//以下、媒介用クラス。なので、拡張する時以外、通常弄る必要なし・・・にしたい
//以下のURLをほぼ丸ごと。少しずつ拡張予定。
//http://hokori.net/2009/02/18/box2dflashas3_base/
import flash.display.Sprite;
import Box2D.Collision.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import Box2D.Collision.Shapes.*;
internal class B2DCatalyst extends Sprite
{
//Box2Dのバージョンは2.0.2
private var m_b2_world:b2World;
//縮尺 1mを何ピクセルで表すか
private var m_b2_physcale:Number = 10;
//演算制度 大きいと正確だけど、負荷が大きい
private var m_b2_iterations:int = 10;
// 演算をfpsに合わせる
private var m_b2_timeStep:Number = 24.0;
//constructor
public function B2DCatalyst(debugModeFlag:Boolean = false, fps:int = 24,
physcale:Number = 10, gravity:Number = 10):void{
//timestep設定
this.m_b2_timeStep = 1.0 / fps;
//スケール設定
this.m_b2_physcale = physcale;
//B2DBoxの世界生成
this.createB2World(gravity);
//debugMode
if (debugModeFlag) startDebugMode();
}
//Box2D世界作成
private function createB2World(gravity:Number):void {
// Creat world AABB
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-1000, -1000);
worldAABB.upperBound.Set(1000, 1000);
// Define the gravity vector
var vec_gravity:b2Vec2 = new b2Vec2(0.0, gravity);
// Allow bodies to sleep
var doSleep:Boolean = true;
// Construct a world object
this.m_b2_world = new b2World(worldAABB, vec_gravity, doSleep);
}
/**
* 長方形の物体作成
* @param int w (ピクセル 内部でB2DBox用に変換)
* @param int h (ピクセル 内部でB2DBox用に変換)
* @param Number x(ピクセル 内部でB2DBox用に変換)
* @param Number y(ピクセル 内部でB2DBox用に変換)
* @param Number angle 角度(360度 内部でラジアンに変換)
* @param density 密度 0にすると固定
* @param friction 摩擦 大きいと滑りにくい
* @param restitution 跳ね返り 大きいと、反発しやすい
* @param viewdata 表示用のSprite
* @param viewgroup 表示用のSpriteを入れるSprite
* @return b2Body
*/
public function makeB2BodyBox(w:int, h:int,
x:Number, y:Number, angle:Number,
density:Number,
friction:Number,
restitution:Number,
viewdata:Sprite = null,
viewgroup:Sprite = null) :b2Body {
var b2_boxdef:b2PolygonDef = this.createB2BoxDef(w, h, density,
friction, restitution);
var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, w, h, angle,
viewdata, viewgroup);
var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef);
b2_body.CreateShape(b2_boxdef);
b2_body.SetMassFromShapes();
return b2_body;
}
/**
* 円の物体作成
* @param diameter 直径(ピクセル 内部でメートルに変換)
* @param x (ピクセル 内部でメートルに変換)
* @param y(ピクセル 内部でメートルに変換)
* @param density 密度 0にすると固定 大きいと、ぶつかったとき強い
* @param friction 摩擦 大きいと滑りにくい
* @param restitution 跳ね返り 大きいと、反発しやすい
* @param viewdata 表示用のSprite
* @param viewgroup 表示用のSpriteを入れるSprite
* @return b2Body
*/
public function makeB2BodyCircle(diameter:int, x:Number, y:Number,
density:Number,
friction:Number,
restitution:Number,
viewdata:Sprite = null,
viewgroup:Sprite = null) :b2Body {
var b2_boxdef:b2CircleDef = this.createB2CircleDef(diameter,
density, friction, restitution);
var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, 0, 0, 0,
viewdata, viewgroup);
var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef);
b2_body.CreateShape(b2_boxdef);
b2_body.SetMassFromShapes();
return b2_body;
}
/**
* 長方形の性質設定(形状と素材)
* @param width (ピクセル 内部でメートルに変換)
* @param height (ピクセル 内部でメートルに変換)
* @param density
* @param friction
* @param restitution
* @return
*/
public function createB2BoxDef(width:int, height:int,
density:Number,
friction:Number,
restitution:Number):b2PolygonDef {
var boxdef:b2PolygonDef = new b2PolygonDef();
//B2DBox用単位・中心座標からの距離のサイズに変換して作成
boxdef.SetAsBox(width / 2 / this.m_b2_physcale,
height/ 2 / this.m_b2_physcale);
//密度 0だと動かない 大きいと、ぶつかったとき強い
boxdef.density = density;
//摩擦 大きいと、滑りにくい
boxdef.friction = friction;
//跳ね返り 大きいと、反発しやすい(ゴムっぽくなる)
//小さいと、粘土っぽくなる
boxdef.restitution = restitution;
return boxdef;
}
/**
* 円の性質設定(形状と素材)
* @param diameter (ピクセル 内部でメートルに変換)
* @param height (ピクセル 内部でメートルに変換)
* @param density
* @param friction
* @param restitution
* @return
*/
public function createB2CircleDef(diameter:int,
density:Number,
friction:Number,
restitution:Number):b2CircleDef {
var cdef:b2CircleDef = new b2CircleDef();
//メートル単位・中心座標からの距離のサイズに変換して作成
cdef.radius = diameter / 2 / this.m_b2_physcale; //半径
//密度 0だと動かない
cdef.density = density;
//摩擦 大きいと、滑りにくい
cdef.friction = friction;
//跳ね返り 大きいと、反発しやすい(ゴムっぽくなる)
//小さいと、粘土っぽくなる
cdef.restitution = restitution;
return cdef;
}
/**
* 配置設定
* @param x(ピクセル worldの中心から物体の中心の距離)
* @param y(ピクセル)
* @param angle 角度 (360度単位)
* @param viewdata 表示用Sprite
* @param viegroup 表示用Spriteを入れるSprite
* @return 2BodyDef
*/
public function createB2BodyDef(x:Number, y:Number, w:Number, h:Number,
angle:Number,viewdata:Sprite = null,viewgroup:Sprite = null):b2BodyDef {
var bodydef:b2BodyDef = new b2BodyDef();
//B2DBox用単位に変換して配置
bodydef.position.Set((x+w*.5) / this.m_b2_physcale, (y+h*.5) / this.m_b2_physcale);
bodydef.angle = (angle / 180) * Math.PI; //ラジアンに変換
//動かないときはスリープ→止まったらイベント受け付けなくなるので起こす
bodydef.allowSleep = true;
if(viewdata != null){
bodydef.userData = viewdata;
bodydef.userData.width = viewdata.width;
bodydef.userData.height = viewdata.height;
//表示用に追加
if(viewgroup != null){
viewgroup.addChild(bodydef.userData);
}
}
return bodydef;
}
/**
* 座標指定用のベクトル作成(単位をピクセルからメートルに変換)
* @param x
* @param y
* @return b2Vec2
*/
public function createB2Vec(x:Number, y:Number):b2Vec2 {
//単位をb2用に変換
var vec:b2Vec2 = new b2Vec2(x / this.m_b2_physcale,
y / this.m_b2_physcale);
return vec;
}
private function startDebugMode():void
{
//DebugDrawを有効にする
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.m_sprite = this;
debugDraw.m_drawScale = m_b2_physcale;
debugDraw.m_fillAlpha = .8;
debugDraw.m_lineThickness = 1;
debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
m_b2_world.SetDebugDraw(debugDraw);
}
//getter/setter
public function get world():b2World { return m_b2_world; }
public function set world(value:b2World):void
{
m_b2_world = value;
}
}