yoppa.org


Web動画表現 2010

AS3でアニメーションを作成する 2 – 物体をなめらかに移動する

物体が移動するアニメーションを作る

先週の授業では、アニメーション作成の導入として、ムービークリップのrotationプロパティを操作して物体が回転するアニメーションを作成しました。今週はこの手法を応用して、物体がなめらかに移動するアニメーションを作成してみましょう。

物体を動いているように見せるには、物体の位置、つまり座標を変化させることで実現可能です。ムービークリップの二次元座標を変化させるには、x (横方向の位置), y (縦方向の位置) を操作します。

アニメーションのためのテンプレート

先週と同様に、ActionScript 3でアニメーションを実現するため、イベントリスナーを使用して画面の更新を行います。イベントリスナーの更新、また、そのイベントハンドラ(関数)を記入したテンプレートを用意しました。まずは、これをコピーして使用しましょう。

package {
  import flash.display.Stage;
  import flash.display.Sprite;
  import flash.events.Event;

  public class Main extends Sprite {
    //ここに変数を宣言する

    public function Main() {
      //初期化のための命令を記述

      //イベントリスナーの登録
      this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }

    function enterFrameHandler(event:Event):void {
      //更新する内容を記述
    }
  }
}

位置を移動する

では、さっそく位置を移動するプログラムを作成してみましょう。

いつものようにまずは、AS3形式でFLAファイルを作成し、ドキュメントクラスを「Main.as」に設定します。次に、FLAファイル側に新規にムービークリップシンボルを作成します。今回はムービークリップのクラス名は「Ball」と名付けています。

このムービークリップの座標(x, y)をそれぞれ、posX、posYという変数に格納するようにしています。また、x軸方向の移動スピードをspeedX、Y軸方向のスピードをspeedYという変数で変化させることにします。まず、Main() 関数で初期位置とスピードを設定した上で、ムービークリップをステージ上に表示しています。その後、定期的に呼びだされるイベントハンドラでは、以下の処理を行っています。

  • X方向の座標 posX を、1フレームで speedX 移動する – posX = posX + speedX
  • X方向の座標 posY を、1フレームで speedY 移動する – posX = posX + speedX
package {
  import flash.display.Sprite;
  import flash.events.Event;

  public class Main extends Sprite {

    //変数を宣言
    var posX:Number,posY:Number;//位置
    var speedX:Number,speedY:Number;//速度
    //ムービークリップをインスタンス化
    var ball:Ball = new Ball();

    public function Main() {
      //位置を初期化
      posX=0;
      posY=0;
      speedX = 4;
      speedY = 2;
      //ムービクリップを画面に表示
      this.addChild(ball);
      //イベントリスナーを登録する
      this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }

    function enterFrameHandler(event:Event):void {
      //座標を更新
      posX+=speedX;
      posY+=speedY;
      //更新した座標をボールのプロパティに適用
      ball.x=posX;
      ball.y=posY;
    }
  }
}

条件分岐:画面の端にきたら反対側の端へ

現状では画面の端からボールがはみ出ても、そのまま画面の外に向かって進みつづけ、ずっと見えない架空の画面外を進みつづけてしまいます。では、この状態を避けるために、画面の端にきたら反対側の端から出現するようにできないでしょうか。

そのために、常にENTER_FRAMEのイベントハンドラ内でボールの座標を監視して、もし画面の外に出たらその瞬間にボールを片方の端に移動するという処理を加えてみます。

AS3のプログラムで「もし〜ならば、…せよ」というような条件分岐を実現するには、if文という構文を使用します。if文は下記のような書式になっています。

画面からはみ出たら反対側から出現というのを、条件に分けて列挙すると次のようになるでしょう

  1. 左:(条件)もし x座標が0より小さくなったら → (処理) x座標を画面の幅の座標に
  2. 右:(条件)もし x座標が画面の幅の座標より大きくなったら → (処理) x座標を0に
  3. 上:(条件)もし y座標が0より小さくなったら → (処理) y座標を画面の高さの座標に
  4. 下:(条件)もし y座標が画面の高さの座標より大きくなったら → (処理) y座標を0に

AS3では、画面の幅と高さは次の式で取り出すことが可能です。

  • 画面の幅: stage.stageWidth
  • 画面の高さ: stage.stageHeight

以上のことを踏まえて、下記のようなコードを作成しましょう。

package {
  import flash.display.Stage;
  import flash.display.Sprite;
  import flash.events.Event;

  public class Main extends Sprite {

    //変数を宣言
    var posX:Number,posY:Number;//位置
    var speedX:Number,speedY:Number;//速度
    //ムービークリップをインスタンス化
    var ball:Ball = new Ball();

    public function Main() {
      //位置を初期化
      posX=0;
      posY=0;
      speedX=4;
      speedY=2;
      //ムービクリップを画面に表示
      this.addChild(ball);
      //イベントリスナーを登録する
      this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }

    function enterFrameHandler(event:Event):void {
      //座標を更新
      posX+=speedX;
      posY+=speedY;
      //更新した座標をボールのプロパティに適用
      ball.x=posX;
      ball.y=posY;
      //画面の端に来たら反対側から出現
      //1.左
      if (posX<0) {
        posX=stage.stageWidth;
      }
      //2.右
      if (posX>stage.stageWidth) {
        posX=0;
      }
      //3.上
      if (posY<0) {
        posX=stage.stageHeight;
      }
      //4.下
      if (posY>stage.stageHeight) {
        posY=0;
      }
    }
  }
}

画面の端でバウンドする

では、次に画面の端で反対側から出現するのではなく、バウンドするように改造してみましょう。

バウンドするという動作は、ボールのスピードの方向が反転するということを意味します。X軸方向のスピードが反転する際には、speedXが、-speedXに、Y軸方向のスピードが反転する際には、speedYが、-speedYになります。実際にプログラムで表現してみましょう。

package {
  import flash.display.Stage;
  import flash.display.Sprite;
  import flash.events.Event;

  public class Main extends Sprite {

    //変数を宣言
    var posX:Number,posY:Number;//位置
    var speedX:Number,speedY:Number;//速度
    //ムービークリップをインスタンス化
    var ball:Ball = new Ball();

    public function Main() {
      //位置を初期化
      posX=0;
      posY=0;
      speedX=4;
      speedY=2;
      //ムービクリップを画面に表示
      this.addChild(ball);
      //イベントリスナーを登録する
      this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }

    function enterFrameHandler(event:Event):void {
      //座標を更新
      posX+=speedX;
      posY+=speedY;
      //更新した座標をボールのプロパティに適用
      ball.x=posX;
      ball.y=posY;
      //画面の端に来たら反対側から出現
      //1.左か右
      if (posX<0 || posX > stage.stageWidth) {
        speedX *= -1;
      }
      //2.上か下
      if (posY<0 || posY > stage.stageHeight) {
        speedY *= -1;
      }
    }
  }
}