Flash CS3 Professionalから実装されたActionScript 3.0は、2.0と同じくECMAScript 4に準拠します*1。したがって、スクリプトの構文や文法は、ActionScript 2.0を発展させたものです。しかし、同時にクラスの構成やイベントの扱いが変わり、個々のプロパティやメソッドにも細かな点で違いがあります。
具体的にスクリプトを記述する際には、「ActionScript 3.0コンポーネントリファレンスガイド」 をよく調べないと、意図した動作が実現できない場合も少なくないでしょう。そこで本稿では、従来のActionScript 1.0や2.0で記述したスクリプトをActionScript 3.0で書替えてみることにより、ActionScript 3.0の新たな考え方やこれまでと異なる点を確認していきます。
なおこの記事では、ActionScript 1.0および2.0のスクリプトはFlash Professional 8で記述し、ActionScript 3.0はFlash CS3 Professionalを使用するものとします。
*1 ActionScript 3.0がこれまでとどう変わったかについては、MYCOMジャーナル「AdobeのFlash担当者に訊く - Flash Player 9とActionScript 3.0何が変わる?」をご参照ください。
まず、MovieClipアクションにスクリプトを記述するActionScript 1.0のFlash 5スタイルで、基本のサンプルを作成します。スクリプトを設定したMovieClipインスタンスが、マウスポインタの方向に追随して回転します。

図01-001: マウスポインタを追いかけてインスタンスが回転する
Flash 5スタイルでのアニメーションの処理は、onClipEvent(enterFrame)イベントハンドラアクションに書くのが定石です。MovieClipインスタンスの角度は、MovieClip._rotaionプロパティに度数で設定します。インスタンスから見たマウス座標は、MoiveClip._xmouse/MovieClip._ymouseプロパティで調べることができます。
座標から角度を取得するには、Mathクラスの関数を使って簡単な計算をする必要があります。この処理は使い回しをする想定で、関数(function)getAngle()としてメインタイムラインに定義することにします。このfunction定義は後で行います。すると、マウスポインタを追いかけて回転するインスタンスには、つぎのようなMovieClipアクションを設定すればよいでしょう*2 *3。
// MovieClip: マウスを追いかけて回転するインスタンス
// MovieClipアクション
onClipEvent (load) {
var nDeceleration:Number = 0.2;
}
onClipEvent (enterFrame) {
var nDegree:Number = _root.getAngle(_xmouse, _ymouse);
_rotation += nDegree*nDeceleration;
}
メインタイムラインには、つぎのようなフレームアクションで関数getAngle()を定義します。関数getAngle()は、引数に渡されたxy座標から角度を計算して、度数の値を返します。
座標から角度を取得するには、Math.atan2()メソッドを用います。このメソッドには、注意点がふたつあります。第1に、引 数の順序が、y座標、x座標となることです。第2に、返される角度はラジアン値です。ラジアン値に掛合わせて度数に変換するための比率は、定数(変数) RADIAN_TO_DEGREEとして設定しておくことにします*4。
// タイムライン: _level0
// 第1フレームアクション
var RADIAN_TO_DEGREE:Number = 180/Math.PI;
function getAngle(nX:Number, nY:Number):Number {
var nRadian:Number = Math.atan2(nY, nX);
var nDegree:Number = nRadian*RADIAN_TO_DEGREE;
return nDegree;
}
これで、サンプルスクリプトは完成です。[制御] > [ムーピープレビュー]で、MovieClipアクション(スクリプト01-001)を設定したインスタンスが、マウスポインタを追いかけて回転します。 なお、スクリプト01-001にはイーズアウトのための係数nDecelerationを回転角nDegreeに乗じていますので、減速しながらアニメー ションすることになります(注釈[*3]に引用のドキュメント参照)。
ところが、現行のActionScript 3.0の仕様では、インスタンスにスクリプトを記述することができません。したがって、この処理をフレームアクションに移行する必要があります。
*2 本稿ではActionScript 1.0スタイルのスクリプトについても、ActionScript 2.0の厳密な型指定を用いることにします。変数に対しては、その宣言時にデータ型を指定します。
var 変数名:データ型;
また、関数(function)の引数や戻り値についても、データ型を指定することができます。
function 関数名(引数:データ型):戻り値のデータ型 {
ステートメント;
}
なお、厳密な型指定について詳しくは、Flash 8オンラインヘルプ[ActionScript 2.0の学習] > [データおよびデータ型] > [データ型について] > [データ型の割り当てと厳密な型指定について]、あるいはFlash CS3オンラインヘルプ[ActionScript 3.0のプログラミング] > [ActionScript 言語とシンタックス] > [変数]をご参照ください。
*3 マウスポインタに追随してインスタンスを回転するスクリプトについて詳しくは、F-siteセミナー「MovieClipのターゲットパスとプロパティ」をご参照ください。
*4 Math.atan2()メソッドやラジアン、三角関数などの意義と考え方については、Flash TechNote「角度と座標の計算 - Flash の三角関数を使う」をご参照ください。
ActionScript 3.0は、インスタンスにスクリプトを記述できません。したがって、少なくともフレームアクションにする必要があります。Flash MXでは、イベントハンドラメソッドの採用により、フレームアクションにイベントハンドラが書けるようになりました。そこで、スクリプト01-001を、 このFlash MXスタイルで、フレームアクションとして記述してみましょう。
まずは、スクリプト01-001をカットして、そのまま回転するMovieClipシンボル内の第1フレームにペーストします。フレームアクションには、onClipEvent()イ ベントハンドラアクションが使えません。使えばSWFの書出し時にエラーが発生してしまいます。そこで、onClipEvent(load)と onClipEvent(enterFrame)のふたつのイベントハンドラアクションを、フレームアクションに適したかたちに書替える必要があります。
まず、onClipEvent(load)は最初に呼出されるので、初期設定に用いられます。しかし、フレームアクションでは第1フレームに書きさえすれば、最初に処理されます。したがって、onClipEvent(load)イベントハンドラアクションは({}も含めて)単純に削除し、中身のステートメントをフレームに直接記述します。

図02-001 MovieClipアクションをイベントハンドラメソッドでフレームアクションに移行
つぎに、イベントハンドラアクションonClipEvent(enterFrame)は、イベントハンドラメソッドのMovieClip.onEnterFrameに書替えます。イベントハンドラメソッドというのは、基本的に関数(function)です。したがって、onClipEvent(enterFrame)に替えて、function onEnterFrame()を記述します*5。
イベントハンドラメソッドを使ってフレームアクションに書替えたスクリプトはつぎのとおりです。なお、メインタイムラインに関数getAngle()を定義したフレームアクション(スクリプト01-002)は、そのまま変更はありません。
// MovieClip: マウスを追いかけて回転するインスタンス
// 第1フレームアクション
var nDeceleration:Number = 0.2;
function onEnterFrame():Void {
var nDegree:Number = _root.getAngle(_xmouse, _ymouse);
_rotation += nDegree*nDeceleration;
}
MovieClipのスクリプト02-001とメインタイムラインのスクリプト01-002はともにフレームアクションですので、これでActionScript 3.0に書替えることが可能になります。
*5 イベントハンドラメソッドMovieClip.onEnterFrameを定義するつぎのふたつの記述方法は、基本的に同じ結果になります。
// イベントハンドラメソッドを名前のない関数で設定
this.onEnterFrame = function():Void {
ステートメント;
};
// イベントハンドラメソッドそのものを関数として定義
function onEnterFrame():Void {
ステートメント;
}
前者は名前のない関数、後者が名前のある関数による定義です。ふたつの関数(function)の違いについては、「名前のない関数(匿名関数/関数リテラル)」をご参照ください。
今回のサンプルを最小限ActionScript 3.0で動くように修正するだけでしたら、さほど手間はかかりません。まず、メインタイムラインに関数getAngle()を定義したフレームアクション (スクリプト01-002)は、そのままActionScript 3.0で動作します。
MovieClipのフレームアクション(スクリプト02-001)を修正するには、大きくふたつのポイントがあります。第1は、イベントハンドラ メソッドに替えて、イベントリスナーを使うことです。第2に、プロパティの名前が、ActionScript 3.0では変わりました。これらの修正を施したのが、つぎのスクリプトです。
// MovieClip: マウスを追いかけて回転するインスタンス
// 第1フレームアクション
var nDeceleration:Number = 0.2;
addEventListener("enterFrame", function (eventObject:Event):void {
var nDegree:Number = root.getAngle(mouseX, mouseY);
rotation += nDegree*nDeceleration;
});
まず、イベントリスナーを登録するために、EventDispatcher.addEventListener()メソッドを使います。ActionScript 3.0では、クラスが大規模な階層構造になりました。EventDispatcherクラスはMovieClipクラスの上位階層にあたり、MovieClipの「スーパークラス」と呼ばれます*6。スーパークラスであるEventDispatcherに定義されたaddEventListener()メソッドは、下位階層つまり「サブクラス」であるMovieClipが自らのメソッドと同じように使用できます。
ActionScript 1.0/2.0のイベントハンドラメソッドは、インスタンスに設定すればイベントを受取って処理することができました。しかし、ActionScript 3.0では、予めインスタンスにイベントリスナーを登録する必要があります。インスタンスはイベントを受取ったら、直接その処理はせずに、登録されたリス ナーに扱いを委ねます。これは一見、まだるこしい手続きに感じられるかもしれません。
しかし、たとえば企業でお客様電話窓口があった場合、さまざまな問合せや要望、クレームが寄せられます。それらを、その窓口の部署自らが処理してい たら、とても対応しきれません。通常は、その処理を適切な部署に回付することでしょう。窓口は情報の受付と担当部門への通知に専念することで、企業として さまざまな声を受止め、かつそれらを必要に応じて専門的に処理することが可能になるのです。
イベントリスナーというのは、役割分担に適した仕組みです。大規模なプロジェクトや複雑な処理を、企業の部門分けのように、適切な単位に小分けして 分担できることがその利点です。もっとも、今回のサンプルは、文法的な確認が主眼ですので、ごく単純な場合です。アニメーションを処理するための enterFrameイベントに、リスナーをひとつだけ登録して処理しています。
EventDispatcher.addEventListener()メソッドは、イベントを受取るインスタンスをターゲットとして、つぎのように使用します。このシンタックス(構文)は、バージョン2アーキテクチャ(Flash MX 2004およびFlash 8)のコンポーネントのEventDispatcher.addEventListener()メソッドとほぼ同じです。
インスタンス.addEventListener(イベント, 関数);
スクリプト03-001で、インスタンスはフレームアクションを設定しているMovieClip自身ですから、省略しています(thisをターゲットにしても構いません)。イベントは"enterFrame"と、文字列で記述します。関数は、名前のない関数で指定しました*7。このスクリプト03-001の記述方法は、入力の手間を省いた必要最小限の書き方です。後で、もう少し応用しやすく、ミスも防げる記述の仕方をご紹介します。
つぎに、プロパティの名前を修正します。ActionScript 3.0のプロパティには、名前の先頭にアンダースコア「_」がつきません。ですから、ActionScript 1.0/2.0の_rootやMovieClip._rotationプロパティは、DisplayObject.rootおよびDisplayObject.rotationに修正します。また一部には、アンダースコア(「_」)を取るだけではなく、名称の変わったプロパティもあります。MovieClip._xmouseやMovieClip._ymouseプロパティがそれで、DisplayObject.mouseXとDisplayObject.mouseYプロパティに名前が変わります。
| 変更方法 | ActionScript 1.0/2.0*8 | ActionScript 3.0*9 |
|---|---|---|
| 「_」削除 | _root、_alpha、_height、_parent、_rotation、_visible、_width、_x、_y | root、alpha、height、parent、rotation、visible、width、x、y |
| 名称変更 | _xmouse、_xscale、_ymouse、_yscale | mouseX、scaleX、mouseY、scaleY |
表03-001: ActionScript 1.0/2.0からActionScript 3.0へのプロパティ名変更の例
*6 スーパークラスとサブクラスとのつがりを「継承」と呼びます。ActionScript 3.0のMovieClipクラスは、つぎのようにいくつものスーパークラスを経て、EventDispatcherクラスを継承しています。
MovieClip > Sprite > DisplayObjectContainer > InteractiveObject > DisplayObject > EventDispatcher > Object
なお、ActionScriptにおける継承については、「ActionScript 2.0と1.0の継承について」をご参照ください。
*7 名前のない関数については、注釈[*5]に引用した「名前のない関数(匿名関数/関数リテラル)」をご参照ください。
*8 グローバルプロパティの_rootを除いて、MovieClipクラスのプロパティを例として掲げました。同名のプロパティが、他のクラスに存在することもあります。
*9 例として挙げたプロパティは、いずれもDisplayObjectクラスに定義されているものです。DisplayObjectは、MovieClipのスーパークラスになります(注釈[*6]参照)。
前述のスクリプト03-001は、動作するための最小限の記述です。後々の応用や拡張を考えると、不十分な点がふたつあります。それらを考慮して、ActionScript 3.0の標準的なフレームアクションに書替えてみましょう。

図04-001: ActionScript 3.0の標準的なフレームアクションに修正
第1に、このままではイベントリスナーが必要なくなったとき、削除することができません。イベントリスナーを削除するには、EventDispatcher.removeEventListener()メソッドを呼出します。その引数に、削除すべきリスナーとして、EventDispatcher.addEventListener()メソッドに登録してある関数(function)を渡す必要があります。
インスタンス.removeEventListener(イベント, 関数);
ところが、EventDispatcher.addEventListener()に名前のない関数で指定してありますと、どこにも参照が残されていないので、取得しようがありません。そういう訳ですので、EventDispatcher.addEventListenerメソッドに指定するとき、関数には予め名前をつけて定義しておく方が、望ましいということになります。
したがって、イベントリスナーに設定するfunctionを、まず通常の名前のある関数として定義します。定義したタイムライン上では、関数はその名前で参照することができます。ですから、EventDispatcher.addEventListenerメソッドには、引数のイベントリスナーとしてその関数名を渡します。
第2は、importステートメントの記述です。
前節で述べたとおり、「ActionScript 3.0では、クラスが大規模な階層構造になりました」。それらのクラスは、「パッケージ」という機能により、カテゴリー分けされています。パッケージは、ディスクのフォルダ/ディレクトリと同じツリー構造になっていて、パスで表します。ただし、パスの区切り文字はスラッシュ(/)ではなく、ドット(.)です。
たとえば、MovieClipクラスの完全パス表記(「完全修飾クラス名」と呼ばれます)は、flash.display.MovieClipとなります。このflash.displayの部分がパッケージです。ディスク内でファイルを分類・整理して格納するフォルダと同じ役割を、このパッケージが果たします。パッケージのクラスを使うためには、スクリプトの冒頭でimportステートメントを記述して、パッケージ(flash.display)とクラス名(MovieClip)をドット(.)で結んだ「完全修飾クラス名」(flash.display.MovieClip)の宣言が必要です。
import 完全修飾クラス名;
前述のスクリプト03-001では、flash.display.MovieClipクラスの(スーパークラスも含めた)プロパティやメソッドにアクセスしているほか、イベントを管理しそのイベントについての情報を保持するflash.events.Eventクラスも利用しています。したがって、これらのクラスをimportステートメントで、スクリプトの冒頭に宣言する必要があるのです*10。
もっとも、スクリプト03-001は、importステートメントを記述することなく、正しく動作しています。「これは、Flashのタイムラインには、デフォルトで必要なクラスが自動的にimportされるためです」*11。ですから、スクリプトをフレームアクションに記述し、ActionScript定義済みのおもなクラスを使うかぎりにおいて、importステートメントは必ずしも書かなくても構いません。
けれども、フレームアクションでなくクラスを外部ファイルに定義する場合や、ActionScriptに定義されていない自作あるいは他の人が作成したクラスを利用する場合、さらには自動的にimportされる以外のクラスを用いる場合などに、importの必要性を忘れてあわてる可能性があります。そうならないためには、少なくともimport宣言が必要であることをつねに意識すべきで、またそれを徹底するためにあえてimportステートメントを記述することも有効だと思われます。
さらに、もうひとつ追加したいことがあります。EventDispatcher.addEventListenerメソッドの第1引数に渡すイベントです。"enterFrame"という文字列で渡すことは、もちろん誤りではありません。しかし、この値は、Event.ENTER_FRAMEという定数(プロパティ)で指定することができます。
Event.ENTER_FRAME定数には、結局"enterFrame"という文字列が設定されています。ですから、直接文字列で指定した場合と、動作結果は変わりません。しかし、Event.ENTER_FRAMEを使うと、ふたついいことがあります。
第1は、綴りミスでエラーが返されることです。たとえば、すべて大文字でなければいけない定数の記述に、小文字を交えてEvent.Enter_Frameと書くと、SWF書出し時にエラーが発生します。ところが、文字列の場合には、"EnterFrame"と書いても、何のエラーを生じることもなく、ただ単に動かなくなります。
Event.ENTER_FRAME定数を使う利点の第2は、イベントリスナーとして指定した関数に渡される引数のデータ型が明らかになることです。Eventクラスの定数を指定したということは、イベントリスナーは引数としてEventインスタンスを受取ります。ですから、当然引数は、Eventで型指定されます。これがたとえば、マウスクリックを受取りたい場合であれば、イベントはMouseEvent.CLICKで指定します*12。すると、イベントリスナーの関数は、引数をMouseEventで型指定すればよいとわかります。
以上3つの点を考慮してスクリプト03-001を修正すると、つぎのようになります。
// MovieClip: マウスを追いかけて回転するインスタンス
// 第1フレームアクション
import flash.display.MovieClip;
import flash.events.Event;
var nDeceleration:Number = 0.2;
addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(eventObject:Event):void {
var nDegree:Number = MovieClip(root).getAngle(mouseX, mouseY);
rotation += nDegree*nDeceleration;
}
なお、上記スクリプト04-001のリスナー関数enterFrame()本体の第1ステートメント右辺で、DisplayObject.rootプロパティをMovieClip()で括っています。これは、DisplayObject.rootプロパティの戻り値がDisplayObjectで型指定されているからです。DisplayObjectクラスのインスタンスには、ユーザーがカスタム関数を定義することはできません。しかし、そのサブクラスであるMovieClipには、関数の定義が可能です。MovieClip()は、DisplayObjectクラスで型指定された値を、MovieClipクラスのデータに変換する役割を果たします*13。
*10 「ActionScript 3.0では、パッケージに定義されたクラスを参照する際には、必ずimportステートメントを記述する必要があります」(F-site「importの使い方が変わった」)。「この仕様は、以前のバージョンのActionScriptとは異なります」(「import指示子」)。ActionScript 2.0では、「import指示子を使わなくても、完全修飾クラス名を使えば、クラスを参照することは可能」でした(前出「importの使い方が変わった」)。
*11 詳しくは、前出注釈[*10]「import指示子」の[訳者注*1]をご覧ください。
*12 マウスイベントについいては、「マウスイベント」をご参照ください。
*13 このようにデータ型を変換することは「キャスト」と呼ばれます。詳しくは、「rootプロパティでメインタイムラインの関数にアクセスできない」をご参照ください。
つぎは、ActionScriptファイルを作成して、クラス定義を行いましょう。まず、スクリプト02-001をもとに、ActionScript 2.0でクラスを定義してみます。
最初に、[ファイル]メニューから[新規]で、[ActionScript (AS) ファイル]を作成します。そして、クラス名を決めます。今回は"MyClass"としましょう。そうしたら、ファイルをこのクラス名(拡張子は.as) で、Flashドキュメント(FLA)ファイルと同階層に保存します。
つぎに、Flashドキュメントファイルに切替えて、回転させるMovieClipシンボルに今作成したクラスを割当てます(クラス定義のスクリプ トは、それが済んでから続けて作成します)。[ライブラリ]パネルでMovieClipシンボルをクリックしたら、パネルのオプションポップアップメ ニューから[プロパティ]を選択します。[シンボルプロパティ]ダイアログボックスが開きますので、[リンケージ]の[アクションスクリプトに書き出し] にチェックをつけ、[識別子]に半角英数字で任意の名前を入力したうえで*14、[AS 2.0クラス]に割当てるクラス名"MyClass"を入力します。

図05-001 [シンボルプロパティ]ダイアログボックスの[AS 2.0クラス]に割当てるクラス名を入力
それでは準備ができましたので、ActionScriptファイルMyClass.asに戻って、ActionScript 2.0クラスを定義します。
| スクリプトの記述場所 | 外部ActionScriptファイル。 |
|---|---|
| ファイル名 | クラス名と同一。拡張子.as。 |
| クラス定義 | classステートメント。 |
| コンストラクタ関数 | クラス名と同一(省略可)。 |
| プロパティ | コンストラクタ関数の前にvar宣言。型指定可能。 |
| メソッド | function定義。引数と戻り値の型指定可能。 |
| 継承 | extendsキーワード。 |
表05-001 ActionScript 2.0のクラス定義
クラスはclassステートメントで始まり、クラス名を記述した後、コードブロック全体を波括弧{}で括ります。コードブロックには、プロパティ(変数)とメソッド(関数)を定義します。クラスには、クラスと同名の関数(function)を必ず定義しなければなりません。これはクラスのインスタンスを作成するときに呼出される特別なfunctionで、「コンストラクタ関数」と呼ばれます*15。
したがって、ActionScript 2.0クラス定義ファイルは、ファイル名とクラス名、およびクラスに定義するコンストラクタ関数名がすべて同一とされ、つぎのようなスタイルを採ります。
// ActionScript 2.0クラス定義ファイル: クラス名.as
class クラス名 {
// プロパティ(変数)宣言
function クラス名() {
// インスタンス生成時の初期化処理
}
// メソッド(関数)定義
}
スクリプト02-001には、ひとつの変数(プロパティ)nDecelerationとひとつの関数(メソッド)onEnterFrameが定義さ れています。基本的にはクラスMyClassのコードブロックに、スクリプト02-001のスクリプトをそっくりそのままカット&ペーストし、 空っぽのコンストラクタ関数を加えれば、ActionScript 2.0クラス定義は完成です。
// ActionScript 2.0クラス定義ファイル: MyClass.as
class MyClass extends MovieClip {
var nDeceleration:Number = 0.2;
function MyClass() {} // 空のコンストラクタ関数
function onEnterFrame():Void {
var nDegree:Number = _root.getAngle(_xmouse, _ymouse);
_rotation += nDegree*nDeceleration;
}
}
ただし、ひとつ追加すべきことがあります。extendsステートメントです。
MovieClipシンボルの[AS 2.0クラス]にMyClassを設定すると、そのインスタンスはMovieClipクラスでなくカスタムクラスMyClassのインスタンスになりま す。そうすると、MovieClipクラスのプロパティやメソッドは使えないことになってしまいます。そうならないためには、MovieClipクラスを ベースとして継承し、そのクラスを拡張(extend)するかたちでプロパティやメソッドを追加することが必要です。そこで用いられるのがextendsステートメントで、その後に指定されたクラス(MovieClip)をスーパークラスとして継承(拡張)することを意味します。
[制御] > [ムービープレビュー]で、ムービーが動作することを確認しましょう。
動作したらさらに、Flashドキュメントのメインタイムライン(_root)に記述したフレームアクション(スクリプト01- 002)も、クラスとして定義します。クラス名は"MyMath"として、Flashドキュメントと同階層にファイル(拡張子.as)を保存します。この フレームアクションも、基本的にクラスMyMathのコードブロックにカット&ペーストするだけです。他のクラスを継承(extends)する必要はありません(コンストラクタ関数の定義は、省略しました*15)。
// ActionScript 2.0クラス定義ファイル: MyMath.as
class MyMath {
static var RADIAN_TO_DEGREE:Number = 180/Math.PI;
static function getAngle(nX:Number, nY:Number):Number {
var nRadian:Number = Math.atan2(nY, nX);
var nDegree:Number = nRadian*RADIAN_TO_DEGREE;
return nDegree;
}
}
ここでも、またひとつだけ追加があります。それは、staticステートメントです。
クラスのメソッド(プロパティも同様)には、ふたつのアクセスの仕方があります。オーソドックスなのは、クラスのインスタンスをnew演算子で作成してから、インスタンスをターゲットにメソッドを呼出すスタイルです。たとえば、Dateクラスを使って、今日の日にちを調べるDate.getDate()メソッドを使用するには、まずDateインスタンスを作成します。
var my_date:Date = new Date(); // Dateインスタンス作成
trace(my_date.getDate()); // 出力: 今日の日にち
もうひとつは、クラスを直接参照してメソッドを呼出すスタイルです。たとえば、Mathクラスのメソッドがその典型です。どちらのスタイルで呼出すかは、それぞれのメソッドによって決まっています。ランダムな浮動小数値を返すMath.random()メソッドは、つぎのようにMathクラスを直接参照して呼出します。
var nRandom:Number = Math.random(); // クラスを直接参照してメソッド呼出し
trace(nRandom); // 出力: ランダムな浮動小数値
今回MyMathクラスに定義するgetAngle()メソッド(関数)は、後者のクラスを直接参照するかたちで、MyMath.getAngle()のスタイルで呼出すことにしました。その場合、関数定義のfunctionステートメントの前にstaticをつける必要があります。このstaticステートメントで宣言したメソッドは、「静的(static)メソッド」とか「クラスメソッド」と呼ばれます。
なお、staticステートメントは、プロパティに対しても用いることができます。RADIAN_TO_DEGREEプロパティは、getAngle()メソッドから参照します。静的メソッド内で参照するプロパティは、static宣言されている必要があります。
メインタイムラインのフレームアクション(スクリプト01-002)をクラス定義(スクリプト05-002)に変更しましたので、スクリプト05- 001のgetAngle()関数呼出しのステートメントは、それに合わせて修正する必要があります。これで、 ActionScript 2.0のクラス定義が完成しました。
// ActionScript 2.0クラス定義ファイル: MyClass.as
class MyClass extends MovieClip {
var nDeceleration:Number = 0.2;
function MyClass() {}
function onEnterFrame():Void {
var nDegree:Number = MyMath.getAngle(_xmouse, _ymouse);
_rotation += nDegree*nDeceleration;
}
}
*14 「識別子」に用いることのできる文字については、「ActionScriptとその基本概念について」の「Word□識別子」をご参照ください。
*15 実際にはクラスにコンストラクタ関数を記述しなくても、クラスは正常に書出されます。「クラスファイル内にコンストラクタ関数を明示的に宣言していない場 合、つまり、クラスと同じ名前の関数を作成していない場合は、コンパイラによって空のコンストラクタ関数が自動的に作成され」るからです(Flash 8オンラインヘルプ[ActionScript 2.0の学習] > [関数とメソッド] > [関数とメソッドについて] > [メソッドと関数の種類について] > [コンストラクタ関数について])。
最後に、ActionScript 3.0のクラス定義を行ってみましょう。まず、ActionScript 3.0でMovieClipのフレームアクションに設定したスクリプト04-001を、ActionScript 3.0クラス定義に書替えます。新規[ActionScript(AS)ファイル]を作成して、クラス名"MyClass"(拡張子.as)で保存しておきます。
準備のためFlashドキュメントファイルに戻って、ActionScript 2.0のクラス定義と同じく、MovieClipシンボルにクラスを割当てます。[ライブラリ]のオプションポップアップメニューから [プロパティ]を選択して、[シンボルプロパティ]ダイアログボックスを開きます。[リンケージ]の[ActionScriptに書き出し]にチェックをつけて、[クラス]に割当てるクラス名"MyClass"を入力します([識別子]は空欄のままで構いません)。

図06-001 [Symbol Properties]ダイアログボックスの[Class]に割当てるクラス名を入力
ActionScriptファイルに切替えて、クラス定義を作成します。ActionScript 3.0も、2.0と同じくclassキーワードでクラスを定義し、クラスと同名のコンストラクタ関数を設定する必要があります。ActionScript 3.0では、さらにpackageキーワードを用いて、「パッケージ」の中にクラスを定義します。「パッケージ」は、クラスをフォルダ/ディレクトリのようにグループ分けする機能です*16。パッケージ名は、指定しないことも可能です。
// ActionScript 3.0クラス定義ファイル: クラス名.as
package [パッケージ名] {
class クラス名 {
// プロパティ(変数)宣言
function クラス名() {
// インスタンス生成時の初期化処理
}
// メソッド(関数)定義
}
}
MovieClipシンボルにクラスを設定する場合には、クラスに対する外部からのアクセスを可能にするための属性キーワードpublicをclassキーワードの前に添える必要があります。また、EventDispatcher.addEventListener()メソッドの呼出しは、初期設定処理として、コンストラクタ内に記述します。回転するMovieClipシンボルに設定するActionScript 3.0クラス定義は、つぎのようになります。
// ActionScript 3.0クラス定義ファイル: MyClass.as
package {
import flash.display.MovieClip;
import flash.events.Event;
public class MyClass extends MovieClip {
var nDeceleration:Number = 0.2;
function MyClass() {
addEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(eventObject:Event):void {
var nDegree:Number = root.getAngle(mouseX, mouseY);
rotation += nDegree*nDeceleration;
}
}
}
[制御] > [ムービープレビュー]で動作が確認できたら、メインタイムラインの関数定義のフレームアクション(スクリプト01-002)を、クラス定義に書替えます。新規 ActionScriptファイルを開いて、クラス名MyMath(拡張子.as)で.flaファイルと同階層に保存します。
packageの中にclass定義を記述するのは、前述ActionScript 3.0クラスの書き方どおりです。また、クラスを参照してメソッドを呼出すためには、static属性キーワードをつけなければならない点は、ActionScript 2.0クラス定義の場合と同じです。メソッドgetAngle()をもつActionScript 3.0クラスMyMathの定義は、つぎのような内容になります。
// ActionScript 3.0クラス定義ファイル: MyMath.as
package {
class MyMath {
static const RADIAN_TO_DEGREE = 180/Math.PI;
static function getAngle(nX:Number, nY:Number):Number {
var nRadian:Number = Math.atan2(nY, nX);
var nDegree:Number = nRadian*RADIAN_TO_DEGREE;
return nDegree;
}
}
}
ひとつ新たなポイントとして、プロパティRADIAN_TO_DEGREEの宣言が、varでなくconstキーワードに書替えられています。スクリプトは、varのままでも、とくに問題なく動作します。ただ、constキーワードで定義されたプロパティは、「定数」(constant)とされるため、一旦設定した値は書替えることができません*17。
スクリプト06-001のroot.getAngle()関数の呼出しを、新たに定義したMyMath.getAngle()メソッドに修正すれば、ActionScript 3.0クラス定義は一応完成です。
// ActionScript 3.0クラス定義ファイル: MyClass.as
package {
import flash.display.MovieClip;
import flash.events.Event;
public class MyClass extends MovieClip {
var nDeceleration:Number = 0.2;
function MyClass() {
addEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(eventObject:Event):void {
var nDegree:Number = MyMath.getAngle(mouseX, mouseY);
rotation += nDegree*nDeceleration;
}
}
}
今回のサンプルでは、MovieClipシンボルは1フレームで、フレームアクションをクラスに書替えましたので、スクリプトもなくなりました。ActionScript 3.0では、MovieClipからタイムラインの機能を取去った、いわばLite版ともいうべきSpriteクラスを実装しました。1フレームのみでフレームアクションの記述がなければ、MovieClipでなくSpriteクラスを継承する方が、つくりは軽くなります*18。
Spriteクラスもflash.displayパッケージに属しますので、スクリプト06-003はコードブロック中のMovieClipをSpriteに書替えるだけで、継承は簡単に修正できます。
// ActionScript 3.0クラス定義ファイル: MyClass.as
package {
import flash.display.Sprite;
import flash.events.Event;
public class MyClass extends Sprite {
var nDeceleration:Number = 0.2;
function MyClass() {
addEventListener(Event.ENTER_FRAME, enterFrame);
}
function enterFrame(eventObject:Event):void {
var nDegree:Number = MyMath.getAngle(mouseX, mouseY);
rotation += nDegree*nDeceleration;
}
}
}
*16「パッケージ」について詳しくは、「package定義キーワード」およびakihiro kamijo「package」をご参照ください。
*17 constキーワードについては、「const定義キーワード」をご参照ください。
*18 Spriteクラスについて詳しくは、「Spriteクラス」およびF-site「new演算子でビジュアルオブジェクトをつくる」、akihiro kamijo「Splite クラスと MovieClip クラス」をご参照ください。