今回は新しいお題として、キーボードのキーでインスタンスを操作してみたい。上下左右の矢印キーで、MovieClipインスタンスをその方向に移動させる。そのためには、キーが押される操作をイベントとして受取り、それが何のキーかを判別して処理することになる。
キーイベントを受取る
まず、キーボードのキーを押した操作はどう受取ればよいか。ActionScript 3.0では、イベントはつねにイベントリスナーの仕組みを使って処理する。キーを押すイベントは、InteractiveObject.keyDown(KeyboardEvent.KEY_DOWN定数)
だ[1]。
InteractiveObjectは、 DisplayObjectクラスのスーパークラスである。マウスやキーボードの操作を扱う。MovieClipクラスはDisplayObjectクラスを継承するので、そのスーパークラスであるInteractiveObjectのイベントも当然受取れる(スーパークラスや継承については、第9回「座標の天動説と地動説」の「インスタンスとマウスポインタの座標」参照)。
もっとも、今回キーイベントInteractiveObject.keyDown
のリスナーは、Stageオブジェクトをターゲットとして登録しなければならない。StageクラスもまたDisplayObjectクラスを継承するので、キーイベントは受取れる。しかし、なぜキー操作で動かそうとするMovieClipインスタンスを、ターゲットにできないのか。
MovieClipインスタンスに対してキーイベント(InteractiveObject.keyDown
など)のリスナーを登録すると、そのインスタンスにフォーカスを当てていないと[2]、イベントが受取れないのだ。またフォーカスを当てても、インスタンス外のステージ上をマウスクリックでもすれば、フォーカスが外れてイベントを受取らなくなってしまう。
したがって、フォーカスに関わりなくキーイベントInteractiveObject.keyDown
を処理するには、キー操作で移動するMovieClipシンボルに以下のようなフレームアクション(スクリプト001)を記述する。なお、リスナー関数xKeyDown()はテスト用に、引数として受取ったイベントオブジェクトeventObjectをtrace()
関数で[出力]パネルに表示することとした。
[ムービープレビュー]を実行して、キーボードからキーを押すと、そのキーイベントの情報が[出力]パネルに表示される(図1)。ところが、[Enter]または[return]などいくつかのキーは、いくら押しても何も[出力]されない。つまり、KeyboardEvent.KEY_DOWN
イベントが発生しないのだ。
[ムービープレビュー]のモードには、いくつかのキーにショートカットが割当てられている。たとえば、[Enter]または[return]キーなら、[制御]メニューの[再生]だ。ショートカットキーを押すと、 FlashのSWFコンテンツでなく、メニューがそのキー入力を先に奪ってしまう。これを避けるためには、[制御]メニューで[キーボードショートカットを無効]にしておく必要がある(図2)。
イベントオブジェクトとキーコード
前掲スクリプト1で、キーを押したとき[出力]パネルに表示される情報を、改めて見てみよう。たとえば、左矢印キーを押したときは、つぎのような[出力]になる。これらは、リスナー関数xKeyDown()が引数として受取ったKeyboardEventオブジェクトの情報だ。
等号=の左辺はKeyboardEventオブジェクトのプロパティで、右辺がその値を意味する[3]。今回知りたい、どのキーが押されたかという情報は、keyCodeプロパティが示す。数値37は左矢印キーのキーコードである。KeyboardEventオブジェクトの基本的なプロパティについて、下表1に説明を掲げた。
表1 KeyboardEventオブジェクトの基本的なプロパティ
プロパティ:データ型 | 値 |
altKey:Boolean |
[Alt](Windows)または[option](Macintosh)キーが押されているとtrue、押されていなかったらfalseを返す。 |
charCode:uint |
イベントが発生したキー入力のAsccii文字コードを整数で返す。 |
ctrlKey:Boolean |
[Ctrl](Windows)または[command](Macintosh)キーが押されているとtrue、押されていなかったらfalseを返す。 |
currentTarget:Object |
イベントリスナーが登録され、リスナー関数にイベントを伝えたインスタンスを返す。 |
keyCode:uint |
イベントが発生したキーのキーコードを整数で返す。 |
shiftKey:Boolean |
[shift]キーが押されているとtrue、押されていなかったらfalseを返す。 |
type:String |
発生したイベント名を文字列で返す。 |
押されたキーのキーコードを調べるには、KeyboardEvent.keyCode
プロパティを取出せばよい。たとえば、キーコードを[出力]しようとするなら、前掲スクリプト1でリスナー関数xKeyDown()内のtrace()
関数の引数を以下のように修正する。これで、各矢印キーなどの、必要なキーコードが調べられるだろう。
もっとも、実は文字以外の多くのキーには、Keyboardクラスの定数が定められている。もちろん、定数の値はキーコードの整数だ。しかし、スクリプト中で整数値をそのまま指定するより、定数を使った方が何のキーに対する処理なのかはずっとわかりやすくなる。矢印キーの定数を下表2に掲げる。
表2 Keyboardクラスの矢印キーの定数
定数 | キー | 値 |
Keyboard.DOWN |
下矢印キー |
40 |
Keyboard.LEFT |
左矢印キー |
37 |
Keyboard.RIGHT |
右矢印キー |
39 |
Keyboard.UP |
上矢印キー |
38 |
キーイベントの受取り方がわかり、押されたキーをどう識別するかも確かめた。すると、お題のキー操作でインスタンスを動かすスクリプトは、もうつくる準備が整った。
矢印キーでインスタンスを移動する
上下左右の矢印キーで、インスタンスをその方向に1ピクセルずつ移動させることにしよう。スクリプトの組立てはこうだ。
インスタンスを移動する関数はxMove()として新たに定義し、押されたキーのキーコードを引数に、リスナー関数xKeyDown()から呼出す。関数xMove()は、渡されたキーコードが上下左右の矢印キーかどうかを判別して、矢印キーだったらその方向にインスタンスの座標を1ピクセル移動する。
前掲スクリプト1のリスナー関数xKeyDown()に修正を加え、新たに関数xMove()を定義したのが、つぎのフレームアクションである(スクリプト2)。
リスナー関数xKeyDown()は、引数として受取ったKeyboardEventオブジェクトからKeyboardEvent.keyCode
プロパティの値を取出し、取得したキーコードを関数xMove()に渡して呼出している。関数xMove()は渡された引数を、if/else if
ステートメントで上下左右の矢印キーの定数と等価比較して、キーコードがいずれかの定数と一致すれば、インスタンスの座標をその方向に1ピクセル移動する。
[ムービープレビュー]で試してみると、キーボードの上下左右の矢印キーで、インスタンスがその方向に1ピクセルずつ移動するはずだ(図3)。ところが、ブラウザで確認(たとえば[パブリッシュプレビュー])すると、矢印キーを押してもインスタンスは動かないことがある。それは、ブラウザウィンドウの中で、SWFがフォーカスを持っていないからだ。
ブラウザウィンドウ内のSWFコンテンツにフォーカスを与えるもっとも簡単で確実な方法は、ユーザーにSWF上をクリックしてもらうことである。コンテンツのナビゲーションを開始する際に、たとえば[スタート]ボタンを置いてクリックさせるなどの工夫が必要とされる。
さて、次回は[shift]キーの組合わせでインスタンスの移動距離を変更し、キーコードの判定をifステートメント以外の構文に書替えてみたい。
今回解説した次のサンプルファイルがダウンロードできます。