ActionScript 3.0で始めるオブジェクト指向スクリプティング

第22回 MovieClipシンボルにクラスを定義する

この記事を読むのに必要な時間:およそ 6.5 分

フレームアクションをクラスに移行する

これで必要な知識は学んだので,第17回「3D風に回転するアニメーション」で作成したスクリプト3を,フレームアクションからカスタムクラスの定義に書替えてみよう。フレームアクションに最小限の修正をしてクラス定義に直したのが以下のスクリプト1だ。

第1に,import宣言は,MovieClipクラスだけでなく,Event(flash.events.Event)およびBlurFilter(flash.filters.BlurFilter)クラスについても必要になる。第2に,クラス定義本体に記述するのはvar宣言したプロパティとfunctionで定義するメソッドのみなので,イベントリスナーを設定するステートメントは,コンストラクタメソッド内に置いた。第3に,アクセス制御の属性は,コンストラクタメソッドをpublicとした以外は,すべてprivateで指定した※4⁠。

スクリプト1 インスタンスを3D風に回転させるEllipticMotionクラスの定義

// ActionScript 3.0クラス定義ファイル: EllipticMotion.as
// 回転するMovieClipシンボルの[クラス]に設定
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.filters.BlurFilter;
  public class EllipticMotion extends MovieClip {
    private var nDegree:Number = 0;
    private var nRadian:Number = 0;
    private var nSpeed:Number = 5;
    private var nDegreeToRadian:Number = Math.PI / 180;
    private var nCenterX:Number = stage.stageWidth / 2;
    private var nCenterY:Number = stage.stageHeight / 2;
    private var nRadiusX:Number = 100;
    private var nRadiusY:Number = 50;
    private var nCos:Number = Math.cos(nRadian);
    private var nSin:Number = Math.sin(nRadian);
    public function EllipticMotion() {
      addEventListener(Event.ENTER_FRAME, xMoveX);
      addEventListener(Event.ENTER_FRAME, xMoveY);
      addEventListener(Event.ENTER_FRAME, xScale);
      addEventListener(Event.ENTER_FRAME, xBlur);
      addEventListener(Event.ENTER_FRAME, xUpdate);
    }
    private function xMoveX(eventObject:Event):void {
      x = nCenterX + nCos * nRadiusX;
    }
    private function xMoveY(eventObject:Event):void {
      y = nCenterY + nSin * nRadiusY;
    }
    private function xScale(eventObject:Event):void {
      scaleX = scaleY = xGetIndexZ(0.8,1);
      scaleX *= xGetIndexZ();
    }
    private function xBlur(eventObject:Event):void {
      var nBlur:Number=xGetIndexZ(4,0);
      var myBlur:BlurFilter=new BlurFilter(nBlur,nBlur/2);
      filters=[myBlur];
    }
    private function xUpdate(eventObject:Event):void {
      nDegree+=nSpeed;
      nDegree = (nDegree%360+360)%360;
      nRadian=nDegree*nDegreeToRadian;
      nCos=Math.cos(nRadian);
      nSin=Math.sin(nRadian);
    }
    private function xGetIndexZ(nMin:Number=-1, nMax:Number=1):Number {
      var nIndexZ:Number = (nMax-nMin)*(nSin+1)/2+nMin;
      return nIndexZ;
    }
  }
}

上記スクリプト1のクラスEllipticMotionを設定したMovieClipインスタンスは,まずはステージに予め置いて試してみよう(ダウンロードしたサンプルを利用している人は,フレームアクションは削除しておくことを忘れないように⁠⁠。[ムービープレビュー]を見ると,フレームアクションと同じように,インスタンスが3D風に回転する図7⁠。

図7 クラスを設定したMovieClipインスタンスは3D風に回転する

図7 クラスを設定したMovieClipインスタンスは3D風に回転する

それではつぎに,MovieClipインスタンスをステージからは消して,スクリプトで動的に作成してみる。インスタンスをコンストラクタメソッドで生成し,DisplayObjectContainer.addChild()メソッドに渡せばよかった。

var my_mc:EllipticMotion = new EllipticMotion();
addChild(my_mc);

ところが,以下のランタイムエラーが発生してしまう。このエラーは,オブジェクトを参照してプロパティにアクセスしようとしているステートメントで,実際にはオブジェクトが存在しない場合に起こる※5⁠。しかも,たちの悪いことに,何行目のステートメントが問題なのかを具体的に知らせはてくれない。

TypeError: Error #1009: nullのオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。 

結論からいうと,原因はクラスEllipticMotionにおけるプロパティのvar宣言で,DisplayObject.stageプロパティにアクセスしている点にある図8⁠。[ヘルプ]の[ActionScript 3.0言語およびコンポーネントリファレンス]でDisplayObject.stageプロパティの項を見ると,つぎのような注意書きがある。

表示オブジェクト(野中注: DisplayObjectインスタンス)が表示リストに追加されていない場合,stageプロパティはnullに設定されます。

図8 表示リストに加わる前はDisplayObject.stageプロパティがnull

図8 表示リストに加わる前はDisplayObject.stageプロパティがnull

※4)
アクセス制御の属性にどれを指定してよいかわからないときには,取りあえずprivateにしてみよう。それで問題があったら,適切な属性に変えればよい。なお,コンストラクタメソッドは,public属性しか指定できなかった(第18回「カスタムクラスを定義する」プロパティとメソッドを定義する表1「アクセス制御の属性キーワード」参照)。
※5)
エラーメッセージに示されたnullは,オブジェクトが設定されるはずのデータに,実際には値がない場合に返される特別な値だ。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書