In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

距離ジョイントを繋げて離す

距離ジョイントを繋げて離す
クリックでジョイントが外れる
はずれた玉はクリックで飛び跳ねる
Get Adobe Flash player
by hokori 13 May 2009
/**
 * Copyright hokori ( http://wonderfl.net/user/hokori )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cko0
 */

//距離ジョイントを繋げて離す
//クリックでジョイントが外れる
//はずれた玉はクリックで飛び跳ねる
package
{
	import Box2D.Collision.b2Bound;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef
	import Box2D.Dynamics.Joints.b2Joint;
	import Box2D.Dynamics.Joints.b2DistanceJoint;
	import Box2D.Dynamics.Joints.b2DistanceJointDef;
	import Box2D.Dynamics.Joints.b2JointEdge;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Collision.b2AABB;
	import Box2D.Collision.Shapes.b2Shape;
	import Box2D.Collision.Shapes.b2CircleDef;
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Common.Math.b2Vec2;

	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.display.Sprite;
	import flash.display.Graphics;


    public class Sample05 extends Sprite
    {
        private var m_disp_grp:Sprite;
        private var m_color:int;
        
        public function Sample05() 
        {    
            //Box2D初期設定
            this.B2Base();
            
            m_disp_grp = new Sprite();
            this.addChild(m_disp_grp);
            
            m_color = Math.random() * 0x00FFFF;
            
            this.createNoren(50, 0, 1, 15);
            this.createNoren(250, 0, 1, 10);
            this.createNoren(450, 0, 1, 15);
			
			this.createWalls();

            this.addEventListener(Event.ENTER_FRAME, update, false, 0, true);
			this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 0, true);
		}
	
		//壁と棚作成
		private function createWalls():void {
			
			//壁作成
			this.makeB2BodyBox(500, 10, 250, 0, 0, 0, 0.5, 0.5);
			this.makeB2BodyBox(500, 10, 250, 500, 0, 0, 0.5, 0.5);
			
			this.makeB2BodyBox(10, 500, 0, 250, 0, 0, 0.5, 0.5);
			this.makeB2BodyBox(10, 500, 500, 250, 0, 0, 0.5, 0.5);
			
			//棚作成
			var self:Sample05 = this;
			
			var make_tana:Function = function(x:int, y:int, w:int, h:int):void {
									var disp:Sprite = new Sprite();
									disp.graphics.beginFill(self.m_color, 0.5);
									disp.graphics.drawRect( - w / 2, - h / 2, w, h);
									disp.graphics.endFill();
									self.makeB2BodyBox(w, h, x, y, 0, 0 , 0.5, 0.5, disp, self.m_disp_grp);				
									}
			make_tana(250, 300, 200, 10);
			make_tana(250, 400, 360, 10);
		}
		
        //距離ジョイントで繋げたものを揺らす
        private function createNoren(x:int, y:int, set_to:int, num: int):void {

            var bodies:Array = new Array();

            var density:int = 0;
            for (var i:int = 0; i < num; i++) {
                
				var size:int = Math.random() * 10 + 10;
				var disp:Sprite = new Sprite();
				disp.graphics.beginFill(m_color, 1);
				disp.graphics.drawCircle(0, 0, size);
				disp.buttonMode = true;
				disp.addEventListener(MouseEvent.MOUSE_OVER,
									  function(e:MouseEvent):void {
										  e.target.alpha = 0.5;
									  });
									  
				disp.addEventListener(MouseEvent.MOUSE_OUT,
									  function(e:MouseEvent):void {
										  e.target.alpha = 1.0;
									  });			  

                var body:b2Body = this.makeB2BodyCircle(size * 2, x, y, density, 0.5, 0.5, disp , m_disp_grp);
				bodies[i] = body;
                
                y += (size + 15) * set_to;
                density = 1;
            }
            
            //距離ジョイントで繋ぐ
            for (var j:int = 0; j < num - 1; j++){
                var d_joint_def:b2DistanceJointDef = new b2DistanceJointDef();
                d_joint_def.collideConnected = true;
                d_joint_def.Initialize(bodies[j], bodies[j + 1], bodies[j].GetPosition(), bodies[j + 1].GetPosition());
                this.m_b2_world.CreateJoint(d_joint_def);
            }
            
            //ちょっと力を加えて動かす
            bodies[num -1].ApplyForce(new b2Vec2(1000, 0), bodies[num - 1].GetPosition());
        }
		
		private function onMouseDown(e:MouseEvent):void {
			
			var m_x:Number = this.mouseX / this.m_b2_physcale;
			var m_y:Number = this.mouseY / this.m_b2_physcale;
			
			//マウスの下の物体取得
			var body:b2Body = this.GetBodyAtMouse(m_x, m_y);
			if (body is b2Body) {
				if(body.GetJointList() is b2JointEdge){
					//ジョイント繋がってたら、、ジョイントをはずすよ
					if(body.GetJointList().joint is b2Joint){
						this.m_b2_world.DestroyJoint(body.GetJointList().joint);
					}
				}
				else {
					//ジョイント繋がってなかったら、上に力加える
					body.ApplyForce(new b2Vec2(0, -5000), body.GetPosition());
				}
			}
		}
		
		//マウスの下の物体取得
		//Box2DのTestBedのコピペ
		private var mousePVec:b2Vec2 = new b2Vec2();
		public function GetBodyAtMouse(mouseXWorldPhys:Number, mouseYWorldPhys:Number, 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_b2_world.Query(aabb, shapes, k_maxCount);
			var body:b2Body = null;
			for (var i:int = 0; i < count; ++i)
			{
				if (shapes[i].GetBody().IsStatic() == false || includeStatic)
				{
					var tShape:b2Shape = shapes[i] as b2Shape;
					var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
					if (inside)
					{
						body = tShape.GetBody();
						break;
					}
				}
			}
			return body;
		}

        private function update(e:Event):void{

            var self:Sample05 = this;
            
            this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations);

            var disp_gra:Graphics = this.m_disp_grp.graphics;
            disp_gra.clear();
            disp_gra.lineStyle(1, m_color);
            
            for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){

                if (bb.m_userData is Sprite){
                    bb.m_userData.x = bb.GetPosition().x * m_b2_physcale;
                    bb.m_userData.y = bb.GetPosition().y * m_b2_physcale;
                    bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
                }
                
                //ジョイントの線
                if (bb.m_jointList is b2JointEdge) {
                    for (var joint:b2Joint = bb.m_jointList.joint; joint; joint=joint.m_next){
                        var anc1:b2Vec2 = joint.GetAnchor1();
                        var anc2:b2Vec2 = joint.GetAnchor2();
                        disp_gra.moveTo(anc1.x * this.m_b2_physcale, anc1.y * this.m_b2_physcale);
                        disp_gra.lineTo(anc2.x * this.m_b2_physcale, anc2.y * this.m_b2_physcale);
                    }
                }
            }
        }
        
        
        //-----------------------------------------------------------------------------------
        //Box2D用まとめ
        //wonderfl上でクラスを複数置く方法がわからない...。
        //-----------------------------------------------------------------------------------
        protected var m_b2_world:b2World;
        protected var m_b2_physcale:Number = 10;
        protected var m_b2_iterations:int = 10; 
        protected var m_b2_timeStep:Number = 24.0; 

        public function B2Base(fps:int = 24, physcale:Number = 10, gravity:Number = 10):void{
            
            this.m_b2_timeStep = 1.0 / fps;
            this.m_b2_physcale = physcale;
            this.createB2World(gravity);            
        }

        private function createB2World(gravity:Number):void {
            
            var worldAABB:b2AABB = new b2AABB();
            worldAABB.lowerBound.Set(-1000, -1000);
            worldAABB.upperBound.Set(1000, 1000);
            
            var vec_gravity:b2Vec2 = new b2Vec2(0.0, 10.0);
            
            var doSleep:Boolean = true;
            
            this.m_b2_world = new b2World(worldAABB, vec_gravity, doSleep);
        }

        protected 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, 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;
        }    

        protected function makeB2BodyCircle(radius:int, x:Number, y:Number, 
                                      density:Number, friction:Number, restitution:Number,
                                      viewdata:Sprite = null, viewgroup:Sprite = null) :b2Body {
            
            var b2_boxdef:b2CircleDef = this.createB2CircleDef(radius, density, friction, restitution);
            var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, 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;
        }

        private function createB2BoxDef(width:int, height:int, 
                                        density:Number, friction:Number, restitution:Number):b2PolygonDef {
            
            var boxdef:b2PolygonDef = new b2PolygonDef();

            boxdef.SetAsBox(width / 2 / this.m_b2_physcale, height/ 2 / this.m_b2_physcale);
            boxdef.density = density; 
            boxdef.friction = friction;
            boxdef.restitution = restitution;
            
            return boxdef;
        }
    
        private function createB2CircleDef(diameter:int, density:Number, friction:Number, restitution:Number):b2CircleDef {
            
            var cdef:b2CircleDef = new b2CircleDef();
            
            cdef.radius = diameter / 2 / this.m_b2_physcale;
            cdef.density = density;
            cdef.friction = friction; 
            cdef.restitution = restitution;
            
            return cdef;
        }

        private function createB2BodyDef(x:Number, y:Number, angle:Number, viewdata:Sprite = null, viewgroup:Sprite = null):b2BodyDef {
            
            var bodydef:b2BodyDef = new b2BodyDef();

            bodydef.position.Set(x / this.m_b2_physcale, y / 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;            
        }

        protected function createB2Vec(x:Number, y:Number):b2Vec2 {
            
            var vec:b2Vec2 = new b2Vec2(x / this.m_b2_physcale, y / this.m_b2_physcale); 
            return vec;
        }
    }
}