物理エンジンライブラリ 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. ジョイント登録

サンプルコード

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

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

Actionscript:
  1. public class StudyB2Joint2 extends B2Base
  2. {
  3.    
  4.     private var m_display_blocks:Sprite;  //表示用
  5.    
  6.     public function StudyB2Joint2()
  7.     {
  8.         super(24, 10, 10);
  9.        
  10.         //表示用設定
  11.         this.m_display_blocks = new Sprite;
  12.         this.addChild(m_display_blocks);
  13.        
  14.         //drawGrid(600, 500, 50);
  15.        
  16.         this.makeGake()//崖作成
  17.        
  18.         this.makeLift1()//左のリフトとぐるぐる円盤(直動ジョイント+回転ジョイント+歯車ジョイント)
  19.         this.makeLift2()//真ん中のリフト2つ(直動ジョイント+歯車ジョイント)
  20.        
  21.         this.makeGuruguru1(); //ぐるぐる円盤(回転ジョイント+歯車ジョイント)
  22.        
  23.         this.initKinokoL()//クリックできる大きいきのこ
  24.         this.initKinokoS()//降ってくる小さいきのこ
  25.        
  26.         //this.setDebugDraw();
  27.        
  28.         this.addEventListener(Event.ENTER_FRAME, update, false, 0, true);
  29.     }
  30.    
  31.    
  32.     //崖作成
  33.     private function makeGake():void {
  34.        
  35.         //左の崖
  36.         this.makeB2BodyBox(100, 100, 75, 450, 0, 0, 0.5, 0.5);
  37.        
  38.         //真ん中の崖2つ
  39.         //上段
  40.         this.makeB2BodyBox(100, 150, 250, 225, 0, 0, 0.5, 0.5);
  41.         this.makeB2BodyBox(100, 150, 525, 225, 0, 0, 0.5, 0.5);
  42.         //中段
  43.         this.makeB2BodyBox(25, 100, 212.5, 350, 0, 0, 0.5, 0.5);
  44.         this.makeB2BodyBox(25, 100, 562.5, 350, 0, 0, 0.5, 0.5);
  45.         //下段
  46.         this.makeB2BodyBox(100, 100, 250, 450, 0, 0, 0.5, 0.5);
  47.         this.makeB2BodyBox(100, 100, 525, 450, 0, 0, 0.5, 0.5);
  48.     }
  49.    
  50.    
  51.     //左の崖 上下移動リフトとぐるぐる円盤きのこ
  52.     //:直動ジョイント+回転ジョイント+歯車ジョイント
  53.     private var m_b2_lift_ud_body:b2Body;
  54.     private var m_b2_lift_ud_joint:b2PrismaticJoint;
  55.    
  56.     private function makeLift1():void {
  57.        
  58.         //表示用
  59.         var lift_disp:Sprite = new board_100_mc as Sprite;              //リフト
  60.         var circle_disp:Sprite = new kinoko_kurukuru_red_mc as Sprite;  //ぐるぐる回る円盤
  61.         circle_disp.width = 60;
  62.         circle_disp.height = 60;
  63.        
  64.         var ground:b2Body = this.m_b2_world.GetGroundBody();
  65.        
  66.         //上下するリフト(直動ジョイント)
  67.         var lift:b2Body = this.makeB2BodyBox(100, 10, 75, 395, 0, 1, 0.5, 0.5, lift_disp, this.m_display_blocks);
  68.  
  69.         //軸(沿って動く方向)
  70.         var axis:b2Vec2 = new b2Vec2(0, -1.0); //上垂直方向に
  71.        
  72.         var pj_def:b2PrismaticJointDef = new b2PrismaticJointDef;
  73.         pj_def.enableMotor = true;    //モーター使う
  74.         pj_def.maxMotorForce = 30000//小さいとモーターが進まない
  75.         pj_def.motorSpeed = 5.0;
  76.        
  77.         pj_def.Initialize(ground, lift, lift.GetPosition(), axis);
  78.         var joint1:b2PrismaticJoint = this.m_b2_world.CreateJoint(pj_def) as b2PrismaticJoint;
  79.        
  80.         this.m_b2_lift_ud_body = lift;
  81.         this.m_b2_lift_ud_joint = joint1;
  82.        
  83.        
  84.         //ぐるぐる回るきのこ円(回転ジョイント)
  85.         var circle:b2Body = this.makeB2BodyCircle(60, 75, 50, 1, 0.5, 0.5, circle_disp, this.m_display_blocks);
  86.        
  87.         //衝突しないようにする
  88.         circle.GetShapeList().m_filter.maskBits = 0;
  89.        
  90.         //回転ジョイント
  91.         var rj_def:b2RevoluteJointDef = new b2RevoluteJointDef;
  92.         rj_def.Initialize(ground, circle, circle.GetPosition());
  93.        
  94.         var joint2:b2Joint = this.m_b2_world.CreateJoint(rj_def);
  95.                
  96.        
  97.         //歯車ジョイントで繋ぐ(直動ジョイントと歯車ジョイント)
  98.         var gj_def:b2GearJointDef = new b2GearJointDef();
  99.         gj_def.body1 = lift;
  100.         gj_def.body2 = circle;
  101.         gj_def.joint1 = joint1;
  102.         gj_def.joint2 = joint2;
  103.        
  104.         //運動量の比率
  105.         //0=伝えない 1=同等
  106.         //1より上=body1の力が大きく伝わる??
  107.         //1より下(小数点以下)=body2の力が大きく伝わる??
  108.         //マイナス=力の方向が同じになる
  109.         gj_def.ratio = 1.0;
  110.        
  111.         this.m_b2_world.CreateJoint(gj_def);           
  112.     }
  113.    
  114.    
  115.     //真ん中の崖2つ 左右移動のリスト2つ
  116.     //:直動ジョイント+歯車ジョイント
  117.     private var m_b2_lift_lr_body:b2Body;
  118.     private var m_b2_lift_lr_joint:b2PrismaticJoint;
  119.    
  120.     private function makeLift2():void {
  121.        
  122.         //表示用
  123.         var lift1_disp:Sprite = new board_80_mc as Sprite;  //リフト上段
  124.         var lift2_disp:Sprite = new board_80_mc as Sprite;  //リフト下段
  125.        
  126.         var ground:b2Body = this.m_b2_world.GetGroundBody();
  127.        
  128.         //左右移動リフト上段(モーターあり)
  129.         var lift1:b2Body = this.makeB2BodyBox(75, 10, 265.5, 145, 0, 1, 0.5, 0.5, lift1_disp, this.m_display_blocks);
  130.        
  131.         //軸(沿って動く方向)
  132.         var axis:b2Vec2 = new b2Vec2(1.0, 0); //右水平方向に
  133.        
  134.         var pj_def1:b2PrismaticJointDef = new b2PrismaticJointDef;
  135.         pj_def1.enableMotor = true;
  136.         pj_def1.maxMotorForce = 30000;
  137.         pj_def1.motorSpeed = 5.0;
  138.        
  139.         pj_def1.Initialize(ground, lift1, lift1.GetPosition(), axis);
  140.         var joint1:b2PrismaticJoint = this.m_b2_world.CreateJoint(pj_def1) as b2PrismaticJoint;
  141.        
  142.         this.m_b2_lift_lr_body = lift1;
  143.         this.m_b2_lift_lr_joint = joint1;
  144.        
  145.         //左右移動リフト下段(モーターなし)
  146.         var lift2:b2Body = this.makeB2BodyBox(75, 10, 515, 395, 0, 1, 0.5, 0.5, lift2_disp, this.m_display_blocks);
  147.        
  148.         var pj_def2:b2PrismaticJointDef = new b2PrismaticJointDef;
  149.        
  150.         pj_def2.Initialize(ground, lift2, lift2.GetPosition(), axis);
  151.         var joint2:b2Joint = this.m_b2_world.CreateJoint(pj_def2);
  152.        
  153.        
  154.         //歯車ジョイントで繋ぐ(直動ジョイントと直動ジョイント)
  155.         var gj_def:b2GearJointDef = new b2GearJointDef();
  156.         gj_def.body1 = lift1;
  157.         gj_def.body2 = lift2;
  158.         gj_def.joint1 = joint1;
  159.         gj_def.joint2 = joint2;
  160.        
  161.         //運動量の比率
  162.         gj_def.ratio = 1.0; //同等に
  163.        
  164.         this.m_b2_world.CreateJoint(gj_def);           
  165.     }
  166.    
  167.    
  168.     //真ん中の崖2つ上のぐるぐる円盤きのこ
  169.     //:回転ジョイント+直動ジョイント
  170.     private function makeGuruguru1():void {
  171.        
  172.         //表示用
  173.         var circle1_disp:Sprite = new kinoko_kurukuru_yellow_mc as Sprite;  //ぐるぐる回る円盤1
  174.         circle1_disp.width = 50;
  175.         circle1_disp.height = 50;
  176.        
  177.         var circle2_disp:Sprite = new kinoko_kurukuru_yellow_mc as Sprite;  //ぐるぐる回る円盤2
  178.         circle2_disp.width = 50;
  179.         circle2_disp.height = 50;
  180.        
  181.         var ground:b2Body = this.m_b2_world.GetGroundBody();
  182.        
  183.         //回転ジョイント1(左側)
  184.         var circle1:b2Body = this.makeB2BodyCircle(50, 212, 50, 1, 0.5, 0.5, circle1_disp, this.m_display_blocks);
  185.        
  186.         //衝突しないようにする
  187.         circle1.GetShapeList().m_filter.maskBits = 0;
  188.        
  189.         var rj_def1:b2RevoluteJointDef = new b2RevoluteJointDef;
  190.         rj_def1.maxMotorTorque = 30000;
  191.         rj_def1.enableMotor = true;
  192.         rj_def1.motorSpeed = 1.0;
  193.        
  194.         rj_def1.Initialize(ground, circle1, circle1.GetPosition());
  195.        
  196.         var joint1:b2Joint = this.m_b2_world.CreateJoint(rj_def1);
  197.        
  198.         //回転ジョイント2(右側)
  199.         var circle2:b2Body = this.makeB2BodyCircle(50, 565, 50, 1, 0.5, 0.5, circle2_disp, this.m_display_blocks);
  200.        
  201.         //衝突しないようにする
  202.         circle2.GetShapeList().m_filter.maskBits = 0;
  203.        
  204.         var rj_def2:b2RevoluteJointDef = new b2RevoluteJointDef;
  205.        
  206.         rj_def2.Initialize(ground, circle2, circle2.GetPosition());
  207.        
  208.         var joint2:b2Joint = this.m_b2_world.CreateJoint(rj_def2);     
  209.        
  210.        
  211.         //歯車ジョイント(回転ジョイントと回転ジョイント)
  212.         var gj_def:b2GearJointDef = new b2GearJointDef();
  213.         gj_def.body1 = circle1;
  214.         gj_def.body2 = circle2;
  215.         gj_def.joint1 = joint1;
  216.         gj_def.joint2 = joint2;
  217.  
  218.         gj_def.ratio = 0.1; //右側の方の運動量を大きく
  219.        
  220.         this.m_b2_world.CreateJoint(gj_def);
  221.     }
  222.    
  223.    
  224.     //演算
  225.     private function update(e:Event):void{
  226.                    
  227.         //左リフトの上下移動制限
  228.         var lift_ud_mspeed:int = this.m_b2_lift_ud_joint.GetMotorSpeed();
  229.         var lift_ud_y:Number = this.m_b2_lift_ud_body.GetPosition().y * this.m_b2_physcale;
  230.         //上限・下限になったらモーターの方向を逆に
  231.         if (lift_ud_y>= 390) {
  232.             if (lift_ud_mspeed <0) {
  233.                 this.m_b2_lift_ud_joint.SetMotorSpeed(lift_ud_mspeed * -1);
  234.             }
  235.         }
  236.         else if (lift_ud_y <= 160) {
  237.             if (lift_ud_mspeed> 0) {
  238.                 this.m_b2_lift_ud_joint.SetMotorSpeed(lift_ud_mspeed * -1);
  239.                
  240.             }            
  241.         }
  242.         //寝てたら起こす
  243.         if (this.m_b2_lift_ud_body.IsSleeping()) {
  244.             this.m_b2_lift_ud_body.WakeUp();
  245.         }
  246.        
  247.         //真ん中リフトの左右移動制限
  248.         var lift_lr_mspeed:int = this.m_b2_lift_lr_joint.GetMotorSpeed();
  249.         var lift_lr_x:Number = this.m_b2_lift_lr_body.GetPosition().x * this.m_b2_physcale;
  250.         if (lift_lr_x>= 515) {
  251.             if (lift_lr_mspeed> 0) {
  252.                 this.m_b2_lift_lr_joint.SetMotorSpeed(lift_lr_mspeed * -1);
  253.             }
  254.         }
  255.         else if (lift_lr_x <= 265) {
  256.             if (lift_lr_mspeed <0) {
  257.                 this.m_b2_lift_lr_joint.SetMotorSpeed(lift_lr_mspeed * -1);
  258.             }            
  259.         }
  260.         //寝てたら起こす
  261.         if (this.m_b2_lift_lr_body.IsSleeping()) {
  262.             this.m_b2_lift_lr_body.WakeUp();
  263.         }
  264.        
  265.         //B2Boxの時間進める
  266.         this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations);  
  267.        
  268.         //各B2BoxのBodyの動きにあわせて中のSpriteを動かす
  269.         for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){
  270.            
  271.             var bb_x:Number = bb.GetPosition().x * m_b2_physcale;
  272.             var bb_y:Number = bb.GetPosition().y * m_b2_physcale;
  273.            
  274.             //画面外に出て行ったきのこ削除
  275.             if (bb_x <-100 || bb_x> 700 || bb_y <-100 || bb_y> 600) {
  276.                 this.m_b2_world.DestroyBody(bb);
  277.                 if(bb.m_userData != null){
  278.                     this.m_kinokoS.removeChild(bb.m_userData);
  279.                     bb.m_userData = null;
  280.                 }
  281.             }
  282.            
  283.             //演算結果にあわせて表示用データ移動
  284.             if (bb.m_userData is Sprite){
  285.                 //メートルからピクセル単位に変換
  286.                 bb.m_userData.x = bb_x;
  287.                 bb.m_userData.y = bb_y;
  288.                 bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
  289.             }
  290.         }
  291.     }
  292.    
  293.     //-----きのこを降らす(ここは、基本と同じもの使用)-----
  294.    
  295.     //落ちてくるきのこ発生装置
  296.     private var m_kinokoL:Sprite;
  297.     private var m_kinokoS:Sprite;
  298.    
  299.     //大きいきのこ作る
  300.     private function initKinokoL():void {
  301.        
  302.         var self:StudyB2Joint2 = this;
  303.        
  304.         //これはMC配置するだけ
  305.         var kinoko:kinoko_L_MC = new kinoko_L_MC;
  306.         kinoko.x = 385;
  307.         kinoko.y = 227;
  308.         kinoko.width = 84;
  309.         kinoko.height = 90;
  310.        
  311.         kinoko.buttonMode = true;
  312.        
  313.         kinoko.addEventListener(MouseEvent.MOUSE_OVER,
  314.                                 function(e:Event):void {
  315.                                     kinoko.gotoAndPlay("frm_hover");
  316.                                 });
  317.                                
  318.         kinoko.addEventListener(MouseEvent.MOUSE_UP,
  319.                                 function(e:Event):void {
  320.                                     kinoko.gotoAndPlay("frm_action");
  321.                                     self.makeKinokoS(Math.random() * 550 + 50, 0);
  322.                                 });
  323.                                
  324.         this.m_kinokoL = kinoko;
  325.        
  326.         this.addChild(this.m_kinokoL);
  327.  
  328.     }
  329.    
  330.    
  331.     //小さいきのこ入れるのを作って、小さいきのこ配置
  332.     private function initKinokoS():void {
  333.        
  334.         //小さいきのこを入れる
  335.         this.m_kinokoS = new Sprite();
  336.         this.addChild(this.m_kinokoS);
  337.        
  338.         //最初の小さいきのこ配置
  339.        
  340.         //左の崖
  341.         this.makeKinokoS(50, 0);
  342.         this.makeKinokoS(100, 0);
  343.        
  344.         //真ん中の崖のリフトの上に
  345.         this.makeKinokoS(240, 115);
  346.        
  347.         this.makeKinokoS(500, 375);   
  348.         /*
  349.         for (var i:int = 0; i <5 ;i++){
  350.             this.makeKinokoS(Math.random() * 550 + 50, 0);
  351.         }
  352.         */
  353.     }
  354.    
  355.    
  356.     //小さいきのこ作成
  357.     private function makeKinokoS(x:Number, y:Number):void {
  358.        
  359.         var kinoko:Sprite;
  360.         var land = Math.random();
  361.        
  362.         if (land>= 0.6) {
  363.             //普通のきのこ
  364.             kinoko = new kinoko_S1_MC as Sprite;
  365.         }
  366.         else if(land>= 0.3){
  367.             //怪しいきのこ
  368.             kinoko = new kinoko_S2_MC as Sprite;
  369.         }
  370.         else {
  371.             //しめじ
  372.             kinoko = new kinoko_S3_MC as Sprite;
  373.         }   
  374.        
  375.         this.makeB2BodyCircle(30, x, y, 1.0, 0.5, 0.5, kinoko, this.m_kinokoS);
  376.     }
  377.    
  378. }

コメント・トラックバック

  1. 冷吟閑酔 2009-06-18 06:12:02 (ピンバック)

    [...] DFlashAS3 ジョイント2(直動ジョイント・歯車ジョイント) http://hokori.net/2009/03/26/box2dflashas3_joint2/ [...]

コメントを送る
※は入力必須です。コメントは管理者の承認後に表示されます。