yoppa.org


Web動画表現技法 2009

第11回:ActionScript 3.0応用:Tweenライブラリを使用したアニメーション表現(2)

今回の内容

前回のTweenMaxを利用したアニメーション表現の応用を行います。前回は1つのムービークリップをステージに配置してTweenを行いましたが、今回は大量のムービークリップを扱う方法について考えていきます。

リンケージ

今回はムービークリップを100個程度ステージに配置して、それをTweenライブラリを使用していろいろ操作する方法について考えていきます。

大量のムービークリップ(100〜1000位のオーダー)を一括して扱おうと考えた際に、最初に直面する課題が、どうやってムービークリップをステージ上に配置するかという点です。手作業でステージに貼っていっていては、とても手間がかかってしまいます。

こうした際に便利な方法として、リンケージという方法があります。リンケージとはライブラリに登録したムービークリップシンボルやサウンドなどのリソースにクラス名をつけ、ActionScriptから動的に読みだしてきるようにする仕組みです。リンケージを用いることで、ムービークリップシンボルを手動でステージに追加しなくても、スクリプト側から配置することが可能となります。リンケージを用いる際には、ライブラリに格納したアイテムであらかじめリンケージの設定をしておく必要があります。

リンケージを設定する

  • 新規にムービークリップを作成
  • ライブラリに表示されたムービークリップシンボルを右クリックして「プロパティ」を選択
  • 「詳細」ボタンを押す
  • 「リンケージ」の欄を設定
    • 「ActionScript用に書き出し」をチェック
    • 「1フレーム目に書き出し」をチェック
    • 「クラス」にクラス名を指定 – 例) Circle
    • 基本クラス「flash.display.MovieClip」はそのままで

この操作により、ActionScriptから、Circleクラスを生成することで新規にステージ上にムービークリップを作成できるようになりました。

ステージにリンケージしたムービークリップを配置する

タイムラインの1フレーム目に下記のスクリプトを記述します。画面の中心にムービクリップが表示されるはずです。

var circle:CircleMc = new CircleMc();
this.addChild(circle);
circle.x = stage.stageWidth / 2;
circle.y = stage.stageHeight / 2;

配置したムービークリップに、イベントリスナーを設定

配置したムービークリップに、マウスのロールオーバーとロールアウトのイベントリスナーを設定してみます。ロールオーバーすると元の2倍の大きさに変化するようにしてみます。変化する際には、TweenMaxを使用してなめらかにTweenするようにします。

import com.greensock.*;
import com.greensock.easing.*;

var circle:CircleMc = new CircleMc();
this.addChild(circle);
circle.x = stage.stageWidth / 2;
circle.y = stage.stageHeight / 2;
circle.addEventListener(MouseEvent.ROLL_OVER, circleRolloverHandler);
circle.addEventListener(MouseEvent.ROLL_OUT, circleRolloutHandler);

function circleRolloverHandler(e:MouseEvent):void
{
    TweenLite.to(circle, 1, {scaleX:3.0, scaleY:3.0, ease:Elastic.easeOut});
}

function circleRolloutHandler(e:MouseEvent):void
{
    TweenLite.to(circle, 1, {scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
}

ムービークリップを複製する

リンケージしたムービークリップを配置する方法を応用して、大量のムービークリップをステージ上に配置してみましょう。配置したムービークリップにはロールオーバーとロールアウトのイベントリスナーが全てに適用されています。

イベントリスナーでTweenを指定する際のターゲット「e.target」というのは、イベントリスナの引数から取得した、そのマウスイベントが発生したシンボルを特定するための工夫です。この方法で、イベントが発生しているターゲットを知ることが可能です。

import com.greensock.*;
import com.greensock.easing.*;

for (var i:int = 0; i<100; i++) {
    var circle:CircleMc = new CircleMc();
    this.addChild(circle);
    circle.x=Math.random()*stage.stageWidth;
    circle.y=Math.random()*stage.stageHeight;
    circle.alpha=0.5;
    circle.scaleX = circle.scaleY = Math.random()+0.2;
    circle.addEventListener(MouseEvent.ROLL_OVER, circleRolloverHandler);
    circle.addEventListener(MouseEvent.ROLL_OUT, circleRolloutHandler);
}

function circleRolloverHandler(e:MouseEvent):void {
    TweenLite.to(e.target, 1, {scaleX:2.0, scaleY:2.0, ease:Elastic.easeOut});
}

function circleRolloutHandler(e:MouseEvent):void {
    var scale:Number = Math.random()+0.2;
    TweenLite.to(e.target, 1, {scaleX:scale, scaleY:scale, ease:Elastic.easeOut});
}

配置したムービークリップを連続してTweenする

ステージに配置したムービークリップの位置を、連続してTweenで移動してみます。移動のための関数、moveTweenを定義しています。この関数内で、Tweenが1回分行います。Tweenが完了すると(onComplete)自分自身の関数が再帰的に呼び出され、連続した移動を実現しています。

import com.greensock.*;
import com.greensock.easing.*;

for (var i:int = 0; i<100; i++) {
    var circle:CircleMc = new CircleMc();
    this.addChild(circle);
    circle.x=Math.random()*stage.stageWidth;
    circle.y=Math.random()*stage.stageHeight;
    circle.alpha=0.5;
    circle.scaleX=circle.scaleY=Math.random()+0.2;
    moveTween(circle);
}

function moveTween(mc:MovieClip):void {
    var moveX=Math.random()*stage.stageWidth;
    var moveY=Math.random()*stage.stageHeight;
    TweenLite.to(mc, Math.random()*2.0+1.0, {
	x:moveX,
	y:moveY,
	ease:Expo.easeOut,
	onComplete:moveTween,
	onCompleteParams:[mc]
    });
}

マウスイベントによる動作の切り替え

連続して移動するムービークリップの移動中に、ステージをマウスダウンするとマウスの周囲に全てのムービクリップが移動してくるように、イベントリスナーを定義します。マウスアップすると連続移動(moveTween)を再開します。全てのムービークリップにTweenやmoveTween関数を設定する必要があることから、ステージにムービクリップを配置する際に、配列「circleArray」に作成したムービクリップを格納しています。

import com.greensock.*;
import com.greensock.easing.*;

var circleArray:Array = new Array();

for (var i:int = 0; i<100; i++) {
    var circle:CircleMc = new CircleMc();
    this.addChild(circle);
    circle.x=Math.random()*stage.stageWidth;
    circle.y=Math.random()*stage.stageHeight;
    circle.alpha=0.5;
    circle.scaleX=circle.scaleY=Math.random()+0.2;
    moveTween(circle);
    circleArray.push(circle);
}

function moveTween(mc:MovieClip):void {
    var moveX=Math.random()*stage.stageWidth;
    var moveY=Math.random()*stage.stageHeight;
    TweenLite.to(mc, Math.random()*2.0+1.0, {
	x:moveX,
	y:moveY,
	ease:Expo.easeOut,
	onComplete:moveTween,
	onCompleteParams:[mc]
    });
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);

function mouseDownHandler(event:MouseEvent):void {
    for (var i:int=0; i<circleArray.length; i++) {
	TweenLite.to(circleArray[i], 5.0, {
	    x:this.mouseX,
	    y:this.mouseY,
	    ease:Elastic.easeOut});
    }
}

function mouseUpHandler(event:MouseEvent):void {
    for (var i:int=0; i<circleArray.length; i++) {
	moveTween(circleArray[i]);
    }
}

色を変化させる

TweenMaxのtint機能を使用して、Tweenするたびに色がランダムに変化するようにしてみます。

import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;
TweenPlugin.activate([TintPlugin]);

var circleArray:Array = new Array();

for (var i:int = 0; i<100; i++) {
    var circle:CircleMc = new CircleMc();
    this.addChild(circle);
    circle.x=Math.random()*stage.stageWidth;
    circle.y=Math.random()*stage.stageHeight;
    circle.alpha=0.5;
    circle.scaleX=circle.scaleY=Math.random()+0.2;
    moveTween(circle);
    circleArray.push(circle);
}

function moveTween(mc:MovieClip):void {
    var moveX=Math.random()*stage.stageWidth;
    var moveY=Math.random()*stage.stageHeight;
    var color:Number = Math.random()*0xffffff;
    TweenLite.to(mc, Math.random()*2.0+1.0, {
	x:moveX,
	y:moveY,
	tint:color,
	ease:Expo.easeOut,
	onComplete:moveTween,
	onCompleteParams:[mc]
    });
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);

function mouseDownHandler(event:MouseEvent):void {
    for (var i:int=0; i<circleArray.length; i++) {
	TweenLite.to(circleArray[i], 5.0, {
	    x:this.mouseX,
	    y:this.mouseY,
	    ease:Elastic.easeOut});
    }
}

function mouseUpHandler(event:MouseEvent):void {
    for (var i:int=0; i<circleArray.length; i++) {
	moveTween(circleArray[i]);
    }
}

マウスの位置を時間をずらしながら追いかける

最後に、マウスの座標を順番をずらしながら、追いかけるサンプルを作成してみましょう。

import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;

TweenPlugin.activate([TintPlugin]);

var circleArray:Array = new Array();
var i:int;

for (i=0; i<50; i++) {
    var circle:CircleMc = new CircleMc();
    this.addChild(circle);
    circle.x=stage.stageWidth/2;
    circle.y=stage.stageHeight/2;
    circle.scaleX = circle.scaleY = i*0.1;
    circleArray.push(circle);
}

setMoveChane();

function setMoveChane() {
    for (i=0; i<50; i++) {
	TweenMax.to(circleArray[i], 10, 
		    {
			x:mouseX, 
			y:mouseY, 
			delay:i*0.1, 
			ease:Elastic.easeOut, 
			overwirte:0
		    });
    }
}

stage.addEventListener(MouseEvent.MOUSE_MOVE, mosemoveHandler);

function mosemoveHandler(e:MouseEvent):void {
    setMoveChane();
}