Starlingフレームワークには、スクリプトでトゥイーンアニメーションを行うstarling.animation.Tweenクラスが備わっています。ActionScript 3.0に定義済みのfl.transitions.Tweenクラスとは少し使い勝手が違います。StarlingフレームワークのTweenクラスを用いたアニメーションについてご説明します。
まず、トゥイーンアニメーションさせるインスタンスを、ステージに置かなければなりません。今回は、[ライブラリ]のビットマップからTextureオブジェクトをつくり、それをImageインスタンスに入れてStarlingルートクラスの子に加えます。そのため、[ライブラリ]のビットマップには、予めクラス(Pen)を定めておきます(図001)。
図001■[ライブラリ]のビットマップにクラスを設定
Flashムービー(FLA)ファイルには、メインタイムラインにつぎの3行のフレームアクションを書きます。そして、Starlingルートクラス(MySprite)を以下のように定めれば、[ライブラリ]のビットマップイメージを納めたImageインスタンスがステージの左端に描かれます(図002)。これらのスクリプトについて詳しくは、本連載第1回「Starlingフレームワークで書く初めてのアニメーション」をお読みください。
// フレームアクション: メインタイムライン import starling.core.Starling; var myStarling:Starling = new Starling(MySprite, stage); myStarling.start();
// ActionScript 3.0クラスファイル: MySprite.as package { import starling.display.Sprite; import starling.display.Image; import starling.textures.Texture; import starling.events.Event; import flash.display.BitmapData; public class MySprite extends Sprite { private var instance:Image; public function MySprite() { addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(eventObject:Event):void { var myBitmapData:BitmapData = new Pen(); var myTexture:Texture = Texture.fromBitmapData(myBitmapData); instance = new Image(myTexture); instance.pivotX = instance.width / 2; instance.pivotY = instance.height / 2; instance.y = stage.stageHeight / 2; addChild(instance); } } }
図002■[ライブラリ]のビットマップイメージを納めたインスタンスがステージ左端に描かれた
StarlingフレームワークのTweenクラスで、ごく簡単なアニメーションを定めましょう。手順は大きく、つぎの3つになります。
トゥイーンのアニメーションを設定するには、まずTweenクラスのコンストラクタメソッドでTweenインスタンスをつくります。引数は3つで、アニメーションさせるインスタンスとその時間、およびイージングの指定です。イージングはTransitionsクラスの定数から選びます(デフォルト値はイージングのない等速のTransitions.LINEAR
)。
new Tween(インスタンス, 時間, イージング);
つぎに、アニメーションさせるプロパティに応じたメソッドを呼出します。ここでは、インスタンスの位置を右端に動かします。xy座標を移動させるメソッドはTween.moveTo()
で、引数ふたつが移動する先のxy座標です。
Tweenオブジェクト.moveTo(x座標, y座標)
そして、アニメーションを始めます。これがTweenクラスのメソッドではありません。StarlingオブジェクトがもつJugglerオブジェクトを用いるのです。静的プロパティStarling.juggler
で参照したJugglerオブジェクトに、Juggler.add()
メソッドでTweenインスタンスを加えます。Jugglerオブジェクトは、本連載第2回「Starlingフレームワークでスプライトシートを使う」04「スプライトシートに書出したフレームアニメーションをインスタンスで再生する」でご紹介しました。
Starling.juggler.add(Tweenオブジェクト)
以上の3つの手順を済ませると、インスタンスにイージングのかかった動きが加えられます。前掲Starlingルートクラス(MySprite)を書替えた後に掲げるスクリプト001は、ステージ左端に置いたインスタンスを右端までトゥイーンアニメーションさせます(図003)。イージングは、トゥイーンの初めと終わりに弾力のある変化を与えるTransitions.EASE_IN_OUT_ELASTIC
にしました。
import
宣言には、TweenインスタンスをつくるのにTweenとTransitionsクラス、Jugglerオブジェクトを使うためにStarlingクラスが加わります。
import starling.core.Starling; // ...[中略]... import starling.animation.Tween; import starling.animation.Transitions;
そして、前述の3つのトゥイーンを定める手順は、新たなメソッド(setTween())で行いました。これは、初期化のメソッド(initialize())から呼出しています。
private function initialize(eventObject:Event):void { // ...[中略]... setTween(); } private function setTween():void { var myTween:Tween = new Tween(instance, 7, Transitions.EASE_IN_OUT_ELASTIC); myTween.moveTo(stage.stageWidth - instance.width / 2, instance.y); Starling.juggler.add(myTween); }
// ActionScript 3.0クラスファイル: MySprite.as
package {
import starling.core.Starling;
import starling.display.Sprite;
import starling.display.Image;
import starling.textures.Texture;
import starling.events.Event;
import starling.animation.Tween;
import starling.animation.Transitions;
import flash.display.BitmapData;
public class MySprite extends Sprite {
private var instance:Image;
public function MySprite() {
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(eventObject:Event):void {
var myBitmapData:BitmapData = new Pen();
var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
instance = new Image(myTexture);
instance.pivotX = instance.width / 2;
instance.pivotY = instance.height / 2;
instance.y = stage.stageHeight / 2;
addChild(instance);
setTween();
}
private function setTween():void {
var myTween:Tween = new Tween(instance, 7, Transitions.EASE_IN_OUT_ELASTIC);
myTween.moveTo(stage.stageWidth - instance.width / 2, instance.y);
Starling.juggler.add(myTween);
}
}
}
前掲スクリプト001では、座標のプロパティをトゥイーンしました。けれど、ひとつのTweenインスタンスに異なるプロパティを定めて、同時にトゥイーンすることもできます。アルファはTween.fadeTo()
、伸縮率にはTween.scaleTo()
というメソッドが備わっています。その他のプロパティも、Tween.animate()
メソッドの引数に指定してトゥイーンアニメーションできます(表001)。
トゥイーンを定めるメソッド | 引数 | トゥイーンされるプロパティ |
animate(property:String, targetValue:Number):void |
property − トゥイーンするプロパティを定める文字列。 targetValue − トゥイーンが達するプロパティ値。 |
第1引数で定めたプロパティ。 |
fadeTo(alpha:Number):void | alpha − トゥイーンが達するアルファ値(0〜1.0)。 | alpha |
moveTo(x:Number, y:Number):void |
x − トゥイーンが達するx座標値。 y − トゥイーンが達するy座標値。 |
xとy |
scaleTo(factor:Number):void |
factor − トゥイーンが達する垂直と水平伸縮率。 |
scaleXとscaleY |
前掲スクリプト001でトゥイーンするプロパティを増やします。インスタンスのアルファと伸縮率は0.5にして、角度を一周回しましょう。手直しするのは、トゥイーンを定めるメソッド(setTween())です。新たにトゥイーンに加えたいプロパティを、それぞれのメソッドでTweenインスタンスに設定します。
private function setTween():void { var myTween:Tween = new Tween(instance, 7, Transitions.EASE_IN_OUT_ELASTIC); myTween.moveTo(stage.stageWidth - instance.width / 2, instance.y); myTween.fadeTo(0.5); myTween.scaleTo(0.5); myTween.animate("rotation", Math.PI * 2); Starling.juggler.add(myTween); }
書直したStarlingルートクラス(MySprite)が、つぎのスクリプト002です。トゥイーンしたインスタンスは、左端から右端に動くとともに、アルファと大きさが半分になりながら1回転します(図004)。
// ActionScript 3.0クラスファイル: MySprite.as
package {
import starling.core.Starling;
import starling.display.Sprite;
import starling.display.Image;
import starling.textures.Texture;
import starling.events.Event;
import starling.animation.Tween;
import starling.animation.Transitions;
import flash.display.BitmapData;
public class MySprite extends Sprite {
private var instance:Image;
public function MySprite() {
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(eventObject:Event):void {
var myBitmapData:BitmapData = new Pen();
var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
instance = new Image(myTexture);
instance.pivotX = instance.width / 2;
instance.pivotY = instance.height / 2;
instance.y = stage.stageHeight / 2;
addChild(instance);
setTween();
}
private function setTween():void {
var myTween:Tween = new Tween(instance, 7, Transitions.EASE_IN_OUT_ELASTIC);
myTween.moveTo(stage.stageWidth - instance.width / 2, instance.y);
myTween.fadeTo(0.5);
myTween.scaleTo(0.5);
myTween.animate("rotation", Math.PI * 2);
Starling.juggler.add(myTween);
}
}
}
図004■インスタンスが左端から右端に動くとともにアルファと大きさは半分になりながら1回転する異なるトゥイーンが定められたTweenインスタンスを複数つくって、順にアニメーションさせることもできます。そこで、トゥイーンのイージングをいくつか変えてみることにします。
Transitionsクラスには、イージングのないデフォルトの等速(定数Transitions.LINEAR)以外に16のイージングが備わっています。これは下表002のように、値の変わり方が標準・反動・バウンド・弾力の4種類あり、それぞれについてトゥイーンの始まりと終わりにどう変化を加えるか4つずつのバリエーションがあるからです。
変化の加え方は、標準についてご説明すれば、始まりに加速(in)、終わりに減速(out)、始まりに加速しつつ終わりに減速(in-out)、真ん中に向かって減速してそれから加速(out-in)の4つになります。リファレンスのTransitionsクラスのページ初めに16のイージングがグラフで掲げられていますので、併せてご参照ください。
表002■Transitionsクラスのイージングを定める定数変化 | 定数 | |||
in | out | in-out | out-in | |
標準 | EASE_IN | EASE_OUT | EASE_IN_OUT | EASE_OUT_IN |
反動 | EASE_IN_BACK | EASE_OUT_BACK | EASE_IN_OUT_BACK | EASE_OUT_IN_BACK |
バウンド | EASE_IN_BOUNCE | EASE_OUT_BOUNCE | EASE_IN_OUT_BOUNCE | EASE_OUT_IN_BOUNCE |
弾力 | EASE_IN_ELASTIC | EASE_OUT_ELASTIC | EASE_IN_OUT_ELASTIC | EASE_OUT_IN_ELASTIC |
前掲スクリプト002にさらに手を加えて、3つの異なるイージングのトゥイーンで順にアニメーションさせてみましょう。イージングはTransitions.EASE_IN_OUT_ELASTIC
とTransitions.EASE_IN_OUT_BOUNCE
およびTransitions.EASE_OUT_IN_ELASTIC
を選びました。それぞれのイージングごとに、Tweenインスタンスもつくらなければなりません。そこで、3つのTransitionsクラスの定数は、予め(Stringベース型)Vectorオブジェクト(myTransitions)に入れておきます。
private var myTransitions:Vector.<String>; private function initialize(eventObject:Event):void { // ...[中略]... myTransitions = new <String>[ Transitions.EASE_IN_OUT_ELASTIC, Transitions.EASE_IN_OUT_BOUNCE, Transitions.EASE_OUT_IN_ELASTIC ]; // ...[中略]... }
つぎのトゥイーンに切換えるには、前のトゥイーンが終わったことを知らなければなりません。ActionScript 3.0のお約束なら、イベントリスナーで扱うところです。けれども、StarlingフレームワークのTweenクラスではコールバック関数(イベントハンドラ)を使います。TweenクラスにはTween.onComplete
プロパティがあり、予めコールバック関数を定めておくと、トゥイーンが終わったときに呼出されるのです。
イベントハンドラは、トゥイーンを定めるメソッド(setTween())の中で設定します。メソッドは、イージングの定数を納めたVectorオブジェクトにエレメントがあるか確かめたうえで、エレメントの定数を取出します。そして、その定数のイージングでTweenインスタンスをつくったら、トゥイーンの設定を行います。そのとき、Tween.onCompleteプロパティにコールバック関数も定めるのです。その関数は、このメソッド自身になります。
private function setTween():void { if (myTransitions.length) { var myTransition:String = myTransitions.shift(); var myTween:Tween = new Tween(instance, 7, myTransition); // トゥイーンの設定 myTween.onComplete = setTween; Starling.juggler.add(myTween); // ...[中略]... } }
あとは、トゥーンするプロパティをどう決めるかです。アニメーションするインスタンスの位置は右端と左端を、行ったり来たりすることにします。そこで、他のプロパティも右端と左端の値を交互に繰返します。
この場合、各プロパティ値を予めどのようにもっておくかです。考えやすいのは、イージングの定数と同じエレメント数(3)のVectorオブジェクトに、トゥイーンごとの値をエレメントとして納めておくことでしょう。
けれど、ここでは以下のように交互に繰返すふたつの値だけを、Vectorオブジェクト(positionsとratiosおよびradians)のエレメントにしました。そして、使うのがどちらのエレメントかは、インデックスの変数(i)を宣言して定めます。Vectorオブジェクトのエレメントはふたつだけですので、インデックス変数の値は0と1を交互に切換えることになります。
整数0と1を互いに反転するには、ビット単位の排他的論理和演算子^
が使えます[*1]。ビット単位の論理演算は、整数を2進数の桁ごとに計算し、繰り上がりや繰り下がりはありません。変数(i)には整数の1か0を使うとしたとき、1との排他的論理和(i ^= 1)をとると、1は0に0は1に反転します。
private var positions:Vector.<Number>; private var ratios:Vector.<Number> = new <Number>[0.5, 1]; private var radians:Vector.<Number> = new <Number>[Math.PI * 2, -Math.PI * 2]; private var i:uint = 0; // ...[中略]... private function initialize(eventObject:Event):void { // ...[中略]... positions = new <Number>[stage.stageWidth - halfWidth / 2, halfWidth]; // ...[中略]... } // ...[中略]... private function setTween():void { if (myTransitions.length) { var myTransition:String = myTransitions.shift(); var ratio:Number = ratios[i]; var myTween:Tween = new Tween(instance, 7, myTransition); myTween.moveTo(positions[i], instance.y); myTween.fadeTo(ratio); myTween.scaleTo(ratio); myTween.animate("rotation", radians[i]); // ...[中略]... i ^= 1; } }
前掲スクリプト002にこれらの修正を加えたのが、つぎのスクリプト003です。3つの異なるイージングを定めたトゥイーンが、順にアニメーションとして実行されます。
// ActionScript 3.0クラスファイル: MySprite.as
package {
import starling.core.Starling;
import starling.display.Sprite;
import starling.display.Image;
import starling.textures.Texture;
import starling.events.Event;
import starling.animation.Tween;
import starling.animation.Transitions;
import flash.display.BitmapData;
public class MySprite extends Sprite {
private var instance:Image;
private var myTransitions:Vector.<String>;
private var positions:Vector.<Number>;
private var ratios:Vector.<Number> = new <Number>[0.5, 1];
private var radians:Vector.<Number> = new <Number>[Math.PI * 2, -Math.PI * 2];
private var i:uint = 0;
public function MySprite() {
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(eventObject:Event):void {
var myBitmapData:BitmapData = new Pen();
var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
instance = new Image(myTexture);
var halfWidth:Number = instance.width / 2;
myTransitions = new <String>[
Transitions.EASE_IN_OUT_ELASTIC,
Transitions.EASE_IN_OUT_BOUNCE,
Transitions.EASE_OUT_IN_ELASTIC
];
positions = new <Number>[stage.stageWidth - halfWidth / 2, halfWidth];
instance.pivotX = halfWidth;
instance.pivotY = instance.height / 2;
instance.y = stage.stageHeight / 2;
addChild(instance);
setTween();
}
private function setTween():void {
if (myTransitions.length) {
var myTransition:String = myTransitions.shift();
var ratio:Number = ratios[i];
var myTween:Tween = new Tween(instance, 7, myTransition);
myTween.moveTo(positions[i], instance.y);
myTween.fadeTo(ratio);
myTween.scaleTo(ratio);
myTween.animate("rotation", radians[i]);
myTween.onComplete = setTween;
Starling.juggler.add(myTween);
i ^= 1;
}
}
}
}
中級の読者の中にはひとつ疑問をもたれた方もあるかもしれません。前掲スクリプト003のトゥイーンを定めるメソッド(setTween())は、新たなTweenインスタンスをつくってはStarlingオブジェクトのもつJugglerオブジェクトにJuggler.add()
メソッドで加えています。トゥイーンアニメーションが正しく行われるのは、Tweenインスタンスの参照がJugglerオブジェクトによって保たれているからです。では、トゥイーンが済んだら、そのTweenインスタンスをJugglerオブジェクトから除かないと、参照がメモリに残ったままにならないでしょうか。
池上彰さんではありませんが、それは「いい質問です」。Tweenインスタンスのトゥイーンアニメーションが終わると、Jugglerオブジェクトはいわれなくてもインスタンスを除いてくれます[*2]。Tweenインスタンスがほかに参照されていなければ、やがて(ガベージコレクションにより)メモリから消え去ります。もちろん、Tweenインスタンスがアニメーションさせたオブジェクト(DisplayObject)は、そのかぎりではありません。表示リストから外したり、さらにリスナーその他の参照を消すことはスクリプトの書き手の責任です。
[*1] ビット単位の論理演算は2進数で考えますので、結果は0と1の4とおりの組合わせで示せます。ビット単位の排他的論理和演算子
[*2] Starling Wiki「The Starling Manual」の「Animation」で解説された「The Juggler」には、つぎのように述べられています(筆者訳)。 TweenはJugglerからいちいち消さなくて構いません。トゥイーンが済んでしまえば、それらは自動的に除かれます。 |