myugaruの色々構想中・・・!

「C#」「画像処理」「XNA未対応PCでゲームIDE作りの無謀な野望」

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  98  : 記事  0  : コメント  2342  : トラックバック  59

ニュース

myugaru
仕事(昔)=ヲタク系プログラマー~マスコミ系サポートデスク
仕事(今)=電子機器系サービス業
趣味a=パズルゲーム全般、シューティングは主に見学
趣味b=画像処理関係の勉強
趣味c=プログラミング言語の勉強
趣味d=アキバ系ヲタク
趣味e=芸能アイドル系ヲタク
d,e色の強いもう一つのブログ
最新目標=シューティングゲームを作る

わんくまりんく

わんくま同盟blog C#,VB.NET掲示板

ぶろぐつーる

あわせて読みたい

はてなりんぐ

書庫

日記カテゴリ

ギャラリ

お友達

リンク

掲示板のほうでキーボードを使ったゲームを作る話がありましたので、

http://bbs.wankuma.com/index.cgi?mode=al2&namber=14398

こっそりテスト済みなDirectInputの実装クラスを公開してみようと思います。キーボードだけじゃなく一応ジョイスティックも動作させることができます。

実はこの日記を書き始める前にすでにDirectXでの各ライブラリの動作については自分にコードが書けるかどうかが不明だと怖いですから、ある程度検証済みなのです。とりあえず何か動かせと言われればDirect3Dの2Dスプライトを使うだけでよければすぐに動かせるくらいの理解はしております。

あ、じゃあ本当に晩御飯たべてきます(笑

using System.Collections;
using Microsoft.DirectX.DirectInput;
namespace GameTemplate
{
    /// <summary>
    /// キー入力情報
    /// </summary>
    enum KeyInfo
    {
        UP, DOWN, LEFT, RIGHT, A, B, C, D,
        Max,
    }
    class DInput
    {
        internal DInput(MainForm f)
        {
            this.mainForm = f;
        }
        /// <summary>
        /// メインフォーム
        /// </summary>
        MainForm mainForm;
        /// <summary>
        /// joystick : レバーマイナス方向判定値
        /// </summary>
        const int JOYSTICK_REBER_MINUS = 0x1000;
        /// <summary>
        /// joystick : レバープラス方向判定値
        /// </summary>
        const int JOYSTICK_REBER_PLUS = 0xffff - 0x1000;
        /// <summary>
        /// joystick : DirectInputデバイス
        /// </summary>
        Device joyDevice;
        /// <summary>
        /// keyboard : DirectInputデバイス
        /// </summary>
        Device keyDevice;
        /// <summary>
        /// keyboard : キー状態
        /// </summary>
        KeyboardState keyState;
        /// <summary>
        /// On状態集計
        /// </summary>
        BitArray resultOns = new BitArray((int)KeyInfo.Max);
        /// <summary>
        /// 溜め時間集計
        /// </summary>
        int[] charge = new int[(int)KeyInfo.Max];
        /// <summary>
        /// メニュー溜め時間(Limit)
        /// </summary>
        const int CHARGE_LIMIT = 15;
        /// <summary>
        /// メニューリピート速度(現在値)
        /// </summary>
        int repeat;
        /// <summary>
        /// メニューリピート速度(Limit)
        /// </summary>
        const int REPEAT_LIMIT = 6;
        /// <summary>
        /// キー状態更新
        /// </summary>
        internal void Poll()
        {
            // On状態集計初期化
            resultOns.SetAll(false);
            // keyboard : デバイス状態確認
            try {
                keyState = keyDevice.GetCurrentKeyboardState();
                foreach (var kv in new[]{
                    new { k = Key.Up,    v = KeyInfo.UP    },
                    new { k = Key.Down,  v = KeyInfo.DOWN  },
                    new { k = Key.Left,  v = KeyInfo.LEFT  },
                    new { k = Key.Right, v = KeyInfo.RIGHT },
                    new { k = Key.Z,     v = KeyInfo.A     },
                    new { k = Key.X,     v = KeyInfo.B     },
                    new { k = Key.C,     v = KeyInfo.C     },
                    new { k = Key.V,     v = KeyInfo.D     },
                }) {
                    if (keyState[kv.k]) {
                        resultOns[(int)kv.v] = true;
                    }
                }
            }
            catch {
                try {
                    // 初期化
                    keyDevice = new Device(SystemGuid.Keyboard);
                    // 協調レベル設定
                    keyDevice.SetCooperativeLevel(mainForm.Handle,
                        CooperativeLevelFlags.Foreground |
                        CooperativeLevelFlags.Exclusive);
                    // アクセス権取得
                    keyDevice.Acquire();
                }
                catch {
                }
            }
            // joystick : デバイス状態確認
            try {
                joyDevice.Poll();
                JoystickState js = joyDevice.CurrentJoystickState;
                if (js.Y < JOYSTICK_REBER_MINUS)
                    resultOns[(int)KeyInfo.UP] = true;
                if (js.Y > JOYSTICK_REBER_PLUS)
                    resultOns[(int)KeyInfo.DOWN] = true;
                if (js.X < JOYSTICK_REBER_MINUS)
                    resultOns[(int)KeyInfo.LEFT] = true;
                if (js.X > JOYSTICK_REBER_PLUS)
                    resultOns[(int)KeyInfo.RIGHT] = true;
                byte[] joyButtons = js.GetButtons();
                foreach (var kv in new[]{
                    new { k = 0, v = KeyInfo.A },
                    new { k = 1, v = KeyInfo.B },
                    new { k = 2, v = KeyInfo.C },
                    new { k = 3, v = KeyInfo.D },
                }) {
                    if (joyButtons[kv.k] != 0) {
                        resultOns[(int)kv.v] = true;
                    }
                }
            }
            catch {
                // 初期化
                try {
                    foreach (DeviceInstance di in Manager.GetDevices(
                        // 接続されたゲームコントローラ検索
                        DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly)) {
                        joyDevice = new Device(di.InstanceGuid);
                        // 協調レベル設定
                        joyDevice.SetCooperativeLevel(mainForm.Handle,
                            CooperativeLevelFlags.Background |
                            CooperativeLevelFlags.NonExclusive);
                        // データフォーマット設定
                        joyDevice.SetDataFormat(DeviceDataFormat.Joystick);
                        // アクセス権取得
                        joyDevice.Acquire();
                        break;
                    }
                }
                catch {
                }
            }
            // 溜め時間更新
            for (int i = 0; i < charge.Length; i++) {
                if (resultOns[i]) charge[i]++; else charge[i] = 0;
            }
        }
        /// <summary>
        /// カーソルタイプ入力確認
        /// (押した瞬間反応、溜まった状態でリピート開始)
        /// (戻り:押されていたらtrue)
        /// </summary>
        /// <param name="key">確認するキー</param>
        internal bool Press(KeyInfo key)
        {
            int c = charge[(int)key];
            if (c == 1 || c > CHARGE_LIMIT &&
                    ++repeat > REPEAT_LIMIT) {
                repeat = 0;
                return true;
            }
            return false;
        }
        /// <summary>
        /// ピアノタイプ入力確認
        /// (押した瞬間のみ反応)
        /// (戻り:押した瞬間ならtrue)
        /// </summary>
        /// <param name="key">確認するキー</param>
        internal bool DownNow(KeyInfo key)
        {
            return charge[(int)key] == 1;
        }
        /// <summary>
        /// ブザータイプ入力確認
        /// (押した瞬間からリピート開始)
        /// (戻り:押されていたらtrue)
        /// </summary>
        /// <param name="key">確認するキー</param>
        internal bool Down(KeyInfo key)
        {
            return charge[(int)key] > 0;
        }
    }
}
投稿日時 : 2008年2月17日 20:32

コメント

No comments posted yet.

Post Feedback

タイトル
名前
Url:
コメント