« コツのお話その5 インターフェース マウス編 « » ゲーム製作コツのお話その6 攻撃・防御 »

2006年03月02日

 コツのお話その5 インターフェース キー編このエントリーを含むはてなブックマーク

このカテゴリはAAWなどのゲームとかを元に
これからFlashゲームを作る人とかゲームの仕組みに興味がある人に
僕の知ってることを中途半端ながら語ってみようというものです。
ちなみに今までの話はこちらから見れます。
ここで語ることはあくまで自己流なので注意。

今回はキーやマウスといったユーザーインターフェースのお話

Flashでゲームを作るときに失敗しやすいのはユーザーインターフェース、つまりマウスとキーボードの取り方です。
そもそもFlashはあまりゲームを作ることを目的にできていない(というかパソコンができていない)ので、システム的にあまりゲームに向いていないところがあります。
そういうのをどうカバーするか、色々挙げてみます。

マウス編はこちら

キーの離した時と押したとき、押し続けているとき
さてさて、Flashがキー入力を取るのは、実はマウス入力よりも難しい問題があります。
マウスの入力には便利なイベントがいっぱい用意されているのですが、キーのほうはあまり便利じゃありません。
キーの判定は、いつ調べるか?というタイミングと、どうやって調べるか?という判定の2つで成り立ちます。
タイミングは2種類
  • 毎フレームごと
  • キーの変更があったとき
技術的な話をすると、毎フレームごとはMCのenterFrameかフレームのループ、キーの変更はMCのkeyDown、keyUpか、Keyオブジェクトへのリスナー登録になります。

判定の方法も2種類
  • 最後に押されたキー(Key.getCode())
  • 今そのキーが押されているかどうか?(Key.isDown())

これらを組み合わせてキー動作を作ることになります。普通ゲームで判定はKey.isDown()を使います。というのは、Key.getCode()だと離したキーを取れないからですね。
逆にKey.isDown()はどのキーを、という指示をしないと動かないので、キーボード全体を使うようなFlash
(例:fallMoji(HacksionScript))
には向きませんから、この場合はKey.getCode()を使うことになります。
まあ普通のゲームではKey.isDown()だと思ってください。毎回、ゲームに使うキーを全部これで判定するわけですね。

次にタイミングなのですが、これは「キーの変更があったとき」が最も正確ですよね、ところがちょっとした落とし穴があります。
次のFlashは、keyDownのタイミングで矢印キーが押されているとその方向にキャラが動くというものです。



(ソース)
環境によりますが、動きがとーってもガクガクですよね。
キーボードはキーを押しっぱなしにすると 「A  AAAAAAAAAAAAAAAAAAAAA」というように1度間を置いてから連打状態になります。これではゲームには使えないのです。

じゃあフレームで取ればいいんだ、というとそうではないのです。
次のFlashはフレームでキーを取るものですが、わざとfpsを下げています。連打をしてみてください。



(ソース)
上手く連打が認識できないことがありますよね。
つまりフレームで判定していると、フレームの速度より早く押したり離したりされた場合に、Flashが認識できなくなってしまうのです。
僕はAAAでこのミスをしてしまい、ダッシュが上手く入力できなくなってしまいました。

じゃあどうすりゃいいんだー!っていうところですが、正解は
「キー入力は、キーの変更があったとき判定し、その動作はフレームでする」
ということです。
イメージ的にはキー入力を判定する人と、キャラクターを動かす人が別にいて、キー入力判定の人は今どのキーが押されているか?などの情報を変数として表示し、キャラクターを動かす人がそれを見てフレームごとに動かすのです。
キーの回数数えや、ダッシュ入力なんかはキー入力判定の人が担当します。

これを使ったサンプルは↓です。



(ソース)
実はキーの変更時だけだと同時押しのときに変なことになるので、フレームごとにも判定させています。
ちょっと無駄があるようですが、より使いやすいキーにするためにはこれくらいがいいんじゃないかと思っています。
無駄を出したくないのであれば、今度は連打などを判定する人と、キーが毎フレーム押されているかを判定する人と、と分ければいいかな?

同時に押せないキー
一部のキーボード(特にノートパソコン)は、同時に押せないキーがあります。
引っかかりやすいところを挙げるので覚えておいてください。
  • 矢印キー1つと、通常キー3つは、ほぼ確実に押せません。矢印と一緒に押せるのは2つまでだと思ってください。
    このせいで、移動ボタンを→、ダッシュボタンをZ、ジャンプボタンX、攻撃ボタンをCと割り当てていると、環境によってダッシュしながらジャンプして攻撃しようとした時に、攻撃が出ないことがあります。
  • 矢印キー2つ(特に上キー)と通常キー1つも一緒に押せません。
    これによって、移動ボタンを→、ダッシュボタンをZ、ジャンプボタンを↑に割り当てていると、ダッシュ中にジャンプができなくなります。かなりまずいです。

これらを回避するためにはゲームのデザインをよく考えなければいけません。
まず、ボタンを押しながら→でダッシュするのはやめましょう。攻撃ボタンが別に無ければ問題ないですが、理想は→→と入力することでダッシュさせる方法です。
もしくは初代マリオのように、攻撃ボタンとダッシュボタンを同じにしてしまう方法があります。
次にジャンプを↑に割り当てないようにします。ユーザーが変更するのはいいのですが、デフォルトは通常キーに割り当てておきましょう。

2重入力
ダッシュを→→に割り当てた時には2重入力を判定する必要があります。
僕が使っている判定方法は「前回離されたときから、○○ミリ秒以内にもう1度押されたら2重入力」としています。
ミリ秒はゲームによって調節してください。

インターフェース部分はひとまとめに
さて、上のほうで2つに分けるという話がありましたが、これにはメリットが幾つかあります。
まず、キーの動作を変更したい時、1箇所を変えればいいのでとても楽です。
次にキーの動作をユーザーから奪うことができます。
クリアした時など、ユーザーに動かせたくない場合は、判定の人のほうを止めてしまえばいいし、判定の人に偽の判定をさせることで、デモプレイのようなオート操作をさせることができます。
処理ををまとめてしまうことはゲームを作るときに関わらず大切なことです。