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

Box2D試作:シロクロ フィジックス

シロクロシリーズをBox2Dオンリーで実現するためのテスト。
Get Adobe Flash player
by o_healer 15 Feb 2011
    Embed
/**
 * 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;
                }
            }
        }
    }
}