Home > Flash | WEB > Box2D で 降りしきる音符を拾いまわる箱

Box2D で 降りしきる音符を拾いまわる箱

前回作ったものに、pngファイルを重ねて表示しました。
動き回る箱が、音符を拾うゲームです。
箱組曲ですねw

Box2Dで落ちる音符が自然でいい感じです。
だいぶ遊べるものに近づいてきました。
ちなみにエンドレスです。ウハハ!拾い続けるのだ!

画面をクリックして、「←」「→」で左右移動、「s」でジャンプです。
今回やっと、無限ジャンプをさせなくしました。

次回は、箱生命体を改め、ちゃんと歩く何か動かそうかなw
それから音符の種類も増やそうと思っています。

今回は、外部ファイルを埋め込んで、
Spriteとして表示できるようにしています。

埋め込み部

ACTIONSCRIPT:
  1. [Embed(source='hako.png')]
  2.     private var hakoImg:Class;
  3.     private var spt:Sprite;
  4.        
  5.     [Embed(source = 'onpu.png')]
  6.     private var onpuImg:Class;

表示できるようにして追加

ACTIONSCRIPT:
  1. var bmp:Bitmap = new hakoImg();
  2.     // 中心座標と重なるように。
  3.     bmp.x = -18;
  4.     bmp.y = -36;
  5.     spt = new Sprite;
  6.     spt.visible = false;
  7.     spt.addChild(bmp);
  8.     addChild(spt);

「箱はどんなことがあっても転ばない」というところで悩みました。
毎フレーム傾きを戻してやることにしました。

ACTIONSCRIPT:
  1. // 箱生命体は、決して倒れない!
  2. var xform:b2XForm = square.GetXForm();
  3. square.SetXForm(xform.position, 0);

書いてみると2行でしたが、果たしてこれが正しいやり方なのか・・・

あとは、地面にいるときだけジャンプ可能にしたのは、
「地面と衝突しているかどうか」でフラグ判定しているだけです。

悩みながらやったのでソースが、だんだん荒くなってきた。

続く!

↓ソース全部

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

なんか、あんまテストしないで、できた勢いでアップしてみたけど、、、
♪ ← ありがイッパイいるみたいでキモー!

Comments:0

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://parpue.net/web/38/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