前回はスクリプトを使ってインスタンスの位置を指定するには,インスタンス名を付けて,_xプロパティと_yプロパティの値を設定してあげれば良いということを紹介しました。ということは,インスタンスを動かし続けるには,この_xプロパティと_yプロパティを任意の時間間隔で変更してあげれば良いわけです。

 では,「スクリプトを使って任意の時間間隔でプロパティ変更する」にはどうしたら良いのでしょうか。その方法の一つが「onEnterFrameイベントハンドラ」を利用することです*1。onEnterFrameイベントハンドラはムービークリップに用意されたイベントハンドラです。スクリプトからムービークリップを動かす場合に非常にポピュラーなイベントハンドラですから,使い方をしっかりマスターしてください。

一定時間ごとに発生するイベント

 以前に本連載で,ボタンを押した(あるいは,離した)タイミングで処理を実行する方法として「onPressイベントハンドラ」や「onReleaseイベントハンドラ」を紹介しました。「onEnterFrameイベントハンドラ」はこれらと同じように,あるイベントが発生したときに特定の処理を実行できるようになっています。

 onEnterFrameイベントハンドラが関連付けられているイベントは,「FPS(1秒間に再生するフレーム数)に応じたタイミングごと」,つまり「フレームが再生されるごと」に発生するイベントです。ムービーの再生速度が12FPSであれば,1秒間に12回,onEnterFrameイベントハンドラとして関連付けられた処理が実行されるわけです*2

onEnterFrameイベントハンドラを利用したコード

 では,実際にonEnterFrameイベントハンドラを使ってインスタンスを動かしてみましょう。新規Flashドキュメントを作成し,ステージ上の左端に「star1」という名前のムービークリップインスタンスを配置します(図1*3

図1:インスタンス「star1」を配置

 インスタンスを作成したら,ActionScript用のレイヤーを一つ用意し,次のようにonEntereFrameイベントハンドラを利用したコードを記述します(図2)。

図2:ActionScriptの記述

  _root.onEnterFrame = function(){
    _root.star1._x += 5;
  };

このコードの内容は,「_rootのonEnterFrameイベントハンドラ」に,「function以下の処理を割り当てる」ことです。メイン・タイムラインである_rootは一つのムービークリップとして扱えるので,とりあえずそこのonEnterFrameイベントハンドラに処理を関連付けてみました。手近にあるコンセント(onEnterFrame)に処理を差し込んだというイメージですね。

 ムービープレビューをしてみると,「star1」がだんだん右側へ移動していくことが確認できます(図3)。これは,デフォルトのFPSである12FPSに応じて,1秒間に12回onEnterFrameイベントハンドラの処理が実行され,その処理の中で「star1」の_xプロパティに5ずつ加算しているためです。

図3:onEnterFrameでの移動*4(クリックするとムービーを表示します)

 これで特定の処理を任意の時間間隔で実行させる方法がわかりました。あとはfunction内の処理をいろいろと変更すれば,スクリプトだけでインスタンスを自由に動かすことができます。

処理を独立した関数(function)に切り分ける

 さて,ここでインスタンスの数を三つに増やしてみましょう。「star1」をコピーして「star2」「star3」を作成します(図4*5。この三つのインスタンスを同時に動かすにはどうしたらいいでしょうか。

図4:インスタンスを増やす

先ほどど同じように_rootのonEnterFrameに処理を関連付ける方法で行くと,三つのインスタンスの分だけ処理を記述してあげればよさそうです。

//FPSに応じたタイミングで実行される処理
  _root.onEnterFrame = function(){
    //「star1」の「_x」を5加算
    _root.star1._x += 5;
    //「star2」の「_x」を5加算
    _root.star2._x += 5;
    //「star3」の「_x」を5加算
    _root.star3._x += 5;
  };
実際にムービープレビューをしてみると,三つのインスタンスが動くのを確認できます。

 でも,同じような内容の処理を三つも書くのは少々大変ですね。こういう場合には移動の処理(現在onEnterFrameに割り当てているfunction( ){}の処理)を,独立した関数として定義し,各インスタンスのonEnterFrameイベントハンドラに,その関数を割り当てる方法が有効です。

 具体的にコードを記述すると,以下のようになります(図5)。

図5:移動の処理を独立させたコード

  //移動の際に使用する処理
  function setXPosition() {
    //処理を呼んだインスタンス自身の_xプロパティを5加算
    this._x += 5;
  }
  //それぞれのインスタンスのonEnterFrameに割り当てる
  _root.star1.onEnterFrame = setXPosition;
  _root.star2.onEnterFrame = setXPosition;
  _root.star3.onEnterFrame = setXPosition;

処理を独立した関数として定義するには,

  function 関数名(){
    //処理の内容
  }
という形式でコードを記述します。図5では,「setXPosition」という名前の関数を作成し,その処理の内容として「this._x += 5;」を定義しているわけです。

 図5ではさらにこの関数を,star1,star2,star3のそれぞれのインスタンスのonEnterFrameのイベントに割り当てています。これでそれぞれのインスタンスでenterFrameイベントが発生するたびに,つまり,FPSに合わせたタイミングで,setXPotision関数の内容が実行されるようになります(図6)。

図6:イベントハンドラの割り当て

 ここで,setXPotisionの内容を詳しく見てみましょう。

  this._x += 5;
と,今までの「_root.star1」「_root.star2」といったインスタンス名の代わりに「this」というキーワードが使われています。この「this」には,関数を呼び出したインスタンスへの参照が格納されています。つまり,「star1」から呼び出されたときには,「_root.star1._x += 5」と記述したのと同じ処理になり,「star2」から呼び出されたときには,「_root.star2._x += 5」と記述したのと同じ処理になります。

 イベントハンドラから関数を呼び出す際には,名刺を渡すように「this」に自分自身の名前を彫り込んで渡すのです。受け取った側は,その名刺を頼りに処理を実行しているというわけです。この仕組みのおかげで,インスタンスごとにコードを記述しなくても,一つの関数を作成し,それを個々のインスタンスのイベントハンドラから呼び出して使いまわせるわけです(図7)。

図7:三つのインスタンスを同時に動かす(クリックするとムービーを表示します)

イベントハンドラへ関連付ける関数を変更する

 移動するための関数を独立させて定義しておくのには,もう一つメリットがあります。それは,移動のための処理を,コンセントを抜き差しするように簡単に切り替えられるという点です。

 例えば,次のように三つの関数を作成しておきます。

  function setXPosition() {
    //処理を呼んだインスタンス自身の_xプロパティを5加算
    this._x = (this._x+5)%350;
  }
  function setYPosition() {
    //処理を呼んだインスタンス自身の_yプロパティを5加算
    this._y = (this._y+5)%150;
  }
  function setXYPosition() {
    //処理を呼んだインスタンス自身の_x,_yプロパティを5加算
    this._x = (this._x+5)%350;
    this._y = (this._y+5)%150;
  }
こうしておいて,任意のボタンを押したタイミングで各インスタンスのonEnterFrameイベントハンドラに割り当てる処理を変えるようにすれば*6,動きを簡単に変更できますね(図8)。

図8:動きの処理を切り替える(クリックするとムービーを表示します)

 onEnterFrameに関連付けられた処理を外すには,「deleteステートメント」を使用して

  delete star1.onEnterFrame
というコードを記述します*7。これで処理の割り当ての切り替えと処理の停止も自由自在です。

 今回はonEnterFrameイベントハンドラを使って,一定の時間間隔でインスタンスを移動させる方法を紹介しました。さらに,関数を使って,複数のインスタンスを動かす方法も解説しました。しかし,すべてのインスタンスの移動が同じようでは面白みに欠けます。そこで次回は,インスタンスごとに移動スピードや移動の方向などを変える処理にチャレンジしてみましょう。


*1 もう一つはsetInterval関数を利用する方法です。JavaScriptなどに慣れてる方にとってはこちらのほうがおなじみかもしれません。

*2 ただし,あまりにFPSの値が大きすぎると,期待している回数の処理が行われないことがあります。

*3 シンボル名ではなく,インスタンス名というところに注意しましょう

*4 図3のムービーでは,「右端に行ったら左端から移動し直す」ために少しコードに手をくわえています。具体的には

  _root.star1._x = (_root.star1._x + 5) % 350」
として,5を加算後に350で割った剰余の値に_xプロパティを変更しています。こうしておけば_xプロパティの値は350を超えると0に近い値へと戻ってくれます。

*5 コピーしたインスタンスの色は「カラー調整」フィルタで変更しています。フィルタ機能が使えない場合には「カラースタイル」で色味を変更することができます。

*6 ボタンの「onPressイベントハンドラ」や「onReleaseイベントハンドラ」を使うのでしたね。

*7 「star1.onEnterFrame = null」と,nullを代入して無効にする方法もあります。