Home > Flash | WEB > Box2d で降りしきる箱と戯れる箱

Box2d で降りしきる箱と戯れる箱

前回に続きまして、四角の一人四角遊びです(?)

画面をクリックした後、「←」「→」で左右移動、「s」キーでジャンプです。
前回同様、「s」キー連打で多段ジャンプ!

↓参考にさせていただきました。
Box2Dサンプル maskBitsによる衝突フィルタリング

今回やりたかったのは、上からものを落として、
何回かぶつかったら、部屋から立ち去らせるということ。

具体的には、
3回、床との衝突を検知したら、
落ちてくる箱の衝突フィルタの値を変更するということをやりたかった。

箱を定義するときにIDを指定しておくことで、何と何が衝突したか検知できる。

ACTIONSCRIPT:
  1. var floorBodyDef:b2BodyDef = new b2BodyDef();
  2.     // 床のIDを floor としておく
  3.     floorBodyDef.userData = new Object;
  4.     floorBodyDef.userData.id = "floor";
  5.     floorBodyDef.position.Set(6, 8);

3回衝突を検知したら、maskBitsの値を0x00に変更して、誰とも衝突しないようにする。
Box2Dのソースから追って、filterを再度ゲットできるところを探したんだけど、
これでよかったんだろうか。

ACTIONSCRIPT:
  1. for (var ce:b2ContactEdge = floor.m_contactList; ce != null; ce = ce.next) { 
  2.     var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
  3.     var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
  4.     if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){ 
  5.         if(obj2.m_userData.id == "dropbox"){
  6.             if (obj2.m_userData.crash> 2){
  7.                 shape = obj2.GetShapeList();
  8.                 shape.m_filter.maskBits = 0x00;
  9.             }else {
  10.                 obj2.m_userData.crash++;
  11.             }
  12.         } 
  13.     }
  14. }

だいぶ作りたいものに近づいてきました!
次はShapeで絵をちゃんと重ねよう!

↓ソース全部

ACTIONSCRIPT:
  1. package src {
  2.     import Box2D.Collision.b2AABB;
  3.     import Box2D.Collision.b2ContactID;
  4.     import Box2D.Collision.Shapes.b2CircleDef;
  5.     import Box2D.Collision.Shapes.b2PolygonDef;
  6.     import Box2D.Collision.Shapes.b2Shape;
  7.     import Box2D.Common.Math.b2Vec2;
  8.     import Box2D.Dynamics.b2Body;
  9.     import Box2D.Dynamics.b2BodyDef;
  10.     import Box2D.Dynamics.b2DebugDraw;
  11.     import Box2D.Dynamics.b2World;
  12.     import Box2D.Dynamics.Contacts.b2ContactEdge;
  13.     import flash.display.Sprite;
  14.     import flash.events.Event;
  15.     import flash.events.KeyboardEvent;
  16.     import flash.events.MouseEvent;
  17.     import flash.events.TextEvent;
  18.     import flash.text.TextField;
  19.     import flash.ui.Keyboard;
  20.     import flash.utils.*;
  21.    
  22.     /**
  23.     * @author okm
  24.     */
  25.     public class LabyrinsSuite extends Sprite{
  26.         private var world:b2World;
  27.         private var square:b2Body;
  28.         private var floor:b2Body;
  29.        
  30.         public function LabyrinsSuite() {
  31.             var textField:TextField = new TextField;
  32.             textField.text = "click me ";
  33.             textField.x = 100;
  34.             textField.y = 100;
  35.            
  36.             textField.selectable = false;
  37.             this.addChild(textField);
  38.            
  39.             stage.addEventListener(MouseEvent.CLICK, go);
  40.         }
  41.        
  42.         public function go(event:MouseEvent):void {
  43.             stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
  44.             stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
  45.             ////////////////////////////////////////
  46.             // 物理エンジンのセットアップ
  47.            
  48.             // 縦横200メートルの世界を作成
  49.             var worldAABB:b2AABB = new b2AABB();
  50.             worldAABB.lowerBound.Set(-100, -100);
  51.             worldAABB.upperBound.Set(100, 100);
  52.            
  53.             // 重力を下方向に10m/s^2とする
  54.             var gravity:b2Vec2 = new b2Vec2(0, 10);
  55.            
  56.             // 外枠と重力を指定して、物理エンジン全体をセットアップする
  57.             world = new b2World(worldAABB, gravity, true);
  58.            
  59.             /////////////////////////////////////////////
  60.             // 部屋の作成 横幅 12M 高さ 8M の部屋を作成
  61.             /////////////////////////////////////////////
  62.             // 床
  63.             // 天井の高さは 8M 床の 中心X座標は 7.5M(真ん中)
  64.             var floorBodyDef:b2BodyDef = new b2BodyDef();
  65.             // 床のIDを floor としておく
  66.             floorBodyDef.userData = new Object;
  67.             floorBodyDef.userData.id = "floor";
  68.             floorBodyDef.position.Set(6, 8);
  69.            
  70.             // 床の形を、幅12m、厚さ20cmとする
  71.             // 指定するのはその半分の値
  72.             var floorShapeDef:b2PolygonDef = new b2PolygonDef();
  73.             floorShapeDef.friction = 0.1;
  74.             floorShapeDef.SetAsBox(6, 0.1);
  75.            
  76.             // 床のcategoryBits/maskBits
  77.             floorShapeDef.filter.maskBits = 0x01;
  78.             floorShapeDef.filter.categoryBits = 0x01;
  79.            
  80.             // 床を動かない物体として作る
  81.             floor = world.CreateBody(floorBodyDef);
  82.             floor.CreateShape(floorShapeDef);
  83.            
  84.             // 両端の壁 高さは 8M 幅 10cm
  85.             // 左壁
  86.             var leftWallBodyDef:b2BodyDef = new b2BodyDef();
  87.             leftWallBodyDef.userData = new Object;
  88.             leftWallBodyDef.userData.id = "left";
  89.             leftWallBodyDef.position.Set(0.05, 4);
  90.             var wallShapeDef:b2PolygonDef = new b2PolygonDef();
  91.             wallShapeDef.friction = 0;
  92.             wallShapeDef.SetAsBox(0.05, 4);
  93.            
  94.             var leftWall:b2Body = world.CreateBody(leftWallBodyDef);
  95.             leftWall.CreateShape(wallShapeDef);
  96.            
  97.             // 右壁
  98.             var rightWallBodyDef:b2BodyDef = new b2BodyDef();
  99.             rightWallBodyDef.userData = new Object;
  100.             rightWallBodyDef.userData.id = "right";
  101.             rightWallBodyDef.position.Set(11.95, 4);
  102.             var rightWall:b2Body = world.CreateBody(rightWallBodyDef);
  103.             rightWall.CreateShape(wallShapeDef);
  104.            
  105.             ////////////////////////////////////////
  106.             // 箱生命体
  107.             ////////////////////////////////////////
  108.            
  109.             // 箱の位置を左から2.5m、上から1mとする
  110.             var boxBodyDef:b2BodyDef = new b2BodyDef();
  111.             boxBodyDef.userData = new Object;
  112.             boxBodyDef.userData.id = "hako";
  113.             boxBodyDef.position.Set(2.5, 1);
  114.            
  115.             // 箱の幅 60cm 高さ 1M 重さは 30kg とする
  116.             var boxShapeDef:b2PolygonDef= new b2PolygonDef();
  117.             //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
  118.             boxShapeDef.SetAsBox(0.6, 1);
  119.             boxShapeDef.density = 50;        // 密度 [kg/m^2] 30/0.6*1
  120.             boxShapeDef.friction = 0.2;      // 摩擦係数
  121.             boxShapeDef.restitution = 0.3;   // 反発係数、通常は0~1
  122.            
  123.             // 箱を動く物体として作る
  124.             var boxBody:b2Body = world.CreateBody(boxBodyDef);
  125.             boxBody.CreateShape(boxShapeDef);
  126.             // SetMassFromShapes で重力が有効になる
  127.             boxBody.SetMassFromShapes();
  128.             square = boxBody;
  129.                        
  130.             ////////////////////////////////////////
  131.             // 描画設定
  132.             var debugDraw:b2DebugDraw = new b2DebugDraw();
  133.             debugDraw.m_sprite = this;
  134.             debugDraw.m_drawScale = 45; // 1mを45ピクセルにする
  135.             debugDraw.m_fillAlpha = 0.3; // 不透明度
  136.             debugDraw.m_lineThickness = 1; // 線の太さ
  137.             debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
  138.             world.SetDebugDraw(debugDraw);
  139.            
  140.             this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  141.             setInterval(dropBox, 700);
  142.         }
  143.        
  144.         private function dropBox():void {
  145.            
  146.             var dropbox_x:Number = this.xRandomInt(11, 1);
  147.            
  148.             var dropboxBodyDef:b2BodyDef = new b2BodyDef();
  149.             dropboxBodyDef.userData = new Object;
  150.             dropboxBodyDef.userData.id = "dropbox";
  151.             dropboxBodyDef.userData.crash = 0;
  152.             dropboxBodyDef.angle = this.xRandomInt(5, 0) / 10;
  153.             dropboxBodyDef.position.Set(dropbox_x, 0.5);
  154.            
  155.             // 箱の幅 15cm 高さ 15cm 重さは 1kg とする
  156.             var dropboxShapeDef:b2PolygonDef= new b2PolygonDef();
  157.             //boxShapeDef.SetAsOrientedBox(0.3, 0.2, new b2Vec2(0, 0), 0.8);
  158.             dropboxShapeDef.SetAsBox(0.15, 0.15);
  159.             dropboxShapeDef.density = 25;        // 密度
  160.             dropboxShapeDef.friction = 0.2;      // 摩擦係数
  161.             dropboxShapeDef.restitution = 0.7;   // 反発係数、通常は0~1
  162.            
  163.             // 箱を動く物体として作る
  164.             var dropboxBody:b2Body = world.CreateBody(dropboxBodyDef);
  165.             //dropboxBody.CreateShape(dropboxShapeDef);
  166.             // SetMassFromShapes で重力が有効になる
  167.             //dropboxBody.SetMassFromShapes();
  168.            
  169.             // ボールのcategoryBits/maskBits
  170.             dropboxShapeDef.filter.categoryBits = 0x01;
  171.             dropboxShapeDef.filter.maskBits = 0x01;
  172.            
  173.             var dropbox:b2Body = world.CreateBody(dropboxBodyDef);
  174.             dropbox.CreateShape(dropboxShapeDef)
  175.             dropbox.SetMassFromShapes();
  176.         }
  177.        
  178.         private var m_InputL:Number = 0;
  179.         private var m_InputR:Number = 0;
  180.         private var m_InputS:Number = 0;
  181.         private var m_Dir:Number = 0;
  182.         private var moveTime:Number = 0;
  183.        
  184.         // キーが押されたときの処理
  185.         private function keyDownHandler(event:KeyboardEvent):void {
  186.             square.WakeUp();
  187.             if(event.keyCode == Keyboard.LEFT && m_InputL != 1){
  188.                 m_InputL = 1;
  189.                 m_InputR = 0;
  190.                 m_Dir = -1.0;
  191.                 moveTime = 0;
  192.             }
  193.             if(event.keyCode == Keyboard.RIGHT && m_InputR != 1){
  194.                 m_InputR = 1;
  195.                 m_InputL = 0;
  196.                 m_Dir = 1.0;
  197.                 moveTime = 0;
  198.             }
  199.             if(event.keyCode == 83){ // s
  200.                 m_InputS = 1;
  201.             }
  202.         }
  203.         private function keyUpHandler(event:KeyboardEvent):void {
  204.             if(event.keyCode == Keyboard.LEFT){
  205.                 m_InputL = 0;
  206.             }
  207.             if(event.keyCode == Keyboard.RIGHT){
  208.                 m_InputR = 0;
  209.             }
  210.             if(event.keyCode == 83){ // s
  211.                 m_InputS = 0;
  212.             }
  213.         }
  214.  
  215.         private function enterFrameHandler(event:Event):void {
  216.             if (m_InputS == 1) {
  217.                 square.m_linearVelocity.y = -4;
  218.             }
  219.             if (m_InputL> 0) {
  220.                 var leftForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
  221.                 if (moveTime <30) moveTime++;
  222.                 square.m_linearVelocity.x = -leftForce;
  223.             }
  224.             if (m_InputR> 0) {
  225.                 var rightForce:Number = this.easeInOutQuad(moveTime, 0.5, 6, 30);
  226.                 if (moveTime <30) moveTime++;
  227.                 square.m_linearVelocity.x = rightForce;
  228.             }
  229.             if (world == null) {
  230.                 return;
  231.             }
  232.  
  233.             var shape:b2Shape;
  234.             // 衝突判定 箱生命体
  235.             /*  今回はとりあえず箱との衝突はカウントしない方向で。
  236.             for (var ce:b2ContactEdge = square.m_contactList; ce != null; ce = ce.next) { 
  237.                 var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
  238.                 var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
  239.                 if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){ 
  240.                     if (obj2.m_userData.id == "dropbox") {
  241.                         if (obj2.m_userData.crash> 2){
  242.                             shape = obj2.GetShapeList();
  243.                             shape.m_filter.maskBits = 0x00;
  244.                         }else {
  245.                             obj2.m_userData.crash++;
  246.                         }
  247.                     } 
  248.                 }
  249.             }
  250.             */
  251.            
  252.             // 衝突判定 床
  253.             for (var ce:b2ContactEdge = floor.m_contactList; ce != null; ce = ce.next) { 
  254.                 var obj1:b2Body = ce.contact.GetShape1().m_body;//1つ目のオブジェクト
  255.                 var obj2:b2Body = ce.contact.GetShape2().m_body;//2つ目のオブジェクト
  256.                 if(obj1.m_userData && obj2.m_userData && ce.contact.GetManifoldCount() == 1){ 
  257.                     if(obj2.m_userData.id == "dropbox"){
  258.                         if (obj2.m_userData.crash> 2){
  259.                             shape = obj2.GetShapeList();
  260.                             shape.m_filter.maskBits = 0x00;
  261.                         }else {
  262.                             obj2.m_userData.crash++;
  263.                         }
  264.                     } 
  265.                 }
  266.             }
  267.            
  268.             // Flashはデフォルトで秒間24フレームなので、
  269.             // 物理シミュレーションを1/24秒進める
  270.             world.Step(1 / 24, 10);
  271.         }
  272.        
  273.         /**
  274.          * t = time
  275.          * b = beginning value
  276.          * c = change in value
  277.          * d = duration
  278.          */
  279.         public function easeInOutQuad(t:Number, b:Number, c:Number, d:Number):Number {
  280.             if ((t/=d/2) <1) return c/2*t*t + b;
  281.             return -c/2 * ((--t)*(t-2) - 1) + b;
  282.         };
  283.        
  284.         public function xRandomInt (nMax:Number, nMin:Number):Number {
  285.             // nMinからnMaxまでのランダムな整数を返す
  286.             var nRandomInt:Number = Math.floor(Math.random()*(nMax-nMin+1))+nMin;
  287.             return nRandomInt;
  288.         }
  289.     }
  290. }

Comments:1

okm 08-07-07 (月) 15:09

あぁ・・・スリープ状態になって、落ち着く四角たちがいる・・・まぁいいや・・・。

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://parpue.net/web/35/trackback
Listed below are links to weblogs that reference
Box2d で降りしきる箱と戯れる箱 from parpue.net

Home > Flash | WEB > Box2d で降りしきる箱と戯れる箱

リンク
chocolataste-planner
millon

サーチ
Feeds
Meta
blog ranking ブログランキング・にほんブログ村へ
にほんブログ村 テクノラティのお気に入りに追加する

Return to page top