chapter1-3

インタラクティブな動きを学ぶ

アニメーションを作る

まずは、ActionScript を使ってアニメーションさせるということを考えていきます。Flashでは、パラパラマンガと同じしくみでアニメーションを実現しています。複数の静止画を、ある間隔をおきながら次々と見せることで、動いているように見せるわけです。

それぞれの静止画をフレームといい、1 秒間に何フレーム表示(再生)するかをフレームレートで表します。パラパラマンガの1 ページ= 1 フレーム、パラパラ送る速さ=フレームレートです。フレームレートは、1 秒当たりのフレーム数(frames per second)を略して「fps」という単位で表します。テレビや映画もアニメーションということができます。アナログテレビのフレームレ―トは約30fps、デジタルフルハイビジョンは60fps、フィルム映画は24fpsです。fps の数字が大きいほど滑らかな動きに見えることになります。

たとえば、10 秒間、30fps のアニメーションを作る場合、1 フレームめから300 フレームめ+まで、300 個の静止画像を用意する必要があります。この1 フレームめから、アニメーションの進行に従って進んでいく時間軸を、Flash では「タイムライン」と呼びます。

図2 Flash IDEのタイムライン

300 フレーム分の画像を1 つひとつ作成するのは手間がかかりますが、Flash IDE などのアニメーションツールでは1 フレームめと10 フレームめのみに画像を用意して、その間の2 .9 フレーム間は滑らかに補完するということがアニメーションツールの機能として組み込まれている場合が多いです。このことをFlash ではトゥイーンと呼びます。

この補完という効率化の方法に対して、1 フレームめの静止画像をフレームごとにどのように動かすか、その動かし方をプログラミング言語で定義しておくことで、効率化する方法もあります。ここでは後者の方法で、ActionScript を使ってフレームアニメーションを作成します。

フレームレート

通常のFlash コンテンツでは、フレームレートを25~30fps に設定するので、つまり1 秒間に30 回程度画面を書き換えることになります。

フレームレートを上げれば上げるほど、よりアニメーションがなめらかになりますが、マシンにかかる負荷も上がります。また、ある程度以上はマシンの処理が追いつかなくなるので、大体これくらいの値に設定するとよいといわれています。

1 フレームごとに移動させる

まずは、サンプルを見てみましょう。010301 を実行すると、円が中央から右下に斜めに下降するアニメーションが再生されます。

コード01 円を動かす 010301

package {
    import flash.display.*;
    import flash.events.Event;

    [SWF(frameRate="30", width="465", height="465")]
    public class MyFirstAnimation extends Sprite {
        private var _circle:Circle;

        public function MyFirstAnimation() {
            // クラスCircleのインスタンスを作る
            _circle = new Circle(10);
            // 半透明(不透明度25%)
            _circle.alpha = 0.25;
            _circle.vx = 3;
            _circle.vy = 4;

            // 最初の位置をwonderflの画面の中央にセット
            _circle.x = 465 / 2;
            _circle.y = 465 / 2;
            // 表示リストに追加
            addChild(_circle);

            // 1フレーム毎に実行する処理にenterFrameHandlerを追加する
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }

        // フレーム毎に行われる処理 [25行目で登録される]
        private function enterFrameHandler(e:Event):void {
            // 1フレーム分動かす
            _circle.move();
        }
    }
}

import flash.display.Sprite;

class Circle extends Sprite {
    public var vx:Number;
    public var vy:Number;
    public var radius:Number;
    // コンストラクタ
    public function Circle(_radius:Number, _fillColor:uint = 0x000000) {
        // 塗り_fillColor, 半径_radiusの円
        graphics.beginFill(_fillColor);
        graphics.drawCircle(0, 0, _radius);
        graphics.endFill();
        // 半径の大きさをパブリックな変数に保存しておく
        radius = _radius
    }
    // 1フレーム分の動き
    public function move():void {
        x += vx;
        y += vy;
    }
}

図3 円が下降していく

53 行めで、フレームレート(単位はfps)と表示するステージのサイズ(単位はpixel)を指定しています。

[SWF(frameRate="30", width="465", height="465")]

このプログラムの大事なところは25 行めです。

// 1フレーム毎に実行する処理にenterFrameHandlerを追加する
addEventListener(Event.ENTER_FRAME, enterFrameHandler);

Event.ENTER_FRAME はフレームが更新されるたびに発行されるイベントです。イベントについて、詳しくは次節で取り上げますが、何かの処理(動作)のきっかけとして使います。たとえば、「マウスがクリックされたら、色を反転する」といった処理の場合、「マウスがクリックされる」というイベントが「色を反転する」という処理のきっかけになります。

イベントをきっかけに何かの処理を実行する(=関数を呼び出す)には、イベントリスナーという関数を使って、きっかけとして捕らえたいイベントの発生を待ち受けておく必要があります。ここでは、イベントリスナー関数addEventListener() を使っています。

addEventListener() は次のように記述します。

addEventListener(監視するイベント名, イベントを処理する関数)

Event.ENTER_FRAME が発行されたらenterFrameHandler を実行するということになります。addEventListener によってイベントと結び付けられた関数のことをイベントハンドラと呼びます。1 つのイベントに対して複数のイベントハンドラを登録することもできます。一般には、イベントが発行されたとき、そのイベントに対して登録されているイベントハンドラのリストが実行されます。

注意しなければならないのは、イベントを処理する関数は必ず、イベントを引数に取る1引数の関数でなければなりません。ここでは、enterFrameHandler は、

private function enterFrameHandler(e:Event):void {
    _circle.move();
}

というふうに定義されています。引数としてe、「:」に続けて引数の型(クラス)をEvent としています。たとえ、この引数を使わなくとも

private function enterFrameHandler():void {
    _circle.move();
}

とすると、コンパイルエラーになってしまうのでご注意を。

以下を定型文として覚えるとよいでしょう。

// フレーム毎の処理を登録
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
private function enterFrameHandler(e:Event):void {
    // 1フレームごとにやりたい処理をここに書く
}

つまりコード01 の場合、1 フレームごと(fps が30 の場合、1 フレームは1 / 30 = 0.033 秒ですから0.033 秒間隔)にイベントを処理する関数enterFrameHandler が実行され、円を移動するアニメーションを表示しています。円を移動する実際の処理はmove() に定義され、enterFrameHandler ではmove() を呼び出しています。

public function move():void {
    x += vx;
    y += vy;
}

move では、x 座標の値をvx、y 座標の値をvy だけ動かします。v は速度です。このvx とvyは、それぞれ次のように指定しています。

_circle.vx = 3;
_circle.vy = 4;

この続きは書籍のほうでご覧いただけます

ここでは「クラス」を使って車をアニメーションさせる方法や、「マウスイベント」をきっかけにしたクリックやドラッグといったインタラクションについて触れています。

より詳しい内容をご覧になりたい方は書籍の方をお買い求めください。

ブラウザで無料ではじめるActionScript 3.0 ―It's a wonderfl world―

AS で作る概念のタイムライン

タイムラインは、始点から終点までが何秒で構成されているかという概念です。Flash IDEでは実際にGUI で、フレーム、キーフレーム、始点、終点を表し編集することができます。ここでは、これをActionScript で再現してみます。

前述の2 つの時間の単位を使いながら、「ターゲットがstart からend までn 秒(or n フレーム)で変化する」というタイムライン的な考え方をサンプルを交えて解説していきたいと思います。

まず、始点と終点を作りましょう。「何が変化するのか」を決め、次に変化する前の値(start)と変化後の値(end)を決めます。たとえば、「x を変化させる」と決めた場合、

var startX:Number=sprite.x
var endX:Number=sprite.x+100

とするわけです。

これは、x やy のような座標系だけでなく、角度(rotation)、大きさ(width, height)、拡大率(scaleX, scaleY)、色(aplha, RGB)、filter のプロパティなど、何らかのプロパティや変数で数値(Number 型, int 型, uint 型)であれば、どんな場合にも適用できます。

よく色の指定で入力する0xFF0000 のような表記も、16 進" 数" なので数値です。

var startColor:uint=0x000000 //黒から
var EndColor:uint=0xFFFFFF //白まで

このようにstart からend までを決めたら、次は何秒でどうなるか、何フレームでどうなるかを設定します。つまり、アニメーションを何コマで再生しきるのか、再生時間を決めてしまいます。再生時間は表現にもよりますが、今回は「シュっとした動き」を例に組んでみたいと思います。

シュっとした感じなので、感覚で0.8 秒程度とし、仮にx を0 からwonderfl ステージサイズ465px まで移動するとします。fps を30fps とすると、0.8 秒なので24 フレーム、つまり24 コマのアニメーションということがわかります。さらに緩急をつけるためにイージングの処理を入れます。

イージングとは、アニメーションの中で動きを徐々に加速したり減速させることを指します。通常、30 コマでx:0 からx:60 まで移動するというアニメーションを作るとき、通常は1 フレームでx が2 ずつ増えていくので0,2,4,6,8,10,... と一定の速度で動いていきます。これに対してイージングは同じ時間枠・同じ移動距離でも、その処理内容によって、動きに強弱をつけることができます。

今回のサンプルでは、最も簡単な(終点ー始点)×比率という式を使っています。次のコード14 がその部分です。

コード14 イージングの処理 010307

private function generateAnimationFrames():Array{
    var tmp:Array=new Array();//出力用の一時的な配列
    var easeRatio:Number=0.2;//イージングの比率
    var tmpX:Number=startX;
    for(var i:int=0; i < frameCountLimit;i++){
        tmpX+=(endX-tmpX)*easeRatio
        tmp.push(tmpX);//各コマのx座標をコマ数だけ計算して配列に追加
    }
    return tmp;
}

この式によって、0 から60 までを0, 30, 45, 52, ... というように、最初の変化を大きく、終わりにいくほど変化が緩やかになる「イーズアウト」と呼ばれる動きの強弱をつけています。

次に、ここまでのタイムライン的な手法をループアニメーションの形へ、さらに、インタラクティブなコンテンツにするため、ユーザーの操作をアニメーションに取り入れる形に変えていきたいと思います。

ここでの変更は、終点まできたら始点に戻すという単純なものです。ActionScript 的にはstop() のタイミングでframeCount を0 に戻すだけです。始点・終点の概念があれば、ループはさほど難しいものではありません。

コード15 タイムラインをループする 010308

private function render(e:Event):void { //レンダリング用のメソッド
    //現在のフレーム数がframeCountLimit以内なら
    if(frameCount < frameCountLimit){
    ball.x=animationFrames[frameCount];//ballのxに今のコマ数のx座標を代入
    }else{
        //stop();//アニメーション終了
        frameCount=0;
    }
    frameCount++;//再生ヘッドを進める
}

この続きは書籍のほうでご覧いただけます

ここでは、この節で学んだアニメーションをつかって、複数の処理を並行して走らせること(非同期処理)について触れていきます。

より詳しい内容をご覧になりたい方は書籍の方をお買い求めください。

ブラウザで無料ではじめるActionScript 3.0 ―It's a wonderfl world―

▲Page top

wonderfl