前回の第13回「キーボードによる操作」では,上下左右の矢印キーでインスタンスがその方向に1ピクセルずつ動くというナビゲーションを作成した。その前回のスクリプト2に,さらに2つ手を加えてみよう。ひとつは,同時に[shift]キーを押したとき,インスタンスの移動距離を変更する。そしてもうひとつは,キーコードの判定を,ifでなくswitchというステートメントによる処理に書替える。
[shift]キーを押したら移動距離を変える
矢印キーを操作する際,同時に[shit]キーも押した場合,インスタンスの移動距離を10ピクセルにしてみる。これはFlashで[選択ツール]を使い,矢印キーでエレメントを移動するときと同じインターフェイスだ。
[shift]キーを押しているかどうかは,KeyboardEvent.shiftKeyプロパティで調べることができた(前回の表1「KeyboardEventオブジェクトの基本的なプロパティ」参照)。そこで,前回のスクリプト2におけるInteractiveObject.keyDownイベント(イベント定数KeyboardEvent.KEY_DOWN)のリスナー関数xKeyDownにステートメントを加え,次のようにKeyboardEvent.shiftKeyプロパティの値を取出したうえで,関数xMove()の第2引数に渡して呼出すことにする。
stage.addEventListener(KeyboardEvent.KEY_DOWN, xKeyDown);
function xKeyDown(eventObject:KeyboardEvent):void {
var nKeyCode:int = eventObject.keyCode;
var bShiftKey:Boolean = eventObject.shiftKey;
xMove(nKeyCode, bShiftKey);
}
関数xMove()は,第2引数として受取った値がtrueつまり[shift]キーが押されていればインスタンスの移動距離を10に設定し,falseで[shift]キーが押されていない場合には移動距離を1にする。この引数値がtrueかfalseかによって,10または1を返すという処理は,新たに関数xGetPixels()として定義しよう。引数にはブール(論理)値をひとつ渡す。すると,関数xMove()は次のようになる。
function xMove(nKeyCode:int, bShiftKey:Boolean):void {
if (nKeyCode == Keyboard.LEFT) {
x -= xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.RIGHT) {
x += xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.UP) {
y -= xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.DOWN) {
y += xGetPixels(bShiftKey);
}
}
関数xGetPixels()は,引数に渡したブール値がtrueなら10を,falseであれば1を返す。この処理はifステートメントを使って簡単に書くことができるだろう。しかし,今回は条件演算子?:を用いてみたい。条件演算子?:は,以下のシンタックスで記述する。そして,条件の評価がtrueなら式1の値を,falseであれば式2の値を返す。
条件 ? 式1 : 式2
戻り値は,変数などに代入する。条件に指定する式は,if条件と同じだ。たとえば,Boolean型の変数bShiftKeyが与えられた場合,変数値がtrueなら10,falseのときは1を,int型で宣言した変数nPixelsに代入する式は次のとおりだ。
var nPixels:int = bShiftKey ? 10 : 1;
さて,これで関数xGetPixels()も定義できるだろう。インスタンスを移動する距離は,変数として宣言しておくことにする。nMoveが矢印キーのみのとき,nShiftMoveは[shift]キーを併せた場合の移動ピクセル数だ。以上の修正を加えた,キー操作で動かすインスタンスのフレームアクションは,つぎのスクリプト1とおりだ(図1)。
スクリプト1 矢印キーで1ピクセル/[shift]キーを加えると10ピクセルずつインスタンスを移動
// MovieClip: キー操作で動かすインスタンス
var nMove:int = 1;
var nShiftMove:int = 10;
stage.addEventListener(KeyboardEvent.KEY_DOWN, xKeyDown);
function xKeyDown(eventObject:KeyboardEvent):void {
var nKeyCode:int = eventObject.keyCode;
var bShiftKey:Boolean = eventObject.shiftKey;
xMove(nKeyCode, bShiftKey);
}
function xMove(nKeyCode:int, bShiftKey:Boolean):void {
if (nKeyCode == Keyboard.LEFT) {
x -= xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.RIGHT) {
x += xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.UP) {
y -= xGetPixels(bShiftKey);
} else if (nKeyCode == Keyboard.DOWN) {
y += xGetPixels(bShiftKey);
}
}
function xGetPixels(bShiftKey:Boolean):int {
var nPixels:int = bShiftKey ? nShiftMove : nMove;
return nPixels;
}
[ムービープレビュー]で確かめると,矢印キーでは前回と同じく1ピクセルずつ動き,[shift]キーを押しながら矢印キーを操作すれば10ピクセルずつ移動するようになった。上記スクリプト1について,2つ補足しよう。
第1は,関数xMove()内からの関数xGetPixels()の呼出しだ。if/else ifそれぞれのステートメントで,いちいち関数を呼出している。つぎのように関数xMove()本体の最初に呼出して,戻り値をローカル変数(※1)に入れた方がスマートではないだろうか。
function xMove(nKeyCode:int, bShiftKey:Boolean):void {
var nPixels:int = xGetPixels(bShiftKey);
if (nKeyCode == Keyboard.LEFT) {
x -= nPixels;
} else if (nKeyCode == Keyboard.RIGHT) {
x += nPixels;
// ...[後略]...
しかし,この流れでは,矢印キーを押さなくても,関数xGetPixels()が呼出されてしまう。確かに,元のスクリプト1では,xGetPixels()の呼出しが4ステートメント記述されている。けれども,1回の呼出しで処理されるのは,押された矢印キーに対応する1ステートメントだけである。それだけではない。矢印キーが押されなければ,関数xGetPixels()が呼出されることもないのだ。よって,スクリプト1の方が無駄は少ないといえる。
第2に,関数xGetPixels()の中で,移動ピクセル数の判定に条件演算子?:を使ったことだ。if/else ifステートメントと比べたメリットは何か。条件演算子?:を使うと,「演算子」という名前のとおり,値を返すという処理内容が明らかになる。また,短く記述されて見やすいということたろう。しかし,処理効率には大きな違いはない。if/else ifの方が見やすいと思う読者は,そちらを利用してもとくに差支えはない。
- ※1)
- 関数本体({}内)でvar宣言された変数を「ローカル変数」(local variable)という。関数本体の中でのみ有効で,関数の外や他の関数からアクセスすることはできない([ヘルプ]の[ActionScript 3.0のプログラミング] > [ActionScript言語とシンタックス] > 変数参照)。関数が終了すれば,ローカル変数は原則としてメモリからクリアされる。
これに対して,フレームアクションで関数の外にvar宣言された変数は,スクリプトを記述したタイムラインにメモリされるので,「タイムライン変数」と呼ばれる。

