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

第13回キーボードによる操作

今回は新しいお題として、キーボードのキーでインスタンスを操作してみたい。上下左右の矢印キーで、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 キーを押すとイベントオブジェクトの情報を[出力]する
// MovieClip: キー操作で動かすインスタンス
stage.addEventListener(KeyboardEvent.KEY_DOWN, xKeyDown);
function xKeyDown(eventObject:KeyboardEvent):void {
  trace(eventObject);
}

[ムービープレビュー]を実行して、キーボードからキーを押すと、そのキーイベントの情報が[出力]パネルに表示される図1⁠。ところが、[Enter]または[return]などいくつかのキーは、いくら押しても何も[出力]されない。つまり、KeyboardEvent.KEY_DOWNイベントが発生しないのだ。

図1 StageオブジェクトにキーイベントInteractiveObject.keyDownのリスナーを登録
図1 StageオブジェクトにキーイベントInteractiveObject.keyDownのリスナーを登録

[ムービープレビュー]のモードには、いくつかのキーにショートカットが割当てられている。たとえば、[Enter]または[return]キーなら、[制御]メニューの[再生]だ。ショートカットキーを押すと、 FlashのSWFコンテンツでなく、メニューがそのキー入力を先に奪ってしまう。これを避けるためには、[制御]メニューで[キーボードショートカットを無効]にしておく必要がある図2⁠。

図2 [制御]メニューで[キーボードショートカットを無効]
図2 [制御]メニューで[キーボードショートカットを無効]

イベントオブジェクトとキーコード

前掲スクリプト1で、キーを押したとき[出力]パネルに表示される情報を、改めて見てみよう。たとえば、左矢印キーを押したときは、つぎのような[出力]になる。これらは、リスナー関数xKeyDown()が引数として受取ったKeyboardEventオブジェクトの情報だ。

[KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=0 keyCode=37 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]

等号=の左辺は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()関数の引数を以下のように修正する。これで、各矢印キーなどの、必要なキーコードが調べられるだろう。

trace(eventObject.keyCode);

もっとも、実は文字以外の多くのキーには、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⁠。

スクリプト2 イベントオブジェクトからキーコードを取得してキー定数で判定
// MovieClip: キー操作で動かすインスタンス
stage.addEventListener(KeyboardEvent.KEY_DOWN, xKeyDown);
function xKeyDown(eventObject:KeyboardEvent):void {
  var nKeyCode:int = eventObject.keyCode;
  xMove(nKeyCode);
}
function xMove(nKeyCode:int):void {
  if (nKeyCode == Keyboard.LEFT) {
    x -= 1;
  } else if (nKeyCode == Keyboard.RIGHT) {
    x += 1;
  } else if (nKeyCode == Keyboard.UP) {
    y -= 1;
  } else if (nKeyCode == Keyboard.DOWN) {
    y += 1;
  }
}

リスナー関数xKeyDown()は、引数として受取ったKeyboardEventオブジェクトからKeyboardEvent.keyCodeプロパティの値を取出し、取得したキーコードを関数xMove()に渡して呼出している。関数xMove()は渡された引数を、if/else ifステートメントで上下左右の矢印キーの定数と等価比較して、キーコードがいずれかの定数と一致すれば、インスタンスの座標をその方向に1ピクセル移動する。

[ムービープレビュー]で試してみると、キーボードの上下左右の矢印キーで、インスタンスがその方向に1ピクセルずつ移動するはずだ図3⁠。ところが、ブラウザで確認(たとえば[パブリッシュプレビュー])すると、矢印キーを押してもインスタンスは動かないことがある。それは、ブラウザウィンドウの中で、SWFがフォーカスを持っていないからだ。

図3 キーコードと矢印キーのキー定数と等価比較してインスタンスをその方向に移動する
図3 キーコードと矢印キーのキー定数と等価比較してインスタンスをその方向に移動する

ブラウザウィンドウ内のSWFコンテンツにフォーカスを与えるもっとも簡単で確実な方法は、ユーザーにSWF上をクリックしてもらうことである。コンテンツのナビゲーションを開始する際に、たとえば[スタート]ボタンを置いてクリックさせるなどの工夫が必要とされる。

さて、次回は[shift]キーの組合わせでインスタンスの移動距離を変更し、キーコードの判定をifステートメント以外の構文に書替えてみたい。

今回解説した次のサンプルファイルがダウンロードできます。

おすすめ記事

記事・ニュース一覧