掲示板のほうでキーボードを使ったゲームを作る話がありましたので、
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;
}
}
}