鳥小屋.txt

主に自作ゲームをつくったりしているよ。制作に関することやそうじゃないことのごった煮ブログ

リプレイ機能を備えたキー入力処理を考える

ゲームを作る上で大事なところはどこでしょう!というと、確かに絵とか音楽とかも重要ですが、絵と音楽だけだと映画になってしまうので、やっぱりゲームは操作できてナンボのもんじゃいなわけです。そんな大事なキー入力処理を作っていきましょう☆

キー入力処理はやっぱり大事な部分なのできちんと考えて作りたいです。そんなわけでこんな機能があったらいいなというのを挙げてみます。

  • キーコンフィグができる
  • 押しっぱなしOKとか押した瞬間だけとかいろいろ判定したい
  • 複数人プレイに簡単に対応できる
  • 簡単にリプレイが作れる
  • できたらネット対戦的なこととか……

挙げればいろんな機能が欲しいですね。個人的にPCゲーはキーコンフィグ必須だと思います。キーボードの配列ってモノによって微妙に違ったりするし、コントローラはボタンの番号がメーカーによって様々なので必須なんてもんじゃないですし。
あと、リプレイ機能を簡単に作れるようにしたいので、どういう入力をしたのか自動的に記憶しておいてくれると便利ですね。で、その情報をファイルに保存できれば簡単にリプレイが作れます!(実際は乱数の初期シードとかも保存しなきゃですけど)

そんなことを考えながら今回僕が作ったヘッダファイルはこんなの。

class Input
{
  /* ● メンバ変数 -------------------------------------------------------- */
  protected:
    static const int MAX_INPUT_DATA     = (60*2)*60*30; // 最大記憶時間(30分)
    static const int INPUT_REPEAT_WAIT1 = 20;           // 繰り返し用ウェイト1(たん)
    static const int INPUT_REPEAT_WAIT2 =  3;           // 繰り返し用ウェイト2(たたたた)

    char _data[MAX_INPUT_DATA];                         // 入力情報
    int _timer;                                         // 内部タイマー
    int _player;                                        // プレイヤー番号
    int _config[MAX_INPUT_KEY];                         // 設定
    int _press[MAX_INPUT_KEY];                          // 押したまま状態記憶
    int _repeat[MAX_INPUT_KEY];                         // 繰り返し状態記憶
  /* ● メソッド ---------------------------------------------------------- */
  public:
    Input(
      int player = 0     // プレイヤー番号(1P = 0、2P = 1、……)
      );
    ~Input(
      );
    int update(          // readKeyを呼び出し、_press等を更新
      );
    int getPress(        // 連続おしっぱ時間を返す
      int key_num            // キーの番号
      );
    int getTrigger(      // 押した瞬間かどうかを返す
      int key_num            // キーの番号
      );
    int getRepeat(       // たん、タタタタタタ……
      int key_num            // キーの番号
      );
    void getData(        // _dataの取得
      );
    void clear(          // _dataの消去
      );
  private:
    int readKey(         // デバイスからキー情報を読み込む
      );
};

なんかもうこれだけでもいい気がしますが、一応簡単に説明。

使い方はとってもシンプル。ゲーム始まった頃にこのInputクラスのオブジェクトを作ってあげて、毎フレームupdateメソッドを呼び出してあげるだけ。あとはキーの情報が欲しいときにget○○を呼び出すだけです。

updateメソッドを呼んであげると、呼び出された時のキー入力情報を取得します。ちなみにupdateの中でreadKeyを呼び出す実装になってます。updateの中で処理しないでわざわざreadKeyを呼び出してるのは、このクラスを継承してちょっと特殊な入力機構(リプレイ再生とかネットワークとか……)を作りたくなったときに使いやすくするためです。

押されてるキーの取得はgetPress、getTrigger、getRepeatの3種類を使います。この3つはRPGツクールXP/VXのRGSSをパクって参考にしています。

getPress
キーが押されてるかどうかを判断。戻り値は押し始めてからのフレーム数(_press[key_num])が戻ってくる。
getTrigger
キーを押した瞬間かどうか判断。内部的には_press[key_num]==1か調べてるだけ*1
getRepeat
RGSSに用意されてる神機能、「タン、タタタタタタ……」を再現!メニュー画面のカーソルなんかを移動するときに下を押しっぱなしにすると、押した瞬間に1個したにカーソルが動いて、少し経ってから早い速度でカーソルが下にどんどん移動していくアレ。*2

あとはgetData。これはリプレイを簡単に作るための秘密(?)機能で、このInputクラスでは最大30分間のプレイヤーのキー入力を保存するようになっています。その保存したキー入力ログを返してくれるのがこのgetDataというわけです。
さて、ここで問題です。なんでこのgetDataは戻り値がvoidなのでしょう?






まだ じっそうが できてない !!

*1:つまり、普通にgetPressで代用可能なんですが、まぁあると便利ってことで……

*2:INPUT_REPEAT_WAIT1,2がこれのウェイト時間になってます