物理エンジンライブラリ Box2DFlashAS3 ジョイント3(滑車ジョイント・マウスジョイント)

滑車ジョイントとマウスジョイントについてのメモ。
サンプルコードでは、距離ジョイントも使ってます。

ついでに任意で物体に力を加える方法も。

滑車ジョイント(PulleyJoint)

  • 滑車の上に紐で繋がった物体をかけたようなジョイント。
  • 二つの滑車を軸に、紐の長さ分だけ物体が動く。
  • 紐の長さ、伸びやすさ(ゴムっぽくしたり)を指定できる。

使い方

  • 滑車の場所(b2Vec2)を左右指定。
  • 滑車に繋げる物体を指定(b2Body)。
  • ジョイントの性質(b2PulleyJointDef)を設定(長さ等)
  • ジョイントの初期化→ジョイント登録

マウスジョイント(MouseJoint)

  • マウスと物体を繋ぐジョイント。
  • マウス(座標)と他の物体を繋ぐだけ。
  • マウスを動かしたら付いてくる、というような動作は自力で実装。

使い方

  • マウス押した時に、マウス座標の下にある物体を取得(これは自力で作る)
  • マウス座標、取得した物体、引っ張る力など設定(b2MouseJointDef)
  • ジョイント作成(b2MouseJoint)
  • 一定時間毎(EnterFrameイベントなど)マウスドラッグ時のマウス座標を反映させる
  • マウス放したらジョイントを削除

物体に任意で力を加える

bb.ApplyForce(new b2Vec2(0, 200), bb.GetPosition());
(bbはb2Bodyオブジェクト。力を加える方向と、力を加える位置を指定する)

サンプルコード

実行結果(きのこの島)
きのこの島

※Box2Dのまとめたクラス(Box2DBase)を作って、基本クラスで使ってます。ソースは物理エンジンライブラリ Box2DFlashAS3(基本)にあります。

マウスジョイントの辺りは、Box2Dの付属コード、TestBedのTest.asのサンプルからほぼコピペです。

Actionscript:
  1. public class StudyB2Joint3 extends B2Base
  2. {
  3.     private var m_display_blocks:Sprite;  //表示用
  4.    
  5.     private var m_left_fook1:b2Body;
  6.     private var m_left_fook2:b2Body;
  7.     private var m_left_box1:b2Body;
  8.     private var m_left_box2:b2Body;  
  9.    
  10.     public function StudyB2Joint3() : void{
  11.        
  12.         super(24, 10, 10);
  13.        
  14.         //滑車ときのこ表示用
  15.         this.m_display_blocks = new Sprite();
  16.         this.addChild(this.m_display_blocks);
  17.        
  18.         //水面
  19.         var water:MovieClip = new water_mc;
  20.         water.y = 350;
  21.         this.addChild(water);
  22.        
  23.         //上下左右の壁作成
  24.         this.makeB2Walls();
  25.        
  26.         //島作成
  27.         this.makeShima();
  28.        
  29.         //滑車表示用のMC
  30.         var kassha_left_fook1:Sprite = new kinoko_fook_mc as Sprite;
  31.         var kassha_left_fook2:Sprite = new kinoko_fook_mc as Sprite;
  32.         var kassha_left_box1:Sprite = new board_100_mc as Sprite;
  33.         var kassha_left_box2:Sprite = new board_100_mc as Sprite;
  34.        
  35.         var kassha_right_fook1:Sprite = new kinoko_fook_mc as Sprite;
  36.         var kassha_right_fook2:Sprite = new kinoko_fook_mc as Sprite;
  37.         var kassha_right_box1:Sprite = new board_50_mc as Sprite;
  38.         var kassha_right_box2:Sprite = new board_50_mc as Sprite;
  39.        
  40.         //左の島の滑車
  41.         this.makeKassha(200, 175, 75, 175, 100, 10, 250,
  42.                         kassha_left_fook1, kassha_left_fook2,
  43.                         kassha_left_box1, kassha_left_box2);
  44.         //右の島の滑車
  45.         this.makeKassha(150, 450, 50, 150, 50, 10, 200,
  46.                         kassha_right_fook1, kassha_right_fook2,
  47.                         kassha_right_box1, kassha_right_box2);
  48.        
  49.         //きのこ
  50.         this.makeKinokos();
  51.        
  52.         //this.setDebugDraw();
  53.        
  54.         this.addEventListener(Event.ENTER_FRAME, this.update, false, 0, true);
  55.        
  56.         this.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown, false, 0, true);
  57.         this.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp, false, 0, true);
  58.     }
  59.    
  60.    
  61.     //上下左右の壁作成
  62.     private function makeB2Walls():void {
  63.  
  64.         this.makeB2BodyBox(700, 10, 300, -50, 0, 0, 0.5, 0.5)//上
  65.         this.makeB2BodyBox(700, 10, 300, 550, 0, 0, 0.5, 0.5)//下
  66.         this.makeB2BodyBox(10, 600, -50, 250, 0, 0, 0.5, 0.5)//左
  67.         this.makeB2BodyBox(10, 600, 650, 250, 0, 0, 0.5, 0.5)//右
  68.     }      
  69.  
  70.     //島作成
  71.     private function makeShima():void {
  72.        
  73.         this.makeB2BodyBox(100, 350, 175, 425, 0, 0, 0.5, 0.5);
  74.         this.makeB2BodyBox(100, 400, 450, 400, 0, 0, 0.5, 0.5);
  75.     }
  76.    
  77.     //滑車作成
  78.     private function makeKassha(pulley_w:int, pulley_x:int, pulley_y:int,
  79.                                  fook_y:int,
  80.                                  box_w:int, box_h:int, box_y:int,
  81.                                  disp_fook1:Sprite = null, disp_fook2:Sprite = null,
  82.                                  disp_box1:Sprite = null, disp_box2:Sprite = null):void {
  83.        
  84.         var x1:Number = pulley_x - (pulley_w / 2);
  85.         var x2:Number = pulley_x + (pulley_w / 2)
  86.        
  87.         //フックに繋がる箱
  88.         var box1:b2Body = this.makeB2BodyBox(box_w, box_h, x1, box_y, 0, 1, 0.5, 0.5, disp_box1, this.m_display_blocks);
  89.         var box2:b2Body = this.makeB2BodyBox(box_w, box_h, x2, box_y, 0, 1, 0.5, 0.5, disp_box2, this.m_display_blocks);
  90.        
  91.         //フック
  92.         var fook1:b2Body = this.makeB2BodyBox(10, 10, x1, fook_y, 0, 1, 0.5, 0.5, disp_fook1, this.m_display_blocks);
  93.         var fook2:b2Body = this.makeB2BodyBox(10, 10, x2, fook_y, 0, 1, 0.5, 0.5, disp_fook2, this.m_display_blocks);
  94.        
  95.         //滑車
  96.         var ga1:b2Vec2 = this.createB2Vec(x1, pulley_y);
  97.         var ga2:b2Vec2 = this.createB2Vec(x2, pulley_y);
  98.        
  99.         //滑車ジョイント作成
  100.         var pj_def:b2PulleyJointDef = new b2PulleyJointDef;
  101.         pj_def.Initialize(fook1, fook2, ga1, ga2, fook1.GetPosition(), fook2.GetPosition(), 1);
  102.        
  103.         this.m_b2_world.CreateJoint(pj_def);
  104.        
  105.         //フックは他のものと衝突しないようにする
  106.         fook1.GetShapeList().m_filter.maskBits = 0;
  107.         fook2.GetShapeList().m_filter.maskBits = 0;
  108.        
  109.         //距離ジョイントで左の箱とフックつなぐ
  110.         var box1_anc_L:b2Vec2 = this.createB2Vec(x1 - (box_w / 2) + 5, box_y);
  111.         var box1_anc_R:b2Vec2 = this.createB2Vec(x1 + (box_w / 2) - 5, box_y);
  112.        
  113.         var dj_def1_L:b2DistanceJointDef = new b2DistanceJointDef;
  114.         dj_def1_L.Initialize(fook1, box1, fook1.GetPosition(), box1_anc_L);
  115.        
  116.         this.m_b2_world.CreateJoint(dj_def1_L);
  117.        
  118.         var dj_def1_R:b2DistanceJointDef = new b2DistanceJointDef;
  119.         dj_def1_R.Initialize(fook1, box1, fook1.GetPosition(), box1_anc_R);
  120.        
  121.         this.m_b2_world.CreateJoint(dj_def1_R);
  122.        
  123.         //距離ジョイントで右の箱とフックつなぐ           
  124.         var box2_anc_L:b2Vec2 = this.createB2Vec(x2 - (box_w / 2) + 5, box_y);
  125.         var box2_anc_R:b2Vec2 = this.createB2Vec(x2 + (box_w / 2) - 5, box_y);
  126.        
  127.         var dj_def2_L:b2DistanceJointDef = new b2DistanceJointDef;
  128.         dj_def2_L.Initialize(fook2, box2, fook2.GetPosition(), box2_anc_L);
  129.        
  130.         this.m_b2_world.CreateJoint(dj_def2_L);
  131.        
  132.         var dj_def2_R:b2DistanceJointDef = new b2DistanceJointDef;
  133.         dj_def2_R.Initialize(fook2, box2, fook2.GetPosition(), box2_anc_R);
  134.        
  135.         this.m_b2_world.CreateJoint(dj_def2_R)
  136.     }
  137.    
  138.    
  139.     //きのこを降らせる
  140.     private function makeKinokos():void {
  141.        
  142.         //滑車の上に
  143.         this.makeKinoko(75, 225);
  144.         this.makeKinoko(257, 225);
  145.        
  146.         this.makeKinoko(375, 175);
  147.         this.makeKinoko(525, 175);
  148.        
  149.         //島の上に
  150.         this.makeKinoko(150, 0);
  151.         this.makeKinoko(200, 0);
  152.  
  153.         this.makeKinoko(425, 0);
  154.         this.makeKinoko(475, 0);
  155.     }
  156.    
  157.     //きのこ作成
  158.     private function makeKinoko(x:Number, y:Number):void {
  159.        
  160.         var kinoko:Sprite;
  161.         var land = Math.random();
  162.        
  163.         if (land>= 0.6) {
  164.             //普通のきのこ
  165.             kinoko = new kinoko_S1_MC as Sprite;
  166.         }
  167.         else if(land>= 0.3){
  168.             //怪しいきのこ
  169.             kinoko = new kinoko_S2_MC as Sprite;
  170.         }
  171.         else {
  172.             //しめじ
  173.             kinoko = new kinoko_S3_MC as Sprite;
  174.         }   
  175.        
  176.         this.makeB2BodyCircle(30, x, y, 1.0, 0.5, 0.5, kinoko, this.m_display_blocks);
  177.     }
  178.    
  179.    
  180.     //演算
  181.     private function update(e:Event):void{
  182.  
  183.         //B2Boxの時間進める
  184.         this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations);
  185.        
  186.         //マウス座標設定
  187.         this.updateMouseWorld();
  188.        
  189.         //マウスドラッグ時の設定
  190.         this.mouseDrag();
  191.        
  192.        
  193.         //滑車とフック・箱の間の線を引く
  194.         var self:StudyB2Joint3 = this;
  195.         //Body位置から描画位置移動する関数
  196.         var moveTo_Pos:Function = function(graphics:Graphics, anchor:b2Vec2):void {
  197.            
  198.             var x:Number = anchor.x * self.m_b2_physcale;
  199.             var y:Number = anchor.y * self.m_b2_physcale;
  200.        
  201.             graphics.moveTo(x, y);
  202.         }
  203.        
  204.         //Body位置へ線を引く関数
  205.         var lineTo_Pos:Function = function(graphics:Graphics, anchor:b2Vec2):void {
  206.            
  207.             var x:Number = anchor.x * self.m_b2_physcale;
  208.             var y:Number = anchor.y * self.m_b2_physcale;
  209.  
  210.             graphics.lineTo(x, y);
  211.         }   
  212.        
  213.         //線表示用ディスプレイオブジェクト
  214.         var disp_gra:Graphics = this.m_display_blocks.graphics;
  215.         disp_gra.clear();
  216.         disp_gra.lineStyle(1, 0x9FD06F);
  217.        
  218.         //worldに登録してあるBodyの動きを描画する
  219.         for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){
  220.             if (bb.IsDynamic()) {
  221.                
  222.                 //Bodyの動きにあわせて中のSpriteを動かす
  223.                 if (bb.m_userData is Sprite){
  224.                     //メートルからピクセル単位に変換
  225.                     bb.m_userData.x = bb.GetPosition().x * m_b2_physcale;
  226.                     bb.m_userData.y = bb.GetPosition().y * m_b2_physcale;
  227.                     bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
  228.                 }
  229.                
  230.                 //ジョイントを持ってるもののみ、線を描画
  231.                 if (bb.m_jointList is b2JointEdge) {
  232.                     for (var joint:b2Joint = bb.m_jointList.joint; joint; joint=joint.m_next){
  233.                         //ジョイントのタイプで分岐)
  234.                         if (joint.m_type == b2Joint.e_pulleyJoint) {
  235.                             //滑車ジョイントの場合(滑車とフックを線で繋ぐ)
  236.                             var joint_p:b2PulleyJoint = joint as b2PulleyJoint;
  237.                             moveTo_Pos(disp_gra, joint_p.GetGroundAnchor1());
  238.                             lineTo_Pos(disp_gra, joint_p.GetAnchor1());
  239.                             moveTo_Pos(disp_gra, joint_p.GetGroundAnchor2());
  240.                             lineTo_Pos(disp_gra, joint_p.GetAnchor2());
  241.                         }
  242.                         else {
  243.                             //その他のジョイント(アンカー同士を線で繋ぐ)
  244.                             //ここでは距離ジョイントとマウスジョイント
  245.                             moveTo_Pos(disp_gra, joint.GetAnchor1());
  246.                             lineTo_Pos(disp_gra, joint.GetAnchor2());
  247.                         }
  248.                     }
  249.                 }
  250.                
  251.                 //水面に浮かぶような感じを出してみる(物体に任意で力を加える)
  252.                 var bb_y:Number = bb.GetPosition().y * m_b2_physcale;
  253.                 if (bb_y> 350) {               
  254.                     //水中は上方向に力を加える
  255.                     var force:b2Vec2;
  256.                     if (bb_y> 500) {
  257.                         //深いところは多めに力を加える
  258.                         force = new b2Vec2(0, -200);
  259.                     }
  260.                     else {
  261.                         force = new b2Vec2(0, -100);
  262.                     }
  263.                     bb.ApplyForce(force, bb.GetPosition());
  264.                 }
  265.                 else if(bb_y <= 350 && bb_y> 250){
  266.                     if (bb.GetLinearVelocity().y <0) {
  267.                         //水面近くは下方向に力を加える(上方向に向かってる場合のみ)
  268.                         bb.ApplyForce(new b2Vec2(0, 200), bb.GetPosition());
  269.                     }
  270.                 }
  271.             }
  272.         }
  273.     }
  274.    
  275.    
  276.     //マウスジョイント設定    ---------------------------------------------------------------------
  277.     //Box2D付属のGeneralのInputをほぼこコピペ
  278.    
  279.     // world mouse position
  280.     private var m_mouseJoint:b2MouseJoint;  //マウスジョイント
  281.    
  282.     private var m_mouseXWorldPhys:Number//メートル単位のマウス座標
  283.     private var m_mouseYWorldPhys:Number;
  284.  
  285.     private var m_mouse_dowm:Boolean = false//マウスボタン押されてるか
  286.    
  287.     private function onMouseDown(e:Event):void {
  288.         this.m_mouse_dowm = true;
  289.     }
  290.    
  291.     private function onMouseUp(e:Event):void {
  292.         this.m_mouse_dowm = false;
  293.     }
  294.    
  295.     //マウス座標取得
  296.     public function updateMouseWorld():void{
  297.         //メートル単位のマウス座標に変換
  298.         m_mouseXWorldPhys = this.mouseX / this.m_b2_physcale;
  299.         m_mouseYWorldPhys = this.mouseY / this.m_b2_physcale;
  300.     }
  301.    
  302.     //マウスドラッグ時
  303.     public function mouseDrag():void{
  304.        
  305.         //マウスボタン押した(ジョイントまだ)
  306.         if (this.m_mouse_dowm && !this.m_mouseJoint){
  307.            
  308.             var body:b2Body = GetBodyAtMouse()//マウスの下の物体取得
  309.  
  310.             if (body)
  311.             {
  312.                 var md:b2MouseJointDef = new b2MouseJointDef();
  313.                 md.body1 = this.m_b2_world.GetGroundBody();
  314.                 md.body2 = body;
  315.                 md.target.Set(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  316.                 md.maxForce = 300000.0 * body.GetMass();
  317.                 md.timeStep = this.m_b2_timeStep;
  318.                 m_mouseJoint = this.m_b2_world.CreateJoint(md) as b2MouseJoint;
  319.                 body.WakeUp();
  320.             }
  321.         }
  322.        
  323.        
  324.         //マウスボタン離した
  325.         if (!this.m_mouse_dowm){
  326.             if (this.m_mouseJoint)
  327.             {
  328.                 this.m_b2_world.DestroyJoint(m_mouseJoint);
  329.                 m_mouseJoint = null;
  330.             }
  331.         }
  332.        
  333.        
  334.         //マウス押されてる状態(ジョイントされてる)
  335.         if (this.m_mouse_dowm && this.m_mouseJoint)
  336.         {
  337.             var p2:b2Vec2 = new b2Vec2(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  338.             m_mouseJoint.SetTarget(p2);
  339.         }
  340.     }
  341.    
  342.    
  343.     //マウスの下の物体取得
  344.     private var mousePVec:b2Vec2 = new b2Vec2();
  345.     public function GetBodyAtMouse(includeStatic:Boolean=false):b2Body{
  346.         // Make a small box.
  347.         mousePVec.Set(this.m_mouseXWorldPhys, this.m_mouseYWorldPhys);
  348.         var aabb:b2AABB = new b2AABB();
  349.         aabb.lowerBound.Set(this.m_mouseXWorldPhys - 0.001, this.m_mouseYWorldPhys - 0.001);
  350.         aabb.upperBound.Set(this.m_mouseXWorldPhys + 0.001, this.m_mouseYWorldPhys + 0.001);
  351.        
  352.         // Query the world for overlapping shapes.
  353.         var k_maxCount:int = 10;
  354.         var shapes:Array = new Array();
  355.         var count:int = this.m_b2_world.Query(aabb, shapes, k_maxCount);
  356.         var body:b2Body = null;
  357.         for (var i:int = 0; i <count; ++i)
  358.         {
  359.             if (shapes[i].GetBody().IsStatic() == false || includeStatic)
  360.             {
  361.                 var tShape:b2Shape = shapes[i] as b2Shape;
  362.                 var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
  363.                 if (inside)
  364.                 {
  365.                     body = tShape.GetBody();
  366.                     break;
  367.                 }
  368.             }
  369.         }
  370.         return body;
  371.     }
  372.  
  373. }

物理エンジンライブラリ Box2DFlashAS3 ジョイント2(直動ジョイント・歯車ジョイント)

直動ジョイントと歯車ジョイント(ギアジョイント)についてのメモ。
サンプルコードでは、回転ジョイントも使ってます。

直動ジョイント(PrismaticJoint)

  • 物体がリフトのように一定方向に動くジョイント。
  • 軸に沿って一定方向に動く。
  • モーターを使って、動かすこともできる。
  • 物があたっても回転しない、軸に沿った方向にしか動かない。

使い方

  1. 繋げる2つの物体(b2Body)を指定
  2. 繋げる場所(座標)(b2Vec2)を1ヶ所指定
  3. 軸(座標(ベクトル))(b2Vec2)を1ヶ所指定
  4. ジョイントの性質(b2PrismaticJointDef)を設定(モーター使用等)
  5. ジョイントの初期化→ジョイント登録

歯車ジョイント(GearJoint)

  • その名の通り、歯車のような働きをするジョイント。
  • 繋げたもの同士で、互いの運動量が影響しあう。
  • 実際の歯車のように運動方向は逆に伝わるっぽい(右回転→左回転)。
  • 繋げた物体の、運動量を合計して、比率を決めて運動量を割り振るっぽい。
  • 繋げられるのは、回転ジョイントと直動ジョイントだけ。

使い方

  1. 繋げる2つの物体(b2Body)を指定(回転ジョイントか直動ジョイントで繋いであるもの)
  2. 繋げる2つの物体のジョイント(b2Joint)を指定
  3. ジョイントの性質(b2GearJointDef)を設定(比率等)/li>
  4. ジョイント登録

続きを読む »

物理エンジンライブラリ Box2DFlashAS3 ジョイント1(回転ジョイント・距離ジョイント)

ジョイントは、物体と物体を繋げて動かしたりもできる機能。
回転・距離・直動・滑車・歯車・マウスの6種類があります。

ここでは、回転ジョイントと距離ジョイントについてのメモ。

回転ジョイント(RevoluteJoint)

  • 物体と物体をピンで繋げるようなジョイント。
  • ピンを中心にくるくる回る。
  • モーターを使って回すことができる。
  • 回る角度の制限もできる。

使い方

  1. 繋げる2つの物体(b2Body)を指定
  2. 繋げる場所(座標)(b2Vec2)を1ヶ所指定
  3. ジョイントの性質(b2RevoluteJointDef)を設定(モーター使用・角度制限等)/li>
  4. ジョイントの初期化→ジョイント登録

距離ジョイント(DistanceJoint)

  • 物体と物体をロープで繋げるようなジョイント。
  • ロープに引っ張られながらそれぞれ勝手に動く。
  • 繋ぐ場所が2箇所あるのが、回転ジョイントと違う。

使い方

  1. 繋げる2つの物体(b2Body)を指定
  2. 繋げる場所(座標)(b2Vec2)を2ヶ所指定
  3. ジョイントの性質(b2DistanceJointDef)を設定(振動数?均衡等??ここの設定はわからないです...。)/li>
  4. ジョイントの初期化→ジョイント登録

サンプルコード

実行結果(きのこの谷)
きのこの谷

※Box2Dのまとめたクラス(Box2DBase)を作って、基本クラスで使ってます。ソースは物理エンジンライブラリ Box2DFlashAS3(基本)にあります。

Actionscript:
  1. public class StudyB2Joint1 extends B2Base
  2. {
  3.     private var m_screen_width:int = 600;
  4.     private var m_screen_height:int = 500;
  5.    
  6.     //ぐるぐるきのこ
  7.     private var m_b2_guru_kinoko1:b2Body;
  8.     private var m_b2_guru_kinoko2:b2Body;
  9.     private var m_b2_guru_kinoko3:b2Body;
  10.     private var m_b2_guru_kinoko4:b2Body;
  11.    
  12.     //ゆらゆら棒
  13.     private var m_b2_yura_bar:b2Body;
  14.     private var m_b2_yura_kinoko1:b2Body;
  15.     private var m_b2_yura_kinoko2:b2Body;
  16.    
  17.     //表示用のMCを入れる
  18.     private var m_display_blocks:Sprite;
  19.    
  20.     //落ちてくるきのこ発生装置
  21.     private var m_kinokoL:Sprite;
  22.     private var m_kinokoS:Sprite;
  23.    
  24.     public function StudyB2Joint1() : void{
  25.        
  26.         super(24, 10, 10);
  27.        
  28.         //表示用設定
  29.         this.m_display_blocks = new Sprite;
  30.         this.addChild(m_display_blocks);
  31.  
  32.         this.makeGake();    //ガケ作成
  33.  
  34.         //橋(距離ジョイント)
  35.         this.makeBridge();
  36.  
  37.         //ぐるぐるきのこ(回転ジョイント+距離ジョイント)
  38.         this.makeGuruguruKinoko()
  39.  
  40.         //ゆらゆら棒(回転ジョイント+距離ジョイント)
  41.         this.makeYurayuraBar();     
  42.        
  43.         this.initKinokoS()//小さいきのこ
  44.         this.initKinokoL()//大きいきのこ
  45.        
  46.         //this.setDebugDraw();
  47.                    
  48.         this.addEventListener(Event.ENTER_FRAME, this.update, false, 0, true);
  49.     }
  50.    
  51.     //ガケ作成
  52.     private function makeGake():void {
  53.        
  54.         this.makeB2BodyBox(120, 120, 60, 440, 0, 0, 0.5, 0.5);
  55.         this.makeB2BodyBox(120, 120, 540, 440, 0, 0, 0.5, 0.5);
  56.    
  57.     }
  58.  
  59.     //橋(真ん中のやつ)作成
  60.     //:距離Joint
  61.     private function makeBridge():void {
  62.  
  63.         var x:Number;
  64.         var y:Number = 390;
  65.         var i:int//カウンタ
  66.        
  67.         var rack:b2Body = this.m_b2_world.GetGroundBody(); //橋の岸
  68.        
  69.         var boards:Array = new Array();
  70.  
  71.         //橋の板
  72.         for (i = 0; i <= 5; i++){
  73.             x = i * 60 + 150//配置場所X
  74.             var borad_display:Sprite = new board_60_mc as Sprite;  //橋板(表示用)
  75.             var board:b2Body = this.makeB2BodyBox(60, 10, x, y, 0, 1, 1.5, 0.5, borad_display, m_display_blocks);
  76.             boards[i] = board;
  77.         }
  78.        
  79.         //Joint
  80.         var body1:b2Body; //距離Joint 繋ぐ物体1つ目
  81.         var body2:b2Body; //距離Joint 繋ぐ物体2つ目
  82.         var anc1:b2Vec2;  //距離Joint 繋ぎ場所1つ目
  83.         var anc2:b2Vec2;  //距離Joint 繋ぎ場所2つ目
  84.        
  85.         var dj_def:b2DistanceJointDef;  //距離Joint
  86.  
  87.        
  88.         //左岸と板
  89.         x = 120//繋げる場所
  90.        
  91.         body1 = rack;
  92.         body2 = boards[0];
  93.         anc1 = this.createB2Vec(x - 5, y);
  94.         anc2 = this.createB2Vec(x + 5, y);
  95.         dj_def = new b2DistanceJointDef();
  96.         //dj_def.length = 0;
  97.         dj_def.Initialize(body1, body2, anc1, anc2);
  98.  
  99.         this.m_b2_world.CreateJoint(dj_def);           
  100.        
  101.         //板と板
  102.         for (i = 0; i <= 4; i++){
  103.            
  104.             //板の左側を繋げる
  105.             x = (i * 60) + 210//繋げる場所
  106.            
  107.             body1 = boards[i];
  108.             body2 = boards[i + 1];
  109.             anc1 = this.createB2Vec(x - 5, y);
  110.             anc2 = this.createB2Vec(x + 5, y);
  111.             dj_def = new b2DistanceJointDef();
  112.             dj_def.Initialize(body1, body2, anc1, anc2);
  113.            
  114.             this.m_b2_world.CreateJoint(dj_def);
  115.         }
  116.  
  117.         //板と右岸
  118.         //板の右側を繋げる
  119.         x = 510//繋げる場所
  120.        
  121.         body1 = boards[5];
  122.         body2 = rack;
  123.         anc1 = this.createB2Vec(x - 5, y);
  124.         anc2 = this.createB2Vec(x + 5, y);
  125.         dj_def = new b2DistanceJointDef();
  126.         dj_def.Initialize(body1, body2, anc1, anc2);
  127.  
  128.         this.m_b2_world.CreateJoint(dj_def);
  129.     }
  130.  
  131.    
  132.     //ぐるぐるきのこ(左側のポールに繋がってる回ってる円盤)作成
  133.     //:回転ジョイント+距離ジョイント
  134.     private function makeGuruguruKinoko():void {
  135.        
  136.         //表示用
  137.         var kinoko1_display:kinoko_kurukuru_green_mc = new kinoko_kurukuru_green_mc;
  138.         var kinoko2_display:kinoko_kurukuru_red_mc = new kinoko_kurukuru_red_mc;
  139.         var kinoko3_display:kinoko_kurukuru_yellow_mc = new kinoko_kurukuru_yellow_mc;
  140.         var kinoko4_display:kinoko_kurukuru_green_mc = new kinoko_kurukuru_green_mc;
  141.         kinoko2_display.width = 30;
  142.         kinoko2_display.height = 30;
  143.         kinoko4_display.width = 30;
  144.         kinoko4_display.height = 30;
  145.        
  146.         //位置
  147.         var bura_x:int = 150;
  148.         var bura_y:int = 100;
  149.        
  150.         var kinoko1:b2Body = this.makeB2BodyCircle(60, bura_x, bura_y, 1, 0.5, 0.5, kinoko1_display, this.m_display_blocks);
  151.         var kinoko2:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 90, 1, 0.5, 0.5, kinoko2_display, this.m_display_blocks);
  152.         var kinoko3:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 180, 1, 0.5, 0.5, kinoko3_display, this.m_display_blocks);
  153.         var kinoko4:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 270, 1, 0.5, 0.5, kinoko4_display, this.m_display_blocks);
  154.  
  155.        
  156.         //回転ジョイント
  157.        
  158.         //きのこ1はぐるぐる回る
  159.         var rj_def:b2RevoluteJointDef = new b2RevoluteJointDef;
  160.         rj_def.enableMotor = true;
  161.         rj_def.motorSpeed = 2.0;
  162.         rj_def.maxMotorTorque = 300000;
  163.        
  164.         rj_def.Initialize(this.m_b2_world.GetGroundBody(), kinoko1, kinoko1.GetPosition());
  165.         this.m_b2_world.CreateJoint(rj_def);
  166.        
  167.         //距離ジョイント
  168.        
  169.         //きのこ1と2(回るきのこ1の中心からずれた位置ときのこ2の中心を繋ぐ)
  170.         var anc1:b2Vec2 = this.createB2Vec(bura_x + 20, bura_y)//
  171.        
  172.         var dj_def1:b2DistanceJointDef = new b2DistanceJointDef;
  173.         dj_def1.Initialize(kinoko1, kinoko2, anc1, kinoko2.GetPosition());
  174.         this.m_b2_world.CreateJoint(dj_def1);
  175.        
  176.         //きのこ2と3(中心同士で繋ぐ)
  177.         var dj_def2:b2DistanceJointDef = new b2DistanceJointDef;
  178.         dj_def2.Initialize(kinoko2, kinoko3, kinoko2.GetPosition(), kinoko3.GetPosition());
  179.         this.m_b2_world.CreateJoint(dj_def2);
  180.        
  181.         //きのこ3と4(中心同士で繋ぐ)
  182.         var dj_def3:b2DistanceJointDef = new b2DistanceJointDef;
  183.         dj_def2.Initialize(kinoko3, kinoko4, kinoko3.GetPosition(), kinoko4.GetPosition());
  184.         this.m_b2_world.CreateJoint(dj_def2);
  185.        
  186.         //後から使えるように
  187.         this.m_b2_guru_kinoko1 = kinoko1;
  188.         this.m_b2_guru_kinoko2 = kinoko2;
  189.         this.m_b2_guru_kinoko3 = kinoko3;
  190.         this.m_b2_guru_kinoko4 = kinoko4;
  191.     }
  192.    
  193.    
  194.     //ゆらゆら棒(右側のポールに繋がってるモビールっぽいやつ)作成:回転ジョイント+距離ジョイント
  195.     private function makeYurayuraBar():void {
  196.        
  197.         //表示用
  198.         var bar_display:board_100_mc = new board_100_mc;
  199.         var kinoko1_display:kinoko_kurukuru_yellow_mc = new kinoko_kurukuru_yellow_mc;
  200.         var kinoko2_display:kinoko_kurukuru_red_mc = new kinoko_kurukuru_red_mc;
  201.         kinoko1_display.width = 40;
  202.         kinoko1_display.height = 40;
  203.         kinoko2_display.width = 40;
  204.         kinoko2_display.height = 40;
  205.        
  206.         var yura_x:int = 450;
  207.         var yura_y:int = 100;
  208.        
  209.         var bar:b2Body = this.makeB2BodyBox(100, 10, yura_x, yura_y, 0, 1, 0.5, 0.5, bar_display, this.m_display_blocks)//棒
  210.         var kinoko1:b2Body = this.makeB2BodyCircle(40, yura_x + 100, yura_y + 150, 1, 0.5, 0.5, kinoko1_display, this.m_display_blocks)//きのこ1
  211.         var kinoko2:b2Body = this.makeB2BodyCircle(40, yura_x - 100, yura_y + 150, 1, 0.5, 0.5, kinoko2_display, this.m_display_blocks)//きのこ2
  212.        
  213.         //回転ジョイント ゆれる棒
  214.         var rj_def:b2RevoluteJointDef = new b2RevoluteJointDef;
  215.         rj_def.enableLimit = true//角度制限付ける
  216.         rj_def.lowerAngle = -30  * Math.PI / 180;
  217.         rj_def.upperAngle = 30  * Math.PI / 180;
  218.        
  219.         rj_def.Initialize(this.m_b2_world.GetGroundBody(), bar, bar.GetPosition());
  220.         this.m_b2_world.CreateJoint(rj_def);
  221.        
  222.        
  223.         //距離ジョイント ゆれる棒ときのこ繋ぐ
  224.        
  225.         //きのこ1
  226.         var anc1:b2Vec2 = this.createB2Vec(yura_x + 50, yura_y);
  227.  
  228.         var dj_def1:b2DistanceJointDef = new b2DistanceJointDef;
  229.         dj_def1.Initialize(bar, kinoko1, anc1, kinoko1.GetPosition());
  230.         this.m_b2_world.CreateJoint(dj_def1);
  231.        
  232.         //きのこ2
  233.         var anc2:b2Vec2 = this.createB2Vec(yura_x - 50, yura_y);
  234.        
  235.         var dj_def2:b2DistanceJointDef = new b2DistanceJointDef;
  236.         dj_def2.Initialize(bar, kinoko2, anc2, kinoko2.GetPosition());
  237.         this.m_b2_world.CreateJoint(dj_def2);
  238.        
  239.         //後から使えるように
  240.         this.m_b2_yura_bar = bar;
  241.         this.m_b2_yura_kinoko1 = kinoko1;
  242.         this.m_b2_yura_kinoko2 = kinoko2;
  243.     }
  244.    
  245.    
  246.     //演算
  247.     private function update(e:Event):void{
  248.    
  249.         var self:StudyB2Joint1 = this;
  250.  
  251.         //距離ジョイントで繋げてる紐を描く
  252.        
  253.         //Body位置から描画位置移動する関数
  254.         var moveTo_Pos:Function = function(graphics:Graphics, body:b2Body, offset_x:Number = 0, offset_y:Number = 0):void {
  255.            
  256.             var x:Number = body.GetPosition().x * self.m_b2_physcale + offset_x;
  257.             var y:Number = body.GetPosition().y * self.m_b2_physcale + offset_y;
  258.        
  259.             graphics.moveTo(x, y);
  260.         }
  261.        
  262.        
  263.         //Body位置へ線を引く関数
  264.         var lineTo_Pos:Function = function(graphics:Graphics, body:b2Body):void {
  265.            
  266.             var x:Number = body.GetPosition().x * self.m_b2_physcale;
  267.             var y:Number = body.GetPosition().y * self.m_b2_physcale;
  268.  
  269.             graphics.lineTo(x, y);
  270.         }      
  271.        
  272.         this.m_display_blocks.graphics.clear();
  273.         this.m_display_blocks.graphics.lineStyle(1, 0x9FD06F);
  274.        
  275.         //ぐるぐるぐきのこ
  276.         moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko1);
  277.         lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko2);
  278.         lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko3);
  279.         lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko4);
  280.    
  281.    
  282.         //ゆらゆら棒
  283.         //棒は斜めになるので、角度から繋ぐ位置取得
  284.         var angle:Number = this.m_b2_yura_bar.GetAngle();
  285.         var offset_x:Number = Math.cos(angle) * 50;
  286.         var offset_y:Number = Math.sin(angle) * 50;
  287.         moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_bar, offset_x, offset_y);
  288.         lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_kinoko1);
  289.         moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_bar, -offset_x, -offset_y);
  290.         lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_kinoko2);
  291.        
  292.         //B2Boxの時間進める
  293.         this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations);
  294.        
  295.         //各B2BoxのBodyの動きにあわせて中のSpriteを動かす
  296.         for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){
  297.            
  298.             var bb_x:Number = bb.GetPosition().x * m_b2_physcale;
  299.             var bb_y:Number = bb.GetPosition().y * m_b2_physcale;
  300.            
  301.             //画面外に出て行ったきのこ削除
  302.             if (bb_x <-100 || bb_x> 700 || bb_y <-100 || bb_y> 600) {
  303.                 this.m_b2_world.DestroyBody(bb);
  304.                 if(bb.m_userData != null){
  305.                     this.m_kinokoS.removeChild(bb.m_userData);
  306.                     bb.m_userData = null;
  307.                 }
  308.             }
  309.            
  310.             //演算結果にあわせて表示用データ移動
  311.             if (bb.m_userData is Sprite){
  312.                 //メートルからピクセル単位に変換
  313.                 bb.m_userData.x = bb_x;
  314.                 bb.m_userData.y = bb_y;
  315.                 bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
  316.             }
  317.         }
  318.     }
  319.    
  320.     //-----きのこを降らす(ここは、基本と同じもの使用)-----
  321.    
  322.     //大きいきのこ作る
  323.     private function initKinokoL():void {
  324.        
  325.         var self:StudyB2Joint1 = this;
  326.        
  327.         //これはMC配置するだけ
  328.         var kinoko:kinoko_L_MC = new kinoko_L_MC;
  329.         kinoko.x = 555;
  330.         kinoko.y = 350;
  331.         kinoko.width = 60;
  332.         kinoko.height = 65;
  333.        
  334.         kinoko.buttonMode = true;
  335.        
  336.         kinoko.addEventListener(MouseEvent.MOUSE_OVER,
  337.             function(e:Event):void {
  338.                 kinoko.gotoAndPlay("frm_hover");
  339.             });
  340.                                
  341.         kinoko.addEventListener(MouseEvent.MOUSE_UP,
  342.             function(e:Event):void {
  343.                 kinoko.gotoAndPlay("frm_action");
  344.                 self.makeKinokoS(Math.random() * 550 + 50, 0);
  345.             });
  346.            
  347.         this.m_kinokoL = kinoko;
  348.        
  349.         this.addChild(this.m_kinokoL);
  350.  
  351.     }
  352.    
  353.    
  354.     //小さいきのこ入れるのを作って、小さいきのこ配置
  355.     private function initKinokoS():void {
  356.        
  357.         //小さいきのこを入れる
  358.         this.m_kinokoS = new Sprite();
  359.         this.addChild(this.m_kinokoS);
  360.        
  361.         //最初の小さいきのこ配置
  362.         for (var i:int = 0; i <5 ;i++){
  363.             this.makeKinokoS(Math.random() * 550 + 50, 0);
  364.         }
  365.     }
  366.    
  367.    
  368.     //小さいきのこ作成
  369.     private function makeKinokoS(x:Number, y:Number):void {
  370.        
  371.         var kinoko:Sprite;
  372.         var land = Math.random();
  373.        
  374.         if (land>= 0.6) {
  375.             //普通のきのこ
  376.             kinoko = new kinoko_S1_MC as Sprite;
  377.         }
  378.         else if(land>= 0.3){
  379.             //怪しいきのこ
  380.             kinoko = new kinoko_S2_MC as Sprite;
  381.         }
  382.         else {
  383.             //しめじ
  384.             kinoko = new kinoko_S3_MC as Sprite;
  385.         }   
  386.        
  387.         this.makeB2BodyCircle(30, x, y, 1.0, 0.5, 0.5, kinoko, this.m_kinokoS);
  388.     }
  389. }