2010年07月11日

【プログラム】XNAでゲームを作る(4)

前回の投稿からしばらく空いてしまいましたね
黒いPCケースの電源タッチパネル基盤が壊れてしまったので
いろいろとありました

前置きはさておき、
前回の続きから

今回は前回作成したインターフェイスを実装する部分まで行きたいと思いますよ






インターフェイスを実装するまえに
キーの繰り返し入力を管理するクラスを作成しましょう

public class Repeat
{
}

変数は以下を宣言しておきます
// 初回押下状態のフレーム数
 private uint m_iFirstIntervalCnt;
// 2回目以降の押下状態フレーム数
 private uint m_iRepeatIntervalCnt;
// 繰り返し状態になったカウント
 private uint m_iCount;
// 初回押下状態で繰り返し押下状態になるフレーム数
 private uint m_iFirstInterval;
// 2回目以降の押下状態で繰り返し押下状態になるフレーム数
 private uint m_iRepeatInterval;

 // リピート状態列挙体
 public enum RepeatState : byte
 {
  Released = 0, // 開放
  FirstPress,  // 最初に押下した状態
  FirstInterval, // 最初に押下したインターバル状態
  RepeatPress, // 繰り返し押下した状態
  RepeatInterval // 繰り返し押下したインターバル状態
 }
// 押下状態

 private RepeatState m_rsState;

宣言したメンバ変数にアクセスできるように
プロパティを作成します。

// 規定リピートインターバルを繰り返した回数
 public uint RepeatIntervalCnt { get { return this.m_iCount; } } 

// 初回インターバル規定値
 public uint FirstInterVal
 {
  set { this.m_iFirstInterval = value; }  
  get { return this.m_iFirstInterval; }
 }
// 2回目以降インターバル規定値
 public uint RepeatInterval
 {
  set { this.m_iRepeatInterval = value; } 
  get { return this.m_iRepeatInterval; }
 }

// インターバルを終え、再度押下状態となったか 
 public bool Repeated
 {
  get
  {
   return (m_rsState == RepeatState.FirstPress || 
        m_rsState == RepeatState.RepeatPress);
  }
 }
// 現在の押下状態を取得
 public RepeatState State { get { return this.m_rsState; } }

インターバルを終えて繰り返し状態になったかのプロパティが一番使用頻度が高いかもしれませんね

次にインスタンスされたときに処理されるコンストラクタを作成します。
このとき引数に初回インターバルフレーム数と2回目以降のインターバルフレーム数を受け取ります。

 public Repeat(uint iFirstInterval, uint iRepeatInterval)
 {
  this.m_iFirstInterval = iFirstInterval;
  this.m_iFirstIntervalCnt = 0;
  this.m_iRepeatInterval = iRepeatInterval;
  this.m_iRepeatIntervalCnt = 0;
  this.m_iCount = 0;
  this.m_rsState = RepeatState.Released;
 }

継承先のクラスでこの引数をもらうことでインスタンス作成時にフレーム数を指定することができるので
後々楽になりますよ
そうするとインターバルフレーム数を設定するプロパティの出番がなくなりますがね・・・
きっと変更したくなったときに使えますよ(爆

最後に更新関数ですね。
引数は現在のフレームでのキー押下状態フラグです。
継承先のクラスから渡される予定です。

 public void Update(bool bsState)
 {
  // 現在押下状態ではない
  if (!bsState)
  {
   m_iFirstIntervalCnt = 0;
   m_iRepeatIntervalCnt = 0;
   m_rsState = RepeatState.Released;
   m_iCount = 0;
  }
  // 押下状態にある
  else
  {
   switch (m_rsState)
   {
    case RepeatState.Released:// 前のフレームで押下状態でない
     m_rsState = RepeatState.FirstPress; // 初期押下状態に変更
     m_iFirstIntervalCnt = 0;
     m_iRepeatIntervalCnt = 0;
     m_iCount++;
     break;
    case RepeatState.FirstPress:// 前のフレームで初期押下状態
     m_rsState = RepeatState.FirstInterval; // 初期押下インターバル状態に変更
     break;
    case RepeatState.FirstInterval:// 前のフレームで初期インターバル状態
     m_iFirstIntervalCnt++;
     if (m_iFirstIntervalCnt >= m_iFirstInterval)
     {
      // インターバルカウントが規定カウントを超えた場合
      m_rsState = RepeatState.RepeatPress; // 繰り返し押下状態に変更
      m_iFirstIntervalCnt = 0;
      m_iCount++;// 繰り返しカウントアップ
     }
     break;
    case RepeatState.RepeatPress:// 前のフレームで繰り返し押下状態
     m_rsState = RepeatState.RepeatInterval; // 繰り返しインターバル状態に変更
     break;
    case RepeatState.RepeatInterval:// 前のフレームで繰り返しインターバル状態
     m_iRepeatIntervalCnt++;
     if (m_iRepeatIntervalCnt >= m_iRepeatInterval)
     {
      // インターバルカウントが規定カウントを超えた場合
      m_rsState = RepeatState.RepeatPress; // 繰り返し押下状態に変更
      m_iRepeatIntervalCnt = 0;
      m_iCount++;// 繰り返しカウントアップ
     }
     break;
   }
  }
 }

これで繰り返し状態であるかというチェック機構はできました。

では実際にインターフェイスを実装したクラスを作りましょう

public class KeyboardInputState : Repeat, I_KeyboardButtonState
{
}

このクラスでひとつにキーに対する入力状態を管理します。
先ほどのRepeatクラスを継承し、前回作成したI_KeyboardButtonStateを実装します。

メンバ変数とプロパティは以下のように宣言しましょう

 private bool m_bPressed;
 private bool m_bJustPressed;
 private uint m_iPressedCnt;

// 押下状態であるか

 public bool Pressed { get { return this.m_bPressed; } } 
// 現フレームで押下状態になっているか
 public bool JustPressed { get { return this.m_bJustPressed; } }
// 連続押下フレーム数
 public uint PressedCnt { get { return this.m_iPressedCnt; } } 

↑の部分がインターフェイス実装部分ですよ

次にコンストラクタを作成

 public KeyboardInputState(uint iFirstInterval, uint iRepeatInterval)
  : base(iFirstInterval, iRepeatInterval)
 {
  // ボタン押下していない状態で情報を初期化する
  this.Update(false);
 }

baseという部分がRepeatクラスへのアクセスとなります。
ここではRepeatクラスのコンストラクタを呼んでいることになります

そして最後に更新処理関数

 public new void Update(bool bsCurrent) /* new の理由→RepeatクラスにもUpdate関数が存在し、このUpdateはオーバーライドしないという明示的なもの */
 {
  bool bsPrevious;
  // 現フレームボタン押下情報を直前フレームボタン押下情報へコピー
  bsPrevious = m_bPressed;

  // ボタンが押下状態の場合、現フレームボタン押下情報を押下状態にする
  if (bsCurrent) { m_bPressed = true; }
  else { m_bPressed = false; }

  // 今回のフレームで初めて押下されたのかチェック
  if ((!bsPrevious) && (bsCurrent)) { m_bJustPressed = true; }
  else { m_bJustPressed = false; }

  // 押下状態の場合、連続押下時間をカウントアップ
  if (bsCurrent) { m_iPressedCnt++; }
  else { m_iPressedCnt = 0; } // 今回のフレームが押下状態ではない場合、カウントを0にクリアする

  // 親クラス(Repeat)のUpdateを実行する
  base.Update(bsCurrent);
 }


最後の一行でRepeatクラスの更新処理を呼んでいますね
引数には今回の押下状態を渡しているので
先ほど作成したときのつじつまはあっていることがお分かりいただけるかと思います。

さて、次回全体のキー入力を管理するクラスを作成していきますよ。

高還元★ドル箱

posted by ヒイロ at 11:46| 福岡 ☁| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。