「コントローラー」タグのついた投稿

今回は、コントローラーが抜けた事を察知する処理をメモります。

 

何故コントローラーが抜けた事をプログラム的に実装する必要があるかと言うと、抜けた時にゲームをポーズしたり、何らかの処理を行いたい時の為です。

 

では実装に入ります。行う事は、前のフレームにコントローラーが繋がれていて、現在のフレームでは繋がれていないかの確認だけなのです。

 

まずは必要な変数を宣言します。

GamePadState[] m_PadState = new GamePadState[4];
GamePadState[] m_OldPadStates = new GamePadState[4];

 

次に、コントローラーの状態を毎フレーム更新します。

 

protected override void Update(GameTime gameTime)
for (int i = 0; i < 4; i++)
{
m_OldPadStates[i] = m_PadState[i];
m_PadState[i] = GamePad.GetState((PlayerIndex)i);
}
}

 

次に、コントローラーが切断されたかを確認するメソッドを実装します。

 

public bool WasDisconnected(PlayerIndex index)
{
return ( !m_PadState[(int)index].IsConnected && m_OldPadStates[(int)index].IsConnected );
}

 

後は、実装したメソッドを呼び出すだけです。

 

if (WasDisconnected(PlayerIndex.One))
{
// ゲームをポーズする・・・?
}

 

今回は以上です。

本来ならばこの処理はイベント型にした方がいい気がしますが、それはまたの機会と言うことにしておきます(その機会が来ない気もしますが・・・)。

 

今回は、前回紹介したコントローラーの振動方法に、タイマーを付けて自動的に振動を止める方法をメモります。

基本的にすることは、振動中はタイマーに経過時間を足し、設定した時間以上立っていれば振動を止めるだけです。

実装するにはまず、振動しているかを表すフラグ、タイマー、そして振動させる時間を保存する変数を宣言します。

float m_timer = 0.0f;            // 振動用のタイマー
bool m_isVibrating = false;      // 振動しているかどうか
float m_vibrationLength = 0.35f; // 振動している時間

次に、振動させ、タイマーなどを初期化する関数を作ります。この関数の第3引数は、何秒コントローラーを振動させるかを表します。

private void SetVibration(float left, float right, float length)
{
 GamePad.SetVibration(PlayerIndex.One, left, right);
 m_isVibrating = true;
 m_timer = 0.0f;
 m_vibrationLength = length;
}

次に、Update()メソッド内に、タイマーを更新し、止めるかどうかの判断をする処理を実装します。している事は、上で説明した物です。

// もし振動中なら
if (m_isVibrating)
{
 // タイマーに経過時間を足す
 m_timer += (float)gameTime.ElapsedGameTime.TotalSeconds;

 // タイマーが設定した時間になった時
 if (m_timer >= m_vibrationLength)
 {
 // 振動を止める
 GamePad.SetVibration(PlayerIndex.One, 0.0f, 0.0f);
 }
}

後は、SetVibration()メソッドを呼び、実際に振動させるだけです。

KeyboardState keystate = Keyboard.GetState();

if (keystate.IsKeyDown(Keys.Z))
{
 // コントローラー1を振動させる
 SetVibration(0.5f, 0.5f, 0.35f);
}

以上です。今回はコントローラー1に限定した実装なので、複数のコントローラーを使ったり、柔軟性を持たせたい場合は、変数を配列にしたり、SetVibration()メソッドにPlayerIndexを渡すようにしたりする事により実装できます。

今回は(も)短めのメモで、コントローラーを振動させる方法をメモります。

XBOXコントローラーを振動させるときは、GamePad.SetVibration()メソッドを使用します。

GamePad.SetVibration()メソッドの第1引数には、振動させるコントローラー、第2引数には左のモーターの振動値、第3引数は右のモーターの振動値です。モーターの振動値は、0.0f~1.0fの間である必要が有り、0.0fは0%、1.0fは100%で中間はそれに比例したパーセンテージで振動します。

それで実際に振動させる時は以下の用に書きます。

KeyboardState keystate = Keyboard.GetState();
if (keystate.IsKeyDown(Keys.Z))
{
GamePad.SetVibration(PlayerIndex.One, 0.5f, 0.5f);
}

これで最高の50%で振動します。ですが、このままだと振動しっ放しになるので、止める処理も必要です。その為には、GamePad.SetVibration()メソッドを呼び出し、第2と第3引数を0.0fにすれば止まります。

KeyboardState keystate = Keyboard.GetState();

if (keystate.IsKeyDown(Keys.Z))
{
GamePad.SetVibration(PlayerIndex.One, 0.5f, 0.5f);
}

if (keystate.IsKeyDown(Keys.X))
{
GamePad.SetVibration(PlayerIndex.One, 0.0f, 0.0f);
}

以上です。

このメモはXNA3.1とVisual Studio 2008でXBOX 以外のコントローラーを使う方法を説明します。

XNAではXinputでサポートされている種類以外のコントローラー(例えばPS2コントローラー)は使えません。コレにより、PC用のゲーム開発はマウス、キーボード、XBOX用コントローラに限定されるので少し面倒になります。それを解決するには基本的に、3種類の方法があります。

–          SlimDX等のライブラリを使う

–          Managed Directx(Direct Input)を使う

–          XBOX 360コントローラーのエミュレーターを使う

このメモでは、外部ライブラリを何となく使いたくなかったのでManaged Directxを使用しての再利用性のあるクラスを作る方法を残します。

 

まず、プロジェクトにMicrosoft.DirectX.DirectInputSystem.Windows.Formsの参照を足してください(System.Windows.FormsはMicrosoft.DirectX.DirectInput.Deviceクラスを初期化するために必要です)。

参照を足した後はまず、コントローラーへの参照を得るための初期化コードを書きます:

Device _pad;
JoystickState _padStates;

// 接続されている全てのゲーム用入力デバイスを獲得する
DeviceList deviceList = Manager.GetDevices( DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly );

//接続されているジョイパッドを探し、保存する

foreach ( DeviceInstance i in deviceList )
{
_pad = new Device( i.InstanceGuid );
if ( _pad )
break;
}

もしコントローラーの参照を得られれば、アナログスティックの戻り値の最高値を決めます:

// アナログスティックの戻り値の最高値を決める
foreach ( DeviceObjectInstance devObjIns in pad.Objects )
{
if ( ( devObjIns.ObjectId & (int)DeviceObjectTypeFlags.Axis ) != 0 )
    {
_pad.Properties.SetRange(ParameterHow.ById, devObjIns.ObjectId, new InputRange( -100, 100 ) );
}
}

デバイス(コントローラー)の設定を終了し、デバイスへのアクセスを取得します:

// セットアップ
_pad.Properties.AxisModeAbsolute = true;
_pad.SetCooperativeLevel( window.Handle, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background );
_pad.Acquire();

コントローラーの設定が終了した後、フレーム毎にコントローラの状態を更新し、保存するのを忘れないようにしてください(これが入力判定に使われるので):

public void Update()
{
 _pad.Poll();
 _padStates = _pad.CurrentJoystickState;
}

入力のテスト:


if ( _padStates.GetButtons()[0] != 0 )
{
  message = "ボタン 0 が押されています"
}

コレで動かすための基本的な事は終わりですが、この時点でプログラムを実行すると例外が投げられ、ちゃんと動きませんでした。

この例外はMDA(Managed Debugging Assistant)の一部に有るLoaderLockによって投げられたものです。詳しい事は今のところわからないのですが、この例外はManaged Directxが原因みたいです。この例外を回避するには、Visual Studio上でLoaderLockを無効にします。無効にするにはメニュー上から「デバッグー>例外・・・」に行き、LoaderLockの部分のチェックを外します。

これらが全て終わったら、動くはずです(今の所PS2コントローラーでのみ確認済み)。

 

ちなみに、コントローラー用のクラスを書いた時に実際に行った作業は結構省きましたので、クラスの中身に興味が有る方はプロジェクトへのリンク置いておくので(主にバックアップ用ですが)見てみてください。あと、プロジェクト内に有るクラスは複数のコントローラーをサポートする用に書きましたが、実際にコントローラーが一つしか無かったので、今の所はテストしていません。

プロジェクトへのリンク:

http://www.mediafire.com/download.php?ew06bbiz08drcp9

追記:sourcecodeと/sourcecodeを使用してソースコード貼り付けた時のインデント方法を知っている方が居たらコメントください m_ _m