リスト3●Keyクラスのイベント・リスナーのテスト用コード
リスト3●Keyクラスのイベント・リスナーのテスト用コード
[画像のクリックで拡大表示]
リスト4●キーを押したタイミングで自機を移動するコード
リスト4●キーを押したタイミングで自機を移動するコード
[画像のクリックで拡大表示]
リスト5●Keyクラスのリスナー・オブジェクトを登録・解除する関数
リスト5●Keyクラスのリスナー・オブジェクトを登録・解除する関数
[画像のクリックで拡大表示]
リスト6●一定の確率で戦闘を発生させるコード
リスト6●一定の確率で戦闘を発生させるコード
[画像のクリックで拡大表示]
リストA●MapChipクラスのコード
リストA●MapChipクラスのコード
[画像のクリックで拡大表示]
図A●<b>リストA</b>のMapChipクラスをシンボルmapChip(リンケージ識別子はSMapChip)に関連付ける
図A●<b>リストA</b>のMapChipクラスをシンボルmapChip(リンケージ識別子はSMapChip)に関連付ける
[画像のクリックで拡大表示]
リスト1●マップにパネルを敷き詰めるコード
リスト1●マップにパネルを敷き詰めるコード
[画像のクリックで拡大表示]
リスト2●自機の移動に関係する変数と関数を定義するコード
リスト2●自機の移動に関係する変数と関数を定義するコード
[画像のクリックで拡大表示]

イベントが発生したタイミングで
指定した処理を実行する

 次に,キーを押したタイミングで自機が移動するようにしましょう。これには「イベント・リスナー」を利用します。イベント・リスナーは,キーが押されたなど特定のイベントが発生したタイミングで,あらかじめ指定しておいた処理を実行する仕組みです。キーボード関連のイベントが発生したときには,Keyクラスのイベント・リスナーを使います。

 イベント発生時に実行する処理は,「イベント発生時にイベントを通知する対象」であるインスタンスに記述しておきます。このインスタンスを「リスナー・オブジェクト」と呼びます。Keyクラスでは,addListenerメソッドを使うことによって,Keyクラスがイベントを通知する対象にするリスナー・オブジェクトを登録できます。

 ユーザーによってキーボード関連のイベントが発生すると,Keyクラスはリスナー・オブジェクトにイベントを通知し,イベントの種類によってあらかじめ決められている名前のメンバーを呼び出します。Keyクラスの場合は,キーを押した(onKeyDown),キーを離した(onKeyUp)の2種類のイベントを通知できます。

 簡単なコードでイベント・リスナーの動作を確認してみましょう。新規にFlashドキュメントを作成し,メインのタイムラインにリスト3[拡大表示]のコードを記述してください。リスナー・オブジェクトkeyListenerを作成し,onKeyDownとonKeyUpの二つのメンバーを追加します。メンバーの内容はここでは,メッセージを表示する関数にしています。次に,リスナー・オブジェクトkeyListenerをKeyクラスのaddListenerメソッドを使用して登録します。これだけです。[ムービープレビュー]で,キーを押したり離したりするたびに,keyListenerのメンバーであるonKeyDownとonKeyUpが呼び出されていることが確認できます。

 この仕組みをマップ上の移動処理に適用します。リスト2[拡大表示]のコードに,リスト4[拡大表示]のような処理を付け加えます。今回は,既存の関数moveMyShipをキーボードが押されたときに実行したいので,onKeyDownの値がmoveMyShipへの参照となるリスナー・オブジェクトkeyListenerを作成し,addListenerメソッドでKeyクラスに登録します。これで,キーを押すたびにmoveMyShipが実行され,マップ上を自由に移動できるようになります。

戦闘やイベント発生時に備える

 移動画面はこれでほぼ完成です。しかし,RPGには移動画面以外に,戦闘画面やイベントを表示する画面があります。Keyクラスにリスナー・オブジェクトを登録しっぱなしでは,ほかの画面の際にも,キー入力に応じて自機が移動してしまいます。

 そこで,リスナー・オブジェクトの登録/解除を切り替える関数chgKeyEvent(リスト5[拡大表示])を作成しておきます。addListenerメソッドでKeyクラスに登録したリスナー・オブジェクトは,removeListenerメソッドで登録を解除できます。関数chgKeyEventでは,引数flgの値がtrueの場合にリスナー登録を行い,falseの場合にはリスナー登録を解除します。すなわち,キー入力による移動を有効にしたい場合はchgKeyEvent(true);と記述し,無効にしたい場合はchgKeyEvent(false);と記述します。

 今回のRPGでは,移動処理が終わったら,一定の確率で戦闘が開始されるようにしてみましょう(リスト6[拡大表示])。関数moveMyShipの末尾に,Math.randomメソッドで得られる乱数の値を使って,一定の確率で戦闘を開始する関数startBattleを呼び出す処理を追加します。戦闘画面は次回に作成するのでとりあえず,「敵が現れた!!」とメッセージを表示してリスナー・オブジェクトの登録を解除し,5秒たったら「戦闘が終了しました」と表示してリスナー・オブジェクトを再登録するだけの処理にしています。

 [ムービープレビュー]で確認してみると,自機を移動時に,一定の確率で戦闘メッセージが表示され,5秒間だけ矢印キーを押しても移動ができない状態となり,5秒後にはまた移動可能となることが確認できるでしょう。

☆     ☆     ☆

 今回はここまでです。配列に指定する値を変更したり,マップの絵を描いたりして,自分なりのマップを作成してみましょう。次回は,複数の敵や味方の情報を管理する戦闘画面の作成方法をご紹介します。

クラスをシンボルに対応付ける

 本文のリスト1[拡大表示]では,シンボルmapChipから作成したインスタンスに,後付けで_typeや_charDepthといった変数(フィールド,プロパティ)を定義しました。これはJavaなどのオブジェクト指向プログラミング(OOP)言語を使用している方にとっては,ちょっと抵抗のある処理だと思います。Javaなどであれば,基本的にクラスで定義したメンバーのみを扱い,あとからホイホイとメンバーを追加することはほとんどありません。

 実はFlash MX 2004(同Professional 2004)にも,通常のOOP言語と同じように「クラス」を定義して利用できる仕組みがあります。クラス側でいろいろな処理を実装できるので,管理が楽になり,変更にも強くなります。普段OOPになじんでいる人は,こちらの方法も試してみてください。

 ActionScriptでクラスを作成する際には,拡張子「.as」のテキスト・ファイルにクラス定義を記述し,クラスパスの通ったフォルダに保存しておきます*A。再利用しないクラスであれば,Flashドキュメントと同じフォルダへと保存しておけば,クラスパスを意識する必要はありません。

 Flash MX Professional 2004は,クラスを定義するための専用エディタを備えています。通常版のFlash MX 2004に専用エディタは付属していないので,メモ帳や秀丸などのテキスト・エディタを使用して記述します。

 ActionScriptでのクラス定義の基本形は,次のようになります*B

class クラス名 [extends 親クラス] {
var 変数名:データ型
function メソッド() {
//処理
}
}
これにならって,マップのパネルを表すクラスMapChipを作成してみましょう(リストA[拡大表示])。

 MapChipクラスはムービークリップ・シンボルに関連付けて使用しますから,extendsでMovieClipクラスを継承します。さらに,_typeと_charDepthの二つの変数(プロパティ)と,移動可能かどうかをブール値で返すcanMoveメソッドを持たせます。コードを記述したら,MapChip.asと名前を付けてFlashドキュメントを格納しているのと同じフォルダに保存します。

 続いて,シンボルとクラスを関連付けます。メニューより,[ウィンドウ]-[ライブラリ](あるいは[Ctrl]+[l])を選択して[ライブラリ]パネルを表示します。mapChipを右クリックして表示されるメニューから[リンケージ]を選択し,[リンケージプロパティ]ダイアログボックスのAS 2.0クラス欄に「MapChip」と入力します(図A[拡大表示])。これで,シンボルmapChip(リンケージ識別子はSMapChip)のインスタンスを通じて,MapChipクラスのメンバーにアクセスできるようになります。

 MapChipクラスを利用すると,リスト1の(5)~(6)の処理は

m.init(_type = map[r][c],
_charDepth = r*20 + 10);
と書き換えられ,リスト2の(4)を含むif文の条件部は
if(nextChip.canMove()) {
//処理

と書き換えられます。

下記のURLから、サンプル・プログラムを無償ダウンロードできます。
http://software.nikkeibp.co.jp/software/download/down05c.html#200502