|  | Adobe Flash非公式テクニカルノート StarlingフレームワークでつくったテクスチャのボールをBox2Dで弾ませる
         
          | ID: FN1203004 | Product: Flash CS5 and above | Platform: All | Version: 11 and above/ActionScript 3.0 |  
 Starlingフレームワークで使える物理演算エンジン「Box2DFlash」(以下単に単にBox2Dと呼びます)の基本的な使い方は「Starlingフレームワークで物理演算エンジンBox2Dを使う」で解説しました。本稿では、そのスクリプトに手を加えて、テクスチャからつくったボールを弾ませてみます。 なお、Box2Dはバージョンによって、細かい仕様が変わることもありますのでご注意ください。本稿ではバージョン2.1aを使います。また、Starlingフレームワークの基礎とその使い方については、「Starlingフレームワークを使う」をお読みください。 
 01 テクスチャでボールをつくる物理演算シミュレーションに入る前に、Starlingフレームワークでテクスチャのボールをつくりましょう。背景が抜かれたボール用の円形ビットマップをFlashの[ライブラリ]に納め、[ビットマッププロパティ]ダイアログボックスでクラスを設定しておきます(図001)。
 図001■[ライブラリ]に用意したボール用ビットマップにクラスを設定する
  さて、この[ライブラリ]のビットマップをどうやってStarlingフレームワークにもっていくかです。というのは、前出「Starlingフレームワークを使う」01「Starlingフレームワークで何からつくり始めるか」に述べたとおり、「Starlingフレームワークの表示リストには、Starlingの表示オブジェクトしか加えられません」。そこで使うのが、Textureクラスです。 テクスチャ(texture)というのは、Starlingフレームワークでイメージを表示するために用いられるビットマップデータのことです。TextureクラスにはTexture.fromBitmapData()という静的メソッドが備わっていて、BitmapDataオブジェクトからTextureインスタンスがつくれます。 もっとも、Textureインスタンスは表示オブジェクトではないので、そのままではStarlingフレームワークのステージには置けません。Imageクラスのコンストラクタメソッドに引数として渡したうえで、そのImageオブジェクトを表示リストに加えます。 
  
    | 
var myTexture:Texture = Texture.fromBitmapData(BitmapDataオブジェクト);var myImage:Image = new Image(myTexture);
 addChild(myImage);
 |  Starlingフレームワークの表示リスト最上位(ルート)に置く表示オブジェクトとして以下のクラス(MySprite)を定めると(スクリプト001)、[ライブラリ]にクラス(Pen)を設定したビットマップがステージの中央に表示されます(図002)。なお、FLAファイル(ASファイルと同階層)には、つぎのフレームアクションが書かれているものとします(前出「Starlingフレームワークを使う」03「Starlingフレームワークの初期化」スクリプト002参照)。 
スクリプト001■[ライブラリ]のビットマップからテクスチャのボールをつくって表示する
  
    | 
// フレームアクション: メインタイムラインimport starling.core.Starling;
 var myStarling:Starling = new Starling(MySprite, stage);
 myStarling.start();
 |  
 
  
    | 
// ActionScript 3.0クラス定義ファイル: MySprite.as
package {  import flash.display.BitmapData;  import starling.display.Sprite;  import starling.display.Image;  import starling.textures.Texture;  import starling.events.Event;  public class MySprite extends Sprite {    public function MySprite() {      addEventListener(Event.ADDED_TO_STAGE, initialize);    }    private function initialize(eventObject:Event):void {      var nStageWidth:Number = stage.stageWidth;      var nStageHeight:Number = stage.stageHeight;      var myBitmapData:BitmapData = new Pen();      var myTexture:Texture = Texture.fromBitmapData(myBitmapData);      var nRadius:Number = myBitmapData.width / 2;      var myBall:Image = createBall(nRadius, myTexture);      myBall.x = nStageWidth / 2;      myBall.y = nStageHeight / 2;      addChild(myBall);    }    private function createBall(nRadius:Number, myTexture:Texture):Image {      var myImage:Image = new Image(myTexture);      myImage.pivotX = nRadius;      myImage.pivotY = nRadius;      return myImage;    }  }} |  図002■[ライブラリ]のビットマップがStarlingフレームワークでステージ中央に表示された
  初期設定のメソッド(initialize())は、[ライブラリ]のビットマップに設定したクラス(Pen)からインスタンスをつくり、Texture.fromBitmapData()メソッドの引数に渡してTextureインスタンス(myTexture)にしています(スクリプト001第14〜15行目)。 さらに、ボールの半径とTextureインスタンスを引数として、ボールのImageインスタンスをつくるメソッド(createBall())が呼出されます(スクリプト001第17行目)。このメソッドは、受取ったTextureオブジェクト(myTexture)から新たなImageインスタンス(myImage)をつくり、半径(nRadius)に合わせてインスタンスの原点を調整します(第23〜25行目)。そして、Imageインスタンスを返します(第26行目)。 
 02 Box2Dのスクリプトにテクスチャのボールを組込む初めに述べましたとおり、本稿はスクリプトを頭から書くのではなく、FN1202006「Starlingフレームワークで物理演算エンジンBox2Dを使う」のサンプルに手を加えます。具体的には、スクリプト003「動的な剛体が落下して静的な剛体のうえで弾むアニメーション」です(FN1203004図005再掲)。
 FN1203004図005■落下した矩形の剛体が床で弾む(再掲)
  この落下する矩形のQuadインスタンスを、テクスチャのボールに置換えます。そのために、FN1203004スクリプト003のクラス(MySprite)にまずはつぎのような追加・修正を加えます。第1に、落下する矩形のQuadインスタンスを扱う処理は、スクリプトから除きます。プロパティ(boxEdge)やメソッド(createDynamicBox())とその呼出しのステートメントなどです。 第2に、テクスチャのボールをつくり、Box2Dの剛体として組入れます。Textureインスタンス(myTexture)のつくり方は、前掲スクリプト001(第14〜16行目)と同じです。Box2Dの剛体に組入れるメソッド(createDynamicBall())は後で定めますので、その呼出しを初期設定のメソッド(initialize())に加え、でき上がったボールのImageインスタンス(myBall)は表示リストに納めます。 
  
    | 
// import宣言追加import flash.display.BitmapData;
 import starling.display.Image;
 import starling.textures.Texture;
 // ...[中略]...
 public class MySprite extends Sprite {
 // ...[中略]...
 // private var boxEdge:Number = 20;   // 削除
 // ...[中略]...
 private function initialize(eventObject:Event):void {
 // ...[中略]...
 // [ライブラリ]のビットマップからTextureインスタンスをつくる
 var myBitmapData:BitmapData = new Pen();
 var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
 var nRadius:Number = myBitmapData.width / 2;
 // ...[中略]...
 // テクスチャのボールを剛体として表示リストに加える
 // var myQuad:Quad = createDynamicBox(nCenterX, boxEdge, boxEdge, boxEdge, 0x0000FF);   // 削除
 var myBall:Image = createDynamicBall(nCenterX, 0, nRadius, myTexture);
 // addChild(myQuad);   // 削除
 addChild(myBall);
 // ...[中略]...
 }
 // ...[中略]...
 /* 削除
 private function createDynamicBox(nX:Number, nY:Number, nWidth:Number, nHeight:Number, nColor:uint):Quad {
 // ...[中略]...
 }
 */
 // ...[中略]...
 }
 |  それでは、取りあえずメソッドをふたつ定義します。できあがりのスクリプトは、後にスクリプト002として掲げます。引用したステートメントには、その行番号を添えました。 ひとつ目は、初期設定のメソッド(initialize())から呼出すメソッド(createDynamicBall())で、Box2Dの剛体を定義し、テクスチャからつくったImageインスタンスを返します(スクリプト002第52〜59行目)。中からふたつのメソッド(createBodyDef()とcreateBallForBodyDef())を呼出しています(前者は前出「Starlingフレームワークで物理演算エンジンBox2Dを使う」ですでに定められています)。この引用部分だけでは、まだ完成していません。 ふたつ目は、ひとつ目のメソッド(createDynamicBall())から呼出したメソッド(createBallForBodyDef())です。テクスチャからImageインスタンスをつくり、剛体定義のb2BodyDefオブジェクトに関連づけて返します(スクリプト002第73〜79行目)。中身は前掲スクリプト001のImageインスタンスをつくるメソッド(createBall())とほとんど同じで、ただインスタンスをb2BodyDef.userDataプロパティに設定するステートメントが加わっています(第77行目)。 
  
    | 
// Box2Dの剛体を定義してボールのImageインスタンスを返す
 private function createDynamicBall(nX:Number, nY:Number, nRadius:Number, myTexture:Texture):Image {  var bodyDef:b2BodyDef = createBodyDef(nX, nY, b2Body.b2_dynamicBody);  var myImage:Image = createBallForBodyDef(bodyDef, nRadius, myTexture); 
  return myImage;} 
// テクスチャからつくったImageインスタンスに剛体定義を関連づけて返す
 private function createBallForBodyDef(bodyDef:b2BodyDef, nRadius:Number, myTexture:Texture):Image {  var myImage:Image = new Image(myTexture);  myImage.pivotX = nRadius;  myImage.pivotY = nRadius;  bodyDef.userData = myImage;  return myImage;} |  ここまで修正しただけで動きを確かめると、ステージ左上角にテクスチャからつくったボールのImageインスタンスが表れます(図003)。Box2Dのシミュレーションにはまだ組込んでいないので、インスタンスは動きません。けれど、物理演算はメモリ内で行われます。ですから、目に見えるところで確かめておくと、後で問題が起こったときにも原因を絞り込みやすくなります。 図003■ステージ左上角にボールのインスタンスが表れる
  
 03 テクスチャのボールをBox2Dで弾ませるそれでは、テクスチャでつくったボールをBox2Dのシミュレーションに組入れます。前項で定めた、Box2Dの剛体を定義してボールのImageインスタンスを返すメソッド(createDynamicBall())には、まだ足りないところがあるといいました。このメソッドに、ステートメントを3行加えます(スクリプト002第55〜57行目)。
 まず、フィクスチャの定義となるb2FixtureDefインスタンス(fixtureDef)をつくります(スクリプト002第55行目)。そのための関数(createFixtureDefAndCircleShape)を新たに定めます。つぎに、フィクスチャに、重さ(密度)や滑りやすさ(摩擦)、跳ね返りの度合い(弾性)などを定めます(第56行目)。そして、剛体とフィクスチャのふたつの定義から剛体(body)をつくるのです(第57行目)。後のふたつの処理については、すでにメソッド(setFixtureDef()とcreateBodyWithFixture())が定められていますので、それぞれに必要な引数を与えて呼出します。 b2FixtureDefインスタンスをつくるメソッド(createFixtureDefAndCircleShape())は、新たなb2FixtureDefインスタンス(fixtureDef)に剛体のかたちを定めた上で、インスタンスを返します(スクリプト002第85〜90行目)。ボールのかたちは円形ですので、b2CircleShapeオブジェクトでつくります。コンストラクタメソッドの引数は円の半径です(第87行目)。b2CircleShapeオブジェクトは、b2FixtureDefインスタンスのb2FixtureDef.shapeプロパティに設定します(第88行目)。 
  
    | 
// import宣言追加
 import Box2D.Collision.Shapes.b2CircleShape;public class MySprite extends Sprite { 
// Box2Dの剛体を定義してボールのImageインスタンスを返す
   private function createDynamicBall(nX:Number, nY:Number, nRadius:Number, myTexture:Texture):Image {    var bodyDef:b2BodyDef = createBodyDef(nX, nY, b2Body.b2_dynamicBody);    var myImage:Image = createBallForBodyDef(bodyDef, nRadius, myTexture);// 3ステートメント追加
    var fixtureDef:b2FixtureDef = createFixtureDefAndCircleShape(nRadius);    setFixtureDef(fixtureDef, density, friction, restitution);    var body:b2Body = createBodyWithFixture(world, bodyDef, fixtureDef);    return myImage;  } 
// 剛体のかたちが定められた新たなb2FixtureDefインスタンスを返す
   private function createFixtureDefAndCircleShape(nRadius:Number):b2FixtureDef {    var fixtureDef:b2FixtureDef = new b2FixtureDef();    var myShape:b2CircleShape = new b2CircleShape(nRadius * SCALE);    fixtureDef.shape = myShape;    return fixtureDef;  } 
} |  これでクラス(MySprite.as)の修正は済みました。テクスチャのボールが物理演算シミュレーションに組込まれましたので、ボールがステージ上から落ちてきて、下にある床に当たって弾みます(図004)。定義したクラス(MySprite)全体は、以下のスクリプト002のとおりです。 図004■テクスチャのボールが落ちて床で弾むスクリプト002■テクスチャでつくったボールの剛体が床に落ちて弾むアニメーション
  
 
  
    | 
// ActionScript 3.0クラス定義ファイル: MySprite.as
package {  import flash.display.BitmapData;  import starling.display.DisplayObject;  import starling.display.Sprite;  import starling.display.Quad;  import starling.display.Image;  import starling.textures.Texture;  import starling.events.Event;  import Box2D.Common.Math.b2Vec2;  import Box2D.Dynamics.b2World;  import Box2D.Dynamics.b2BodyDef;  import Box2D.Dynamics.b2Body;  import Box2D.Dynamics.b2FixtureDef;  import Box2D.Collision.Shapes.b2PolygonShape;  import Box2D.Collision.Shapes.b2CircleShape;  public class MySprite extends Sprite {    private const SCALE:Number = 1 / 30;    private var world:b2World;    private var gravityVertical:Number = 10;    private var velocityIterations:int = 10;    private var positionIterations:int = 10;    private var time:Number = 1 / 24;    private var density:Number = 1;    private var friction:Number = 0.5;    private var restitution:Number = 0.8;    public function MySprite() {      addEventListener(Event.ADDED_TO_STAGE, initialize);    }    private function initialize(eventObject:Event):void {      var nStageWidth:Number = stage.stageWidth;      var nStageHeight:Number = stage.stageHeight;      var nCenterX:Number = nStageWidth / 2;      var nFloorWidth:Number = nStageWidth * 0.8;      var nFloorHeight:Number = 20;      var myBitmapData:BitmapData = new Pen();      var myTexture:Texture = Texture.fromBitmapData(myBitmapData);      var nRadius:Number = myBitmapData.width / 2;      world = new b2World(new b2Vec2(0, gravityVertical), true);      var floorQuad:Quad = createStaticFloor(nCenterX,nStageHeight - nFloorHeight,nFloorWidth,nFloorHeight,0xCCCCCC);      addChild(floorQuad);      var myBall:Image = createDynamicBall(nCenterX, 0, nRadius, myTexture);      addChild(myBall);      addEventListener(Event.ENTER_FRAME, update);    }    private function createStaticFloor(nX:Number, nY:Number, nWidth:Number, nHeight:Number, nColor:uint):Quad {      var bodyDef:b2BodyDef = createBodyDef(nX, nY);      var myQuad:Quad = createQuadForBodyDef(bodyDef, nWidth, nHeight, nColor);      var fixtureDef:b2FixtureDef = createFixtureDefWithShape(nWidth, nHeight);      var body:b2Body = createBodyWithFixture(world, bodyDef, fixtureDef);      return myQuad;    }    private function createDynamicBall(nX:Number, nY:Number, nRadius:Number, myTexture:Texture):Image {      var bodyDef:b2BodyDef = createBodyDef(nX, nY, b2Body.b2_dynamicBody);      var myImage:Image = createBallForBodyDef(bodyDef, nRadius, myTexture);      var fixtureDef:b2FixtureDef = createFixtureDefAndCircleShape(nRadius);      setFixtureDef(fixtureDef, density, friction, restitution);      var body:b2Body = createBodyWithFixture(world, bodyDef, fixtureDef);      return myImage;    }    private function createBodyDef(nX:Number, nY:Number, nType:uint= 0):b2BodyDef {      var bodyDef:b2BodyDef = new b2BodyDef();      bodyDef.position.Set((nX * SCALE), nY * SCALE);      bodyDef.type = nType;      return bodyDef;    }    private function createQuadForBodyDef(bodyDef:b2BodyDef, nWidth:Number, nHeight:Number, nColor:uint=0):Quad {      var myQuad:Quad = new Quad(nWidth,nHeight,nColor);      myQuad.pivotX = myQuad.width / 2;      myQuad.pivotY = myQuad.height / 2;      bodyDef.userData = myQuad;      return myQuad;    }    private function createBallForBodyDef(bodyDef:b2BodyDef, nRadius:Number, myTexture:Texture):Image {      var myImage:Image = new Image(myTexture);      myImage.pivotX = nRadius;      myImage.pivotY = nRadius;      bodyDef.userData = myImage;      return myImage;    }    private function createFixtureDefWithShape(nWidth:Number, nHeight:Number):b2FixtureDef {      var fixtureDef:b2FixtureDef = new b2FixtureDef();      setShapeToFixtureDef(fixtureDef, nWidth / 2, nHeight / 2);      return fixtureDef;    }    private function createFixtureDefAndCircleShape(nRadius:Number):b2FixtureDef {      var fixtureDef:b2FixtureDef = new b2FixtureDef();      var myShape:b2CircleShape = new b2CircleShape(nRadius * SCALE);      fixtureDef.shape = myShape;      return fixtureDef;    }    private function setShapeToFixtureDef(fixtureDef:b2FixtureDef, nX:Number, nY:Number):void {      var myShape:b2PolygonShape = new b2PolygonShape();      myShape.SetAsBox(nX * SCALE, nY * SCALE);      fixtureDef.shape = myShape;    }    private function setFixtureDef(fixtureDef:b2FixtureDef, density:Number, friction:Number, restitution:Number = 0):void {      fixtureDef.density = density;      fixtureDef.friction = friction;      fixtureDef.restitution = restitution;    }    private function createBodyWithFixture(world:b2World, bodyDef:b2BodyDef, fixtureDef:b2FixtureDef):b2Body {      var body:b2Body = world.CreateBody(bodyDef);      body.CreateFixture(fixtureDef);      return body;    }    private function update(eventObject:Event):void {      world.Step(time, velocityIterations, positionIterations);      var body:b2Body = world.GetBodyList();      while (body) {        var myObject:DisplayObject = body.GetUserData() as DisplayObject;        if (myObject) {          var position:b2Vec2 = body.GetPosition();          myObject.x = position.x / SCALE;          myObject.y = position.y / SCALE;          myObject.rotation = body.GetAngle();        }        body = body.GetNext();      }    }  }} |  
 04 ボールをたくさん落として互いに弾ませるひとつのボールが無事に落ちましたので、数を増やしてみましょう。100個のボールをランダムな水平位置から、時間差で落とすことにします。Timerクラスを使えば、時間の間隔も、イベントリスナーの呼出し回数も決められるので便利です。でき上がりのクラス(MySprite)は、後にスクリプト003として掲げてあります。そのうち、修正した部分をつぎに抜出しました。
 
  
    | 
import flash.utils.Timer;import flash.events.TimerEvent; 
public class MySprite extends Sprite { 
  private var restitution:Number = 0.8;   // 0.5;// プロパティとして宣言
  private var myTexture:Texture;  private var nStageWidth:Number;  private var nStageHeight:Number;  private var nRadius:Number;  private var myTimer:Timer = new Timer(200, 100); 
  private function initialize(eventObject:Event):void {// var nStageWidth:Number = stage.stageWidth;
    nStageWidth = stage.stageWidth;// var nStageHeight:Number = stage.stageHeight;
    nStageHeight = stage.stageHeight; 
    // var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
     myTexture = Texture.fromBitmapData(myBitmapData);// var nRadius:Number = myBitmapData.width / 2;
    nRadius = myBitmapData.width / 2; 
    // var myBall:Image = createDynamicBall(nCenterX, 0, nRadius, myTexture);// addChild(myBall);
 
 
    myTimer.addEventListener(TimerEvent.TIMER, addBall);    myTimer.start();  }// ランダムな水平位置からボールを落とす
  private function addBall(eventObject:TimerEvent):void {    var nX:Number = Math.random() * nStageWidth;    var myBall:Image = createDynamicBall(nX, -nRadius, nRadius, myTexture);    addChild(myBall);  } 
} |  まず、Timerクラスを使った処理を見ていきます。必要なクラスをimport宣言し(スクリプト003第2〜3行目)、Timerインスタンスをプロパティ(myTimer)に納めます(第32行目)。200ミリ秒間隔で、イベントリスナーを100回呼出します。そして、初期設定のメソッド(initialize())は、Timerオブジェクトにリスナーメソッド(addBall())を定めて、Timer.start()メソッドを呼出します(第49〜50行目)。 つぎに、リスナーメソッド(addBall())は、呼出されるたびにひとつボールの剛体を定義してImageインスタンスをつくります(スクリプト003第52〜56行目)。前掲スクリプト002(第41〜42行目)では、初期設定のメソッド(initialize())でこの処理を行っていましたので、そのステートメントは削除しました。また、このリスナーメソッドの中で用いている値には、初期設定のメソッド(initialize())で得ているもの(nStageWidthやnRadius、myTexture)があります。したがって、それらはプロパティとして宣言しました(第28〜31行目)。 これで、200ミリ秒ごとにランダムな水平位置から、つぎつぎと100個のボールが落とされ、互いにぶつかり合います(図005)。 図005■ランダムな水平位置から時間差で100個のボールが落とされて互いにぶつかり合うスクリプト003■ボールの剛体をつぎつぎに落として互いに弾ませるアニメーション
  
 
  
    | 
// ActionScript 3.0クラス定義ファイル: MySprite.as
package {  import flash.display.BitmapData;  import flash.utils.Timer;  import flash.events.TimerEvent;  import starling.display.DisplayObject;  import starling.display.Sprite;  import starling.display.Quad;  import starling.display.Image;  import starling.textures.Texture;  import starling.events.Event;  import Box2D.Common.Math.b2Vec2;  import Box2D.Dynamics.b2World;  import Box2D.Dynamics.b2BodyDef;  import Box2D.Dynamics.b2Body;  import Box2D.Dynamics.b2FixtureDef;  import Box2D.Collision.Shapes.b2PolygonShape;  import Box2D.Collision.Shapes.b2CircleShape;  public class MySprite extends Sprite {    private const SCALE:Number = 1 / 30;    private var world:b2World;    private var gravityVertical:Number = 10;    private var velocityIterations:int = 10;    private var positionIterations:int = 10;    private var time:Number = 1 / 24;    private var density:Number = 1;    private var friction:Number = 0.5;    private var restitution:Number = 0.8;    private var myTexture:Texture;    private var nStageWidth:Number;    private var nStageHeight:Number;    private var nRadius:Number;    private var myTimer:Timer = new Timer(200, 100);    public function MySprite() {      addEventListener(Event.ADDED_TO_STAGE, initialize);    }    private function initialize(eventObject:Event):void {      nStageWidth = stage.stageWidth;      nStageHeight = stage.stageHeight;      var nCenterX:Number = nStageWidth / 2;      var nFloorWidth:Number = nStageWidth * 0.8;      var nFloorHeight:Number = 20;      var myBitmapData:BitmapData = new Pen();      myTexture = Texture.fromBitmapData(myBitmapData);      nRadius = myBitmapData.width / 2;      world = new b2World(new b2Vec2(0, gravityVertical), true);      var floorQuad:Quad = createStaticFloor(nCenterX, nStageHeight - nFloorHeight, nFloorWidth, nFloorHeight, 0xCCCCCC);      addChild(floorQuad);      addEventListener(Event.ENTER_FRAME, update);      myTimer.addEventListener(TimerEvent.TIMER, addBall);      myTimer.start();    }    private function addBall(eventObject:TimerEvent):void {      var nX:Number = Math.random() * nStageWidth;      var myBall:Image = createDynamicBall(nX, -nRadius, nRadius, myTexture);      addChild(myBall);    }    private function createStaticFloor(nX:Number, nY:Number, nWidth:Number, nHeight:Number, nColor:uint):Quad {      var bodyDef:b2BodyDef = createBodyDef(nX,nY);      var myQuad:Quad = createQuadForBodyDef(bodyDef, nWidth, nHeight, nColor);      var fixtureDef:b2FixtureDef = createFixtureDefWithShape(nWidth, nHeight);      var body:b2Body = createBodyWithFixture(world, bodyDef, fixtureDef);      return myQuad;    }    private function createDynamicBall(nX:Number, nY:Number, nRadius:Number, myTexture:Texture):Image {      var bodyDef:b2BodyDef = createBodyDef(nX, nY, b2Body.b2_dynamicBody);      var myImage:Image = createBallForBodyDef(bodyDef, nRadius, myTexture);      var fixtureDef:b2FixtureDef = createFixtureDefAndCircleShape(nRadius);      setFixtureDef(fixtureDef, density, friction, restitution);      var body:b2Body = createBodyWithFixture(world, bodyDef, fixtureDef);      return myImage;    }    private function createBodyDef(nX:Number, nY:Number, nType:uint= 0):b2BodyDef {      var bodyDef:b2BodyDef = new b2BodyDef();      bodyDef.position.Set((nX * SCALE), nY * SCALE);      bodyDef.type = nType;      return bodyDef;    }    private function createQuadForBodyDef(bodyDef:b2BodyDef, nWidth:Number, nHeight:Number, nColor:uint=0):Quad {      var myQuad:Quad = new Quad(nWidth, nHeight, nColor);      myQuad.pivotX = myQuad.width / 2;      myQuad.pivotY = myQuad.height / 2;      bodyDef.userData = myQuad;      return myQuad;    }    private function createBallForBodyDef(bodyDef:b2BodyDef, nRadius:Number, myTexture:Texture):Image {      var myImage:Image = new Image(myTexture);      myImage.pivotX = nRadius;      myImage.pivotY = nRadius;      bodyDef.userData = myImage;      return myImage;    }    private function createFixtureDefWithShape(nWidth:Number, nHeight:Number):b2FixtureDef {      var fixtureDef:b2FixtureDef = new b2FixtureDef();      setShapeToFixtureDef(fixtureDef, nWidth / 2, nHeight / 2);      return fixtureDef;    }    private function setShapeToFixtureDef(fixtureDef:b2FixtureDef, nX:Number, nY:Number):void {      var myShape:b2PolygonShape = new b2PolygonShape();      myShape.SetAsBox(nX * SCALE, nY * SCALE);      fixtureDef.shape = myShape;    }    private function setFixtureDef(fixtureDef:b2FixtureDef, density:Number, friction:Number, restitution:Number = 0):void {      fixtureDef.density = density;      fixtureDef.friction = friction;      fixtureDef.restitution = restitution;    }    private function createBodyWithFixture(world:b2World, bodyDef:b2BodyDef, fixtureDef:b2FixtureDef):b2Body {      var body:b2Body = world.CreateBody(bodyDef);      body.CreateFixture(fixtureDef);      return body;    }    private function createFixtureDefAndCircleShape(nRadius:Number):b2FixtureDef {      var fixtureDef:b2FixtureDef = new b2FixtureDef();      var myShape:b2CircleShape = new b2CircleShape(nRadius * SCALE);      fixtureDef.shape = myShape;      return fixtureDef;    }    private function update(eventObject:Event):void {      world.Step(time, velocityIterations, positionIterations);      var body:b2Body = world.GetBodyList();      while (body) {        var myObject:DisplayObject = body.GetUserData() as DisplayObject;        if (myObject) {          var position:b2Vec2 = body.GetPosition();          myObject.x = position.x / SCALE;          myObject.y = position.y / SCALE;          myObject.rotation = body.GetAngle();        }        body = body.GetNext();      }    }  }} |  
 作成者: 野中文雄作成日: 2012年2月19日
 Copyright © 
2001-2012 Fumio Nonaka.  All rights reserved.
 |