Box2Dでサンプルアプリを作ってみました。
Box2Dでサンプルアプリを作ってみました。
こんな感じ。
http://moeten.info/flex/20080926_moetenBox2DTest/bin-release/
まだ、使ってない機能がたくさんあるので勉強です。
ソースは右クリックかこちら↓
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundAlpha="0.5" backgroundColor="0xffffff" backgroundGradientAlphas="[1,1]" backgroundGradientColors="[0xffffff,0x000000]" horizontalScrollPolicy="off" verticalScrollPolicy="off" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ [Bindable]private var server:String = "moeten.info"; [Bindable]private var site:String = "maidcafe"; private function init():void{ if( this.parameters.site ) site = this.parameters.site; if( this.parameters.server )server = this.parameters.server; hts.send({"tid":13,"cid":1}); htsTid.send({"tid":"list"}); htsCid.send({"cid":"list", "tid":13 }); pBar.visible = true; } private function onHtsResult():void{ initBox2D(); } private function onTidChange():void{ htsCid.send({ "tid":tidBox.selectedItem.tid, "cid":"list" }); hts.send({"tid":tidBox.selectedItem.tid}); pBar.visible = true; } private function onCidChange():void{ pBar.visible = true; hts.send({ "tid":tidBox.selectedItem.tid, "cid":cidBox.selectedItem.cid }); } //HTTP結果イベント private function onTidResult():void{ showCidBox.play([tidBox]); pBar.visible = false; var len:int = htsTid.lastResult.item.length(); for( var i:int = 0 ; i < len ; i ++ ){ // trace( htsTid.lastResult.item[i].tid ); if( htsTid.lastResult.item[i].tid == 13 ){ tidBox.selectedIndex = i; return; } } return; } private function onCidResult():void{ showCidBox.play([cidBox]); pBar.visible = false; } private function onResult():void{ initBox2D(); pBar.visible = false; } //フルスクリーン private function setFullscreen():void{ switch(stage.displayState) { case "normal": stage.displayState = StageDisplayState.FULL_SCREEN; break; case "fullScreen": default: stage.displayState = "normal"; break; } } /* ****************************** Box2D ****************************** */ import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.*; import Box2D.Dynamics.Joints.*; import General.*; private function initBox2D():void{ //Box2D初期化 setWorld(); //自分のメイン部分 //オブジェクト作成 setAllCircle(); //壁作成 setAllWall(); //描画+デバッグ setSprite(); // setDebug(); this.addEventListener(Event.ENTER_FRAME , EnterFrame ); } private var m_world:b2World; private var m_iterations:int = 10; private var m_timeStep:Number = 1.0/14.0; public var m_physScale:Number = 30; private function setWorld():void{ m_sprite = new Sprite(); var len:Number = myUI.numChildren; for( var i:int = 0 ; i < len ; i ++ ){ myUI.removeChildAt(i); } //ワールドを定義する //--ワールドの広さ。この範囲の外に出たオブジェは物理演算されなくなる-- var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-100.0, -100.0); worldAABB.upperBound.Set( 100.0, 100.0); //-- 重力の強さ、方向の設定 -- var gravity:b2Vec2 = new b2Vec2(0.0, 10.0); //-- 一定時間動きがない場合スリープにするかどうか -- var doSleep:Boolean = true; //-- ワールド定義 -- m_world = new b2World(worldAABB, gravity, doSleep); } private var onMouse:Boolean = false; private function setGround():void{ //-------------------------------------------- // 地面を作る //-------------------------------------------- var bodyDef:b2BodyDef; bodyDef = new b2BodyDef(); //Bodyの定義 bodyDef.position.Set(0, this.height/m_physScale); //位置(座標) var boxDef:b2PolygonDef; boxDef = new b2PolygonDef(); //Polygonの定義 boxDef.SetAsBox(this.width/m_physScale, 3); //形状 boxDef.friction = 0.3; //摩擦力 boxDef.density = 0; //静的な物体を作る場合は密度を0に var body:b2Body; body = m_world.CreateBody(bodyDef); body.CreateShape(boxDef); //boxDefをBodyに設定する(無いと貫通する) body.SetMassFromShapes(); //形状と密度から物体の質量を定義 } private function setAllWall():void{ //-------------------------------------------- // 壁を作る //-------------------------------------------- setWall( 0 , this.height - 50, this.width ,40); setWall(10,10,100,this.height-110); setWall(this.width-10,10,100,this.height-110); setWall( 410, 180 ,10 ,20); setWall( 490, 180 ,10 ,20); setWall( 450, 220 ,50 ,10); } private function setWall( x:Number , y:Number , w:Number , h:Number ):void{ //-------------------------------------------- // 壁を作る //-------------------------------------------- var bodyDef:b2BodyDef; bodyDef = new b2BodyDef(); //Bodyの定義 bodyDef.position.Set(x/m_physScale, y/m_physScale); //位置(座標) var boxDef:b2PolygonDef; boxDef = new b2PolygonDef(); //Polygonの定義 boxDef.SetAsBox( w/m_physScale, h/m_physScale); //形状 boxDef.friction = 0.3; //摩擦力 boxDef.density = 0; //静的な物体を作る場合は密度を0に var body:b2Body; body = m_world.CreateBody(bodyDef); body.CreateShape(boxDef); //boxDefをBodyに設定する(無いと貫通する) body.SetMassFromShapes(); //形状と密度から物体の質量を定義 } private function setAllCircle():void{ //-------------------------------------------- // 円を作る //-------------------------------------------- var len:int = hts.lastResult.item.length(); for( var i:int = 0 ; i < len ; i ++ ){ setCircle( i , hts.lastResult.item[i].shopname , hts.lastResult.item[i].image.image1 ); } } private function setCircle( i:int , shopname:String , fname:String):void{ //-------------------------------------------- // 円を作る //-------------------------------------------- var sp:Sprite = new Sprite(); var dsf:DropShadowFilter = new DropShadowFilter(0,0); var gf:GlowFilter = new GlowFilter( 0xffffff,1,6,6,10); // sp.filters = [gf,dsf]; // var r:int = int( Math.random() * 20 ) + 10; var r:int = 30; var myMask:Sprite = new Sprite(); myMask.graphics.beginFill(0xeeeeee,1); myMask.graphics.drawCircle(0,0,r); myMask.graphics.endFill(); sp.name = shopname; sp.addChild( myMask ); var loader:Loader = new Loader(); loader.load( new URLRequest( fname ) ); loader.contentLoaderInfo.addEventListener(Event.COMPLETE , function ():void{ var bd:BitmapData = new BitmapData( 2*r , 2*r ); var mat:Matrix = new Matrix(); mat.scale(0.5,0.5); bd.draw( loader.content , mat ); var bm:Bitmap = new Bitmap( bd ); bm.cacheAsBitmap = true; bm.x = -r; bm.y = -r; sp.addChild( bm ); bm.mask = myMask; }); //動く円形オブジェクトを作成 var circleDef:b2CircleDef=new b2CircleDef(); // 大きさ、密度、摩擦力、反発力などを設定。 circleDef.radius = r / m_physScale; circleDef.density = 1.0; circleDef.friction = 1.0 ; circleDef.restitution = 0.2 ; // Bodyを入れる箱を用意。位置はここで指定 var circleBD:b2BodyDef=new b2BodyDef(); circleBD.position.Set( Math.random()*this.width/m_physScale , Math.random()*200 /this.height/ m_physScale ); // 円を保存 circleBD.userData = sp; circleBD.userData.width = 2*r; circleBD.userData.height = 2*r; circleBD.userData.name = "" + i + "_" + shopname; m_sprite.addChild(circleBD.userData); // Bodyを生成して、Box2Dのworldに落とし込む var circle:b2Body=m_world.CreateBody( circleBD ); circle.CreateShape( circleDef ); circle.SetMassFromShapes(); circleArr[i] = circleBD; sp.addEventListener(MouseEvent.ROLL_OVER , function( e:Event ):void{ onMouse = true; myName.text = e.target.name myName.visible = true; }); sp.addEventListener(MouseEvent.ROLL_OUT , function( e:Event ):void{ onMouse = false; myName.visible = false; }); sp.doubleClickEnabled = true; sp.addEventListener(MouseEvent.DOUBLE_CLICK , function( e:Event ):void{ dg.dataProvider = hts.lastResult.item[i]; dg.visible = true; }); sp.addEventListener(MouseEvent.MOUSE_MOVE , function( e:Event ):void{ myName.visible = true; if( onMouse ){ myName.x = (myUI.mouseX) - 20; myName.y = (myUI.mouseY) - 50; } }); } private var circleArr:Array = new Array(); //-------------------------------------------- // EnterFrameで物理演算を処理する //-------------------------------------------- private function EnterFrame(event:Event):void{ UpdateMouseWorld(); MouseDrag(); m_world.Step(m_timeStep, m_iterations); //物理演算の更新 // 実際の描写作業 for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) { if(bb.m_userData is Sprite) { bb.m_userData.x = (bb.GetPosition().x)* m_physScale; bb.m_userData.y = (bb.GetPosition().y)* m_physScale; bb.m_userData.rotation = bb.GetAngle()*(180/Math.PI); if( Math.abs(bb.m_userData.x - 450) < 3 && Math.abs(bb.m_userData.y - 180 ) < 3 ){ if( nowname != bb.m_userData.name ){ var i:int = int( String(bb.m_userData.name).split( "_")[0]); nowname = bb.m_userData.name; dg.dataProvider = hts.lastResult.item[i]; dg.visible = true; }else{ } } } } } private var nowname:String = null; private var m_sprite:Sprite = new Sprite(); //グラフィック表示用のSpriteを作成 private function setSprite():void{ //-------------------------------------------- // ラインで表示する(デバッグ描写の使用) //-------------------------------------------- var dbgDraw:b2DebugDraw = new b2DebugDraw(); //b2DebugDrawクラスの定義 dbgDraw.m_sprite = m_sprite; //デバッグを描くSpriteを設定 dbgDraw.m_drawScale = 30.0; //画面に描く倍率 dbgDraw.m_fillAlpha = 0.3; // 塗りの透明度 dbgDraw.m_lineThickness = 1.0; // ラインの太さ dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit; // 物体、ジョイントを表示するかどうか m_world.SetDebugDraw(dbgDraw); myUI.addChild(m_sprite); //表示用のSpriteをステージの表示リストに追加 m_input = new InputFlex(m_sprite); // マウス状態を取得するクラス } //-------------マウス操作。以下はTestクラスから引用--------------------- private var m_input:InputFlex; private var mousePVec:b2Vec2 = new b2Vec2(); private var mouseXWorldPhys:Number; // ワールド内でのマウス座標 private var mouseYWorldPhys:Number; // ワールド内でのマウス座標 private var mouseXWorld:Number; //m_sprite内でのマウス座標 private var mouseYWorld:Number; //m_sprite内でのマウス座標 private var m_mouseJoint:b2MouseJoint; //====================== // Update mouseWorld //====================== private function UpdateMouseWorld():void{ mouseXWorldPhys = (InputFlex.mouseX)/m_physScale; mouseYWorldPhys = (InputFlex.mouseY)/m_physScale; mouseXWorld = (InputFlex.mouseX); mouseYWorld = (InputFlex.mouseY); // trace(Input.mouseX , Input.mouseY) } //====================== // Mouse Drag //====================== private function MouseDrag():void{ //trace(Input) // mouse press if (InputFlex.mouseDown && !m_mouseJoint){ var body:b2Body = GetBodyAtMouse(); if (body) { var md:b2MouseJointDef = new b2MouseJointDef(); md.body1 = m_world.m_groundBody; md.body2 = body; md.target.Set(mouseXWorldPhys, mouseYWorldPhys); md.maxForce = 300.0 * body.m_mass; md.timeStep = m_timeStep; m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint; body.WakeUp(); } } // mouse release if (!InputFlex.mouseDown){ if (m_mouseJoint) { m_world.DestroyJoint(m_mouseJoint); m_mouseJoint = null; } } // mouse move if (m_mouseJoint) { var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys); m_mouseJoint.SetTarget(p2); } } //====================== // GetBodyAtMouse //====================== private function GetBodyAtMouse(includeStatic:Boolean=false):b2Body{ // Make a small box. mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001); aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001); // Query the world for overlapping shapes. var k_maxCount:int = 10; var shapes:Array = new Array(); var count:int = m_world.Query(aabb, shapes, k_maxCount); var body:b2Body = null; for (var i:int = 0; i < count; ++i) { if (shapes[i].m_body.IsStatic() == false || includeStatic) { var tShape:b2Shape = shapes[i] as b2Shape; var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), mousePVec); if (inside) { body = tShape.m_body; break; } } } return body; } // デバッグ用の関数 public function setDebug():void{ var dbgDraw:b2DebugDraw = new b2DebugDraw(); var dbgSprite:Sprite = new Sprite(); myUI.addChild(dbgSprite); dbgDraw.m_sprite=dbgSprite; dbgDraw.m_drawScale=m_physScale; dbgDraw.m_fillAlpha=0.5; dbgDraw.m_lineThickness=0; dbgDraw.m_drawFlags=0xFFFFFFFF; m_world.SetDebugDraw(dbgDraw); } ]]> </mx:Script> <mx:HTTPService id="hts" url="{'http://'+server+'/'+site+'/?m=api&type=shop'}" resultFormat="e4x" result="onResult()"/> <mx:HTTPService id="htsTid" url="{'http://'+server+'/'+site+'/?m=api&type=shop'}" resultFormat="e4x" result="onTidResult()"/> <mx:HTTPService id="htsCid" url="{'http://'+server+'/'+site+'/?m=api&type=shop'}" resultFormat="e4x" result="onCidResult()"/> <mx:Sequence id="showCidBox"> <mx:WipeRight/> <mx:Glow alphaFrom="1" alphaTo="0" blurXFrom="20" blurYFrom="20" blurXTo="0" blurYTo="0" color="0xffffff"/> </mx:Sequence> <mx:UIComponent id="myUI" width="100%" height="100%"/> <mx:ProgressBar themeColor="#666666" indeterminate="true" id="pBar" label="" trackHeight="10" width="100%" visible="false"/> <mx:TextInput id="myName" cornerRadius="5" backgroundAlpha="0.8" backgroundColor="0x333333" borderColor="0x000000" borderStyle="solid" borderThickness="3" color="0xffffff" editable="false" visible="false" mouseEnabled="false"/> <mx:ComboBox id="tidBox" x="20" y="26" width="142" prompt="都道府県" rowCount="10" dataProvider="{htsTid.lastResult.item}" labelField="todouhuken" change="onTidChange()" /> <mx:ComboBox id="cidBox" x="170" y="26" width="150" prompt="カテゴリー" rowCount="10" dataProvider="{htsCid.lastResult.item}" labelField="category" change="onCidChange()" /> <mx:TileList id="dg" x="20" y="100" width="300" height="508" itemRenderer="shopDetail" visible="false" backgroundAlpha="0.8" cornerRadius="5" borderColor="0x333333" borderStyle="solid" borderThickness="3" showEffect="WipeUp" hideEffect="WipeUp" selectable="false"/> </mx:Application>