ジョイパッドの入力状態を取得するプログラム
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ジョイパッドの入力状態を取得するプログラム
Xbox360コントローラならアナログ値をとれるのは、LRトリガーと2つのアナログスティックが取得出来ます。
LRトリガーは0 ~ 255、アナログスティックは -32768 ~ 32767の範囲の値です。
Windows用のゲームパッドでもアナログ値はありますよ。
今のプログラムは、強引にデジタル入力だけとして扱おうとしています。
LRトリガーは0 ~ 255、アナログスティックは -32768 ~ 32767の範囲の値です。
Windows用のゲームパッドでもアナログ値はありますよ。
今のプログラムは、強引にデジタル入力だけとして扱おうとしています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ジョイパッドの入力状態を取得するプログラム
アナログとデジタルを分けるというイメージでやってみましたが、もう少し簡単にわけれそうですね・・・考え中です。
Controller.h
Controller.cpp
main.cpp
Controller側のソースは短くなったのですが、逆に呼び出しの引数が2つになり、メイン側の呼び出しの楽差がなくなってしまっているので、
どうやって引数を一つで、まとめれるかを考え中です。
Controller.h
#pragma once
#pragma comment(lib,"XInput.lib")
#include <windows.h>
#include <Xinput.h>
class Controller
{
public:
enum PAD_STATE{
PAD_A = XINPUT_GAMEPAD_A, // Aボタン
PAD_B = XINPUT_GAMEPAD_B, // Bボタン
PAD_X = XINPUT_GAMEPAD_X, // Xボタン
PAD_Y = XINPUT_GAMEPAD_Y, // Yボタン
PAD_L_SHOULDER = XINPUT_GAMEPAD_LEFT_SHOULDER, // LB
PAD_R_SHOULDER = XINPUT_GAMEPAD_RIGHT_SHOULDER, // RB
PAD_BACK = XINPUT_GAMEPAD_BACK, // Back
PAD_START = XINPUT_GAMEPAD_START, // Start
PAD_LEFT_THUMB = XINPUT_GAMEPAD_LEFT_THUMB, // 左スティック
PAD_RIGHT_THUMB = XINPUT_GAMEPAD_RIGHT_THUMB, // 右スティック
PAD_LEFT_U_STICK, // 左スティックの上
PAD_LEFT_D_STICK, // 左スティックの下
PAD_LEFT_L_STICK, // 左スティックの左
PAD_LEFT_R_STICK, // 左スティックの右
PAD_RIGHT_U_STICK, // 右スティックの上
PAD_RIGHT_D_STICK, // 右スティックの下
PAD_RIGHT_L_STICK, // 右スティックの左
PAD_RIGHT_R_STICK, // 右スティックの右
PAD_L_TRIGGER, // 左トリガー
PAD_R_TRIGGER, // 右トリガー
PAD_UP = XINPUT_GAMEPAD_DPAD_UP, // 十字キーの上
PAD_DOWN = XINPUT_GAMEPAD_DPAD_DOWN, // 十字キーの下
PAD_LEFT = XINPUT_GAMEPAD_DPAD_LEFT, // 十字キーの左
PAD_RIGHT = XINPUT_GAMEPAD_DPAD_RIGHT,// 十字キーの右
};
enum INPUT_MODE{
DIGITAL,
ANALOG,
};
public:
Controller(int playerNum);
bool GetPadState(PAD_STATE p_state, INPUT_MODE mode);
private :
int _controllerNum;
};
#include "Controller.h"
Controller::Controller(int playerNum)
{
_controllerNum = playerNum -1;
}
bool Controller::GetPadState(PAD_STATE p_state, INPUT_MODE mode)
{
// 範囲指定用
int L_TRIGGER_DEADZONE = 100;
int R_TRIGGER_DEADZONE = 100;
int L_STICK_THUMB_DEAD = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
int R_STICK_THUMB_DEAD = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
XINPUT_STATE state; // コントローラ情報取得用
ZeroMemory( &state, sizeof(XINPUT_STATE) ); // 初期化
DWORD dwResult; // 関数結果判定用
// 情報取得
dwResult = XInputGetState(_controllerNum,&state);
if(dwResult == ERROR_SUCCESS){
switch(mode){
case DIGITAL:
if(state.Gamepad.wButtons & p_state){return true;}
break;
case ANALOG:
if(p_state == PAD_L_TRIGGER){
if(state.Gamepad.bLeftTrigger > L_TRIGGER_DEADZONE){return true;}
break;
}else if(p_state == PAD_R_TRIGGER){
if(state.Gamepad.bRightTrigger > R_TRIGGER_DEADZONE){return true;}
break;
}else if(p_state == PAD_LEFT_U_STICK){
if(state.Gamepad.sThumbLY > L_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_LEFT_D_STICK){
if(state.Gamepad.sThumbLY < -L_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_LEFT_R_STICK){
if(state.Gamepad.sThumbLX > L_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_LEFT_L_STICK){
if(state.Gamepad.sThumbLX < -L_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_RIGHT_U_STICK){
if(state.Gamepad.sThumbRY > R_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_RIGHT_D_STICK){
if(state.Gamepad.sThumbRY < -R_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_RIGHT_R_STICK){
if(state.Gamepad.sThumbRX > R_STICK_THUMB_DEAD ){return true;}
break;
}else if(p_state == PAD_RIGHT_L_STICK){
if(state.Gamepad.sThumbRX < -R_STICK_THUMB_DEAD ){return true;}
break;
}
break;
}
}
return false;
}
#include "Controller.h"
#include <iostream>
using namespace std;
Controller* control;
int main()
{
control = new Controller(1);
while(true)
{
if(control->GetPadState(control->PAD_LEFT_D_STICK, control->ANALOG))
{cout<<"左スティックの下が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_U_STICK, control->ANALOG))
{cout<<"左スティックの上が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_L_STICK, control->ANALOG))
{cout<<"左スティックの左が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_R_STICK, control->ANALOG))
{cout<<"左スティックの右が押されました。"<<endl;}
if(control->GetPadState(control->PAD_L_TRIGGER, control->ANALOG))
{cout<<"左トリガー押されました。"<<endl;}
if(control->GetPadState(control->PAD_R_TRIGGER, control->ANALOG))
{cout<<"右トリガー押されました。"<<endl;}
if(control->GetPadState(control->PAD_A, control->DIGITAL))
{cout<<"Aボタンが押されました。"<<endl;}
if(GetKeyState(VK_ESCAPE) & 0x80 )
{
break;
}
}
return 0;
}
どうやって引数を一つで、まとめれるかを考え中です。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ジョイパッドの入力状態を取得するプログラム
(1)アナログ入力をデジタルのように使いたいのなら使うときに引数でアナログを意識するもは面倒なだけです。
(2)アナログ入力はアナログで使いたいのならアナログ値を返さないとダメです。
つまり、(1)でも(2)でも無くどっちつかずだと思います。
ちなみに、(2)を共通のメンバ関数で実現するには無理があるので止めて下さい。
クラス側の都合が使うときに意識されると言うことは、クラスが抽象化の役割を果たしていないことになります。
XInputをわざわざクラスで包み隠しているのですから、XInputをそのまま使ったほうが分かりやすいというような事態は避けなければ行けません。
何のためのクラスなのかをよく考えてみて下さい。
※ だからと言ってクラスの1メンバ関数のコードが長くなるのは避けてくださいね。privateなメンバ関数も使い関数分割をしましょう。
(2)アナログ入力はアナログで使いたいのならアナログ値を返さないとダメです。
つまり、(1)でも(2)でも無くどっちつかずだと思います。
ちなみに、(2)を共通のメンバ関数で実現するには無理があるので止めて下さい。
クラス側の都合が使うときに意識されると言うことは、クラスが抽象化の役割を果たしていないことになります。
XInputをわざわざクラスで包み隠しているのですから、XInputをそのまま使ったほうが分かりやすいというような事態は避けなければ行けません。
何のためのクラスなのかをよく考えてみて下さい。
※ だからと言ってクラスの1メンバ関数のコードが長くなるのは避けてくださいね。privateなメンバ関数も使い関数分割をしましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ジョイパッドの入力状態を取得するプログラム
Xbox360のコントローラーに対応したプログラムでPS3のコントローラーを使いたいとき、PS3のコントローラーでXbox360のコントローラーを操作して、その入力を受け取るようにしたらプログラムを変更しなくて済みます。
Aボタンしか必要のないゲームでは、Aボタンしかないコントローラーを前提に作ればプログラムがシンプルになります。
実際に押されたのが何のボタンでも(あるいはボタンでなくても)、プログラムからはAボタンが押されたように見えれば良いわけです。
Aボタンしか必要のないゲームでは、Aボタンしかないコントローラーを前提に作ればプログラムがシンプルになります。
実際に押されたのが何のボタンでも(あるいはボタンでなくても)、プログラムからはAボタンが押されたように見えれば良いわけです。
Re: ジョイパッドの入力状態を取得するプログラム
GetPadStateのなかを関数で分け、アナログとデジタルをそれぞれ関数を持つようにしてみました。
Controller.h
Controller.cpp
質問なんですが、なぜアナログ値を返す必要があるのでしょうか?何に使うのですか?
あと、まだ(1)でも(2)でもない状態ですか?
Controller.h
#pragma once
#pragma comment(lib,"XInput.lib")
#include <windows.h>
#include <Xinput.h>
class Controller
{
public:
enum PAD_STATE{
PAD_A = XINPUT_GAMEPAD_A, // Aボタン
PAD_B = XINPUT_GAMEPAD_B, // Bボタン
PAD_X = XINPUT_GAMEPAD_X, // Xボタン
PAD_Y = XINPUT_GAMEPAD_Y, // Yボタン
PAD_L_SHOULDER = XINPUT_GAMEPAD_LEFT_SHOULDER, // LB
PAD_R_SHOULDER = XINPUT_GAMEPAD_RIGHT_SHOULDER, // RB
PAD_BACK = XINPUT_GAMEPAD_BACK, // Back
PAD_START = XINPUT_GAMEPAD_START, // Start
PAD_LEFT_THUMB = XINPUT_GAMEPAD_LEFT_THUMB, // 左スティック
PAD_RIGHT_THUMB = XINPUT_GAMEPAD_RIGHT_THUMB, // 右スティック
PAD_LEFT_U_STICK, // 左スティックの上
PAD_LEFT_D_STICK, // 左スティックの下
PAD_LEFT_L_STICK, // 左スティックの左
PAD_LEFT_R_STICK, // 左スティックの右
PAD_RIGHT_U_STICK, // 右スティックの上
PAD_RIGHT_D_STICK, // 右スティックの下
PAD_RIGHT_L_STICK, // 右スティックの左
PAD_RIGHT_R_STICK, // 右スティックの右
PAD_L_TRIGGER, // 左トリガー
PAD_R_TRIGGER, // 右トリガー
PAD_UP = XINPUT_GAMEPAD_DPAD_UP, // 十字キーの上
PAD_DOWN = XINPUT_GAMEPAD_DPAD_DOWN, // 十字キーの下
PAD_LEFT = XINPUT_GAMEPAD_DPAD_LEFT, // 十字キーの左
PAD_RIGHT = XINPUT_GAMEPAD_DPAD_RIGHT,// 十字キーの右
};
public:
Controller(int playerNum);
bool GetPadState(PAD_STATE p_state);
private :
int _controllerNum;
bool GetDigitalState(XINPUT_STATE state, PAD_STATE p_state);
bool GetAnalogState(XINPUT_STATE state, PAD_STATE p_state);
};
#include "Controller.h"
Controller::Controller(int playerNum)
{
_controllerNum = playerNum -1;
}
bool Controller::GetPadState(PAD_STATE p_state)
{
XINPUT_STATE state; // コントローラ情報取得用
ZeroMemory( &state, sizeof(XINPUT_STATE) ); // 初期化
DWORD dwResult; // 関数結果判定用
// 情報取得
dwResult = XInputGetState(_controllerNum,&state);
if(dwResult == ERROR_SUCCESS){
if(GetDigitalState(state,p_state)){return true;}
if(GetAnalogState(state,p_state)){return true;}
}
return false;
}
bool Controller::GetDigitalState(XINPUT_STATE state, PAD_STATE p_state)
{
if(state.Gamepad.wButtons & p_state){return true;}
return false;
}
bool Controller::GetAnalogState(XINPUT_STATE state, PAD_STATE p_state)
{
// 範囲指定用
int TRIGGER_DEADZONE = 100;
int L_STICK_THUMB_DEAD = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
int R_STICK_THUMB_DEAD = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
switch(p_state){
case PAD_L_TRIGGER:
if(state.Gamepad.bLeftTrigger > TRIGGER_DEADZONE){return true;}
break;
case PAD_R_TRIGGER:
if(state.Gamepad.bRightTrigger > TRIGGER_DEADZONE){return true;}
break;
case PAD_LEFT_U_STICK:
if(state.Gamepad.sThumbLY > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_D_STICK:
if(state.Gamepad.sThumbLY < -L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_R_STICK:
if(state.Gamepad.sThumbLX > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_L_STICK:
if(state.Gamepad.sThumbLX < -L_STICK_THUMB_DEAD ){
return true;
}
break;
case PAD_RIGHT_U_STICK:
if(state.Gamepad.sThumbRY > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_D_STICK:
if(state.Gamepad.sThumbRY < -R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_R_STICK:
if(state.Gamepad.sThumbRX > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_L_STICK:
if(state.Gamepad.sThumbRX < -R_STICK_THUMB_DEAD ){return true;}
break;
}
return false;
}
あと、まだ(1)でも(2)でもない状態ですか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ジョイパッドの入力状態を取得するプログラム
質問には作るクラスの用途が書いていないので確認したいんです。
3DのFPSなどを作るならアナログ入力は必須で2Dでもシューティングやアクションで照準用として使っているゲームなんかもありますよね。
それこそ、どうコントローラのクラスをmainなど呼び出し側から使うのかって事です。
今の時点で使わないし汎用的に後でも使えるようなクラスを目指さないなら必要無いわけです。
>あと、まだ(1)でも(2)でもない状態ですか?
(1)に隠蔽できたいと思いますよ。
それとパッドの有無を調べるメソッドも必要だと思いますが如何でしょう?
【補足】
気になるといえばenum の定義が一貫性に掛けててバグりそうな予感がする事とそれに関連して
if(GetDigitalState(state,p_state)){return true;}
if(GetAnalogState(state,p_state)){return true;}
の分岐方法がビットパターンによってバグになる気がするんですが確かめられてますか?
【さらに補足】
上でISLeさんがPSパッドでも兼用する事を書いてますが、このクラスをどう使うか決めるのはEKISUKEさんなんです。
なのでしっかりクラスの設計コンセプトを決めてください。
3DのFPSなどを作るならアナログ入力は必須で2Dでもシューティングやアクションで照準用として使っているゲームなんかもありますよね。
それこそ、どうコントローラのクラスをmainなど呼び出し側から使うのかって事です。
今の時点で使わないし汎用的に後でも使えるようなクラスを目指さないなら必要無いわけです。
>あと、まだ(1)でも(2)でもない状態ですか?
(1)に隠蔽できたいと思いますよ。
それとパッドの有無を調べるメソッドも必要だと思いますが如何でしょう?
【補足】
気になるといえばenum の定義が一貫性に掛けててバグりそうな予感がする事とそれに関連して
if(GetDigitalState(state,p_state)){return true;}
if(GetAnalogState(state,p_state)){return true;}
の分岐方法がビットパターンによってバグになる気がするんですが確かめられてますか?
【さらに補足】
上でISLeさんがPSパッドでも兼用する事を書いてますが、このクラスをどう使うか決めるのはEKISUKEさんなんです。
なのでしっかりクラスの設計コンセプトを決めてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ジョイパッドの入力状態を取得するプログラム
このプログラムを何に使うかと言いますと、学校の制作展に使います。softya(ソフト屋) さんが書きました:質問には作るクラスの用途が書いていないので確認したいんです。
3DのFPSなどを作るならアナログ入力は必須で2Dでもシューティングやアクションで照準用として使っているゲームなんかもありますよね。
それこそ、どうコントローラのクラスをmainなど呼び出し側から使うのかって事です。
今の時点で使わないし汎用的に後でも使えるようなクラスを目指さないなら必要無いわけです。
最近企画変更があり、コントローラーを使うということは決まっているのですが、
操作方法も詳しく決まっていないので、サンプルプログラムでも組んでみようと思って質問させていただいました。
今後コントローラーを使うゲームを作るとき、このソースコードを持っていくだけで出来ればいいと思っていますが、
他にも今取り組んでいる制作展で、やることはあるはずなので、そちらを優先しようと思っています。
なので、今回はアナログ値を返すプログラムはやめておきます。また、必要になった時に悩んだり、質問させていただくかと思います。
(2)にする場合どういうふうになったのでしょうか?教えていただければ幸いです。softya(ソフト屋) さんが書きました:(1)に隠蔽できたいと思いますよ。
それとパッドの有無を調べるメソッドも必要だと思いますが如何でしょう?
全部試してませんでした。十字キーなど色々バグがあったので、以下の様にしました。(長いです)softya(ソフト屋) さんが書きました:【補足】
気になるといえばenum の定義が一貫性に掛けててバグりそうな予感がする事とそれに関連して
if(GetDigitalState(state,p_state)){return true;}
if(GetAnalogState(state,p_state)){return true;}
の分岐方法がビットパターンによってバグになる気がするんですが確かめられてますか?
Controller.h
#pragma once
#pragma comment(lib,"XInput.lib")
#include <windows.h>
#include <Xinput.h>
class Controller
{
public:
enum PAD_STATE{
// デジタル
PAD_A, // Aボタン
PAD_B, // Bボタン
PAD_X, // Xボタン
PAD_Y, // Yボタン
PAD_L_SHOULDER, // LB
PAD_R_SHOULDER, // RB
PAD_BACK, // Back
PAD_START, // Start
PAD_UP, // 十字キーの上
PAD_DOWN, // 十字キーの下
PAD_LEFT, // 十字キーの左
PAD_RIGHT, // 十字キーの右
PAD_LEFT_THUMB, // 左スティック
PAD_RIGHT_THUMB, // 右スティック
// アナログ
PAD_LEFT_U_STICK, // 左スティックの上
PAD_LEFT_D_STICK, // 左スティックの下
PAD_LEFT_L_STICK, // 左スティックの左
PAD_LEFT_R_STICK, // 左スティックの右
PAD_RIGHT_U_STICK, // 右スティックの上
PAD_RIGHT_D_STICK, // 右スティックの下
PAD_RIGHT_L_STICK, // 右スティックの左
PAD_RIGHT_R_STICK, // 右スティックの右
PAD_L_TRIGGER, // 左トリガー
PAD_R_TRIGGER, // 右トリガー
};
enum MODE{
DIGITAL,
ANALOG,
};
public:
Controller(int playerNum);
bool IsConnected();
bool GetPadState(PAD_STATE p_state);
private :
int _controllerNum;
MODE mode;
bool GetDigitalState(XINPUT_STATE state, PAD_STATE p_state);
bool GetAnalogState(XINPUT_STATE state, PAD_STATE p_state);
void To_XInput(PAD_STATE &p_state);
void CheckMode(PAD_STATE p_state);
};
#include "Controller.h"
Controller::Controller(int playerNum)
{
_controllerNum = playerNum -1;
}
bool Controller::IsConnected()
{
XINPUT_STATE state; // コントローラ情報取得用
// 初期化
ZeroMemory( &state, sizeof(XINPUT_STATE) );
// 状態取得
DWORD Result = XInputGetState(_controllerNum, &state);
if(Result == ERROR_SUCCESS){
return true; // 接続されています。
}else{
return false; // 接続されていません。
}
}
bool Controller::GetPadState(PAD_STATE p_state)
{
XINPUT_STATE state; // コントローラ情報取得用
ZeroMemory( &state, sizeof(XINPUT_STATE) ); // 初期化
DWORD dwResult; // 関数結果判定用
// 情報取得
dwResult = XInputGetState(_controllerNum,&state);
if(dwResult == ERROR_SUCCESS){
CheckMode(p_state);
switch(mode){
case ANALOG:
if(GetAnalogState(state,p_state)){return true;}
break;
case DIGITAL:
if(GetDigitalState(state,p_state)){return true;}
break;
}
}
return false;
}
bool Controller::GetDigitalState(XINPUT_STATE state, PAD_STATE p_state)
{
To_XInput(p_state);
if(state.Gamepad.wButtons & p_state){return true;}
return false;
}
bool Controller::GetAnalogState(XINPUT_STATE state, PAD_STATE p_state)
{
// 範囲指定用
int TRIGGER_DEADZONE = 100;
int L_STICK_THUMB_DEAD = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
int R_STICK_THUMB_DEAD = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
switch(p_state){
case PAD_L_TRIGGER:
if(state.Gamepad.bLeftTrigger > TRIGGER_DEADZONE){return true;}
break;
case PAD_R_TRIGGER:
if(state.Gamepad.bRightTrigger > TRIGGER_DEADZONE){return true;}
break;
case PAD_LEFT_U_STICK:
if(state.Gamepad.sThumbLY > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_D_STICK:
if(state.Gamepad.sThumbLY < -L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_R_STICK:
if(state.Gamepad.sThumbLX > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_L_STICK:
if(state.Gamepad.sThumbLX < -L_STICK_THUMB_DEAD ){
return true;
}
break;
case PAD_RIGHT_U_STICK:
if(state.Gamepad.sThumbRY > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_D_STICK:
if(state.Gamepad.sThumbRY < -R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_R_STICK:
if(state.Gamepad.sThumbRX > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_L_STICK:
if(state.Gamepad.sThumbRX < -R_STICK_THUMB_DEAD ){return true;}
break;
}
return false;
}
void Controller::To_XInput(PAD_STATE &p_state)
{
switch(p_state){
case PAD_A:
p_state = (PAD_STATE)XINPUT_GAMEPAD_A;
break;
case PAD_B:
p_state = (PAD_STATE)XINPUT_GAMEPAD_B;
break;
case PAD_X:
p_state = (PAD_STATE)XINPUT_GAMEPAD_X;
break;
case PAD_Y:
p_state = (PAD_STATE)XINPUT_GAMEPAD_Y;
break;
case PAD_L_SHOULDER:
p_state = (PAD_STATE)XINPUT_GAMEPAD_LEFT_SHOULDER;
break;
case PAD_R_SHOULDER:
p_state = (PAD_STATE)XINPUT_GAMEPAD_RIGHT_SHOULDER;
break;
case PAD_BACK:
p_state = (PAD_STATE)XINPUT_GAMEPAD_BACK;
break;
case PAD_START:
p_state = (PAD_STATE)XINPUT_GAMEPAD_START;
break;
case PAD_UP:
p_state = (PAD_STATE)XINPUT_GAMEPAD_DPAD_UP;
break;
case PAD_DOWN:
p_state = (PAD_STATE)XINPUT_GAMEPAD_DPAD_DOWN;
break;
case PAD_LEFT:
p_state = (PAD_STATE)XINPUT_GAMEPAD_DPAD_LEFT;
break;
case PAD_RIGHT:
p_state = (PAD_STATE)XINPUT_GAMEPAD_DPAD_RIGHT;
break;
case PAD_LEFT_THUMB:
p_state = (PAD_STATE)XINPUT_GAMEPAD_LEFT_THUMB;
break;
case PAD_RIGHT_THUMB:
p_state = (PAD_STATE)XINPUT_GAMEPAD_RIGHT_THUMB;
break;
}
}
void Controller::CheckMode(PAD_STATE p_state){
switch(p_state){
case PAD_LEFT_U_STICK:
case PAD_LEFT_D_STICK:
case PAD_LEFT_L_STICK:
case PAD_LEFT_R_STICK:
case PAD_RIGHT_U_STICK:
case PAD_RIGHT_D_STICK:
case PAD_RIGHT_L_STICK:
case PAD_RIGHT_R_STICK:
case PAD_L_TRIGGER:
case PAD_R_TRIGGER:
mode = ANALOG; // アナログモード
break;
default:
mode = DIGITAL; // デジタルモード
break;
}
}
#include "Controller.h"
#include <iostream>
using namespace std;
Controller* control;
int main()
{
control = new Controller(1);
// 接続情報取得
if(control->IsConnected()==false)
{cout<<"コントローラーが接続されていません。"<<endl;}
while(control->IsConnected())
{
//---- スティック
//---- 左
if(control->GetPadState(control->PAD_LEFT_D_STICK))
{cout<<"左スティックの下が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_U_STICK))
{cout<<"左スティックの上が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_L_STICK))
{cout<<"左スティックの左が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_R_STICK))
{cout<<"左スティックの右が押されました。"<<endl;}
//---- 右
if(control->GetPadState(control->PAD_RIGHT_D_STICK))
{cout<<"右スティックの下が押されました。"<<endl;}
if(control->GetPadState(control->PAD_RIGHT_U_STICK))
{cout<<"右スティックの上が押されました。"<<endl;}
if(control->GetPadState(control->PAD_RIGHT_L_STICK))
{cout<<"右スティックの左が押されました。"<<endl;}
if(control->GetPadState(control->PAD_RIGHT_R_STICK))
{cout<<"右スティックの右が押されました。"<<endl;}
//---- トリガー
if(control->GetPadState(control->PAD_L_TRIGGER))
{cout<<"左トリガー押されました。"<<endl;}
if(control->GetPadState(control->PAD_R_TRIGGER))
{cout<<"右トリガー押されました。"<<endl;}
//---- ボタン
if(control->GetPadState(control->PAD_A))
{cout<<"Aボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_B))
{cout<<"Bボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_X))
{cout<<"Xボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_Y))
{cout<<"Yボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_BACK))
{cout<<"Backボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_START))
{cout<<"Startボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT_THUMB))
{cout<<"左スティックボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_RIGHT_THUMB))
{cout<<"右スティックボタンが押されました。"<<endl;}
if(control->GetPadState(control->PAD_L_SHOULDER))
{cout<<"LBが押されました。"<<endl;}
if(control->GetPadState(control->PAD_R_SHOULDER))
{cout<<"RBが押されました。"<<endl;}
//---- 十字キー
if(control->GetPadState(control->PAD_UP))
{cout<<"十字キーの上が押されました。"<<endl;}
if(control->GetPadState(control->PAD_DOWN))
{cout<<"十字キーの下が押されました。"<<endl;}
if(control->GetPadState(control->PAD_LEFT))
{cout<<"十字キーの左が押されました。"<<endl;}
if(control->GetPadState(control->PAD_RIGHT))
{cout<<"十字キーの右が押されました。"<<endl;}
if(GetKeyState(VK_ESCAPE) & 0x80 )
{
break;
}
}
return 0;
}
そうですね、少し考えてみます。softya(ソフト屋) さんが書きました:【さらに補足】
上でISLeさんがPSパッドでも兼用する事を書いてますが、このクラスをどう使うか決めるのはEKISUKEさんなんです。
なのでしっかりクラスの設計コンセプトを決めてください。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ジョイパッドの入力状態を取得するプログラム
それがアナログ値を返すって事です。まぁメソッドを増やすことになるでしょう。EKISUKE さんが書きました:(2)にする場合どういうふうになったのでしょうか?教えていただければ幸いです。
どう返すかは工夫の余地あるところですね。 → つまり使い方を想定してインターフェイス設計しないといけません。
To_XInput()とCheckMode()は配列を使うと短く出来るかもと言っておきます。EKISUKE さんが書きました:まだプログラムとして、なにか指摘ありましたら、お願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ジョイパッドの入力状態を取得するプログラム
返信遅くなりました。
今回はコントローラーの入力もとれ、どこに持って行ってもすぐにコントローラーが使えるようなソースファイルが作れました。
なので、解決とさせて頂きます。
コードの長さを短縮させる方法は今やっている他のことが落ち着いてから、考えてみます。
回答ありがとうございました。
今回はコントローラーの入力もとれ、どこに持って行ってもすぐにコントローラーが使えるようなソースファイルが作れました。
なので、解決とさせて頂きます。
コードの長さを短縮させる方法は今やっている他のことが落ち着いてから、考えてみます。
回答ありがとうございました。
Re: ジョイパッドの入力状態を取得するプログラム
お久しぶりです。
すこしコントローラーの長かった部分を短縮してみました。
配列でのやり方が思い浮かばなかったので、違ったやり方ですが、これでできました。
Controller.h
Controller.cpp
XInputのボタンが10進数で10と11以外の時は16進数の0x001の左シフトでいけるようなのでそうしました。
そのため自前の列挙体もXInputと同じ並びにしました。
アナログかデジタルかは元の列挙体の並びをアナログとデジタルで分けているので、
デジタルの最後の列挙体の番号より大きければアナログ、そうでなければデジタルという分け方にしてみました。
すこしやり方が汚いと思うので、教えてほしいことがあります。
1 以前おっしゃっていた配列でのやり方というのはどのようなやり方なのでしょうか?
2 このやり方はプログラムとして悪いやり方ですか?
この2点を教えてください。
すこしコントローラーの長かった部分を短縮してみました。
配列でのやり方が思い浮かばなかったので、違ったやり方ですが、これでできました。
Controller.h
class Controller
{
public:
//! コマンド列挙体
//@{
enum PAD_STATE{
// デジタル
PAD_UP, // 十字キーの上
PAD_DOWN, // 十字キーの下
PAD_LEFT, // 十字キーの左
PAD_RIGHT, // 十字キーの右
PAD_START, // Start
PAD_BACK, // Back
PAD_LEFT_THUMB, // 左スティック
PAD_RIGHT_THUMB, // 右スティック
PAD_LB, // LB
PAD_RB, // RB
PAD_A, // Aボタン
PAD_B, // Bボタン
PAD_X, // Xボタン
PAD_Y, // Yボタン
// アナログ
PAD_LEFT_U_STICK, // 左スティックの上
PAD_LEFT_D_STICK, // 左スティックの下
PAD_LEFT_L_STICK, // 左スティックの左
PAD_LEFT_R_STICK, // 左スティックの右
PAD_RIGHT_U_STICK, // 右スティックの上
PAD_RIGHT_D_STICK, // 右スティックの下
PAD_RIGHT_L_STICK, // 右スティックの左
PAD_RIGHT_R_STICK, // 右スティックの右
PAD_LT, // 左トリガー
PAD_RT, // 右トリガー
};
//@}
//! 入力モード
//@{
enum MODE{
DIGITAL,
ANALOG,
};
public:
//! コンストラクタ
Controller(s32 playerNum);
//! 接続確認関数
bool IsConnected();
//! 入力チェック関数
bool GetPadState(PAD_STATE p_state);
//! 振動
void EnableVibration( f32 L_vib, f32 R_vib );
void DisableVibration();
private :
s32 _controllerNum; //!< 接続コントローラー数
MODE mode; //!< 入力モード
s32 XInputPadState[14]; //!< XInputのパッドの列挙が入っている
//! デジタルの入力チェック
bool GetDigitalState(XINPUT_STATE state, PAD_STATE p_state);
//! アナログの入力チェック
bool GetAnalogState(XINPUT_STATE state, PAD_STATE p_state);
//! XINPUTに変換
void To_XInput(PAD_STATE &p_state);
//! 入力モードチェック関数
void CheckMode(PAD_STATE p_state);
};
//--------------------------------------------------------------
//! コンストラクタ
//--------------------------------------------------------------
Controller::Controller(s32 playerNum)
{
_controllerNum = playerNum -1;
for( int i=0; i<16; i++ ){
// 配列番号用の変数
static int Index = 0;
if( i == 10 || i == 11 ){
continue;
}
XInputPadState[Index] = 0x001 << i;
// 次の番号へ
Index++;
}
}
//--------------------------------------------------------------
//! 接続確認
//--------------------------------------------------------------
bool Controller::IsConnected()
{
XINPUT_STATE state; // コントローラ情報取得用
// 初期化
ZeroMemory( &state, sizeof(XINPUT_STATE) );
// 状態取得
DWORD Result = XInputGetState(_controllerNum, &state);
if(Result == ERROR_SUCCESS){
return true; // 接続されています。
}else{
return false; // 接続されていません。
}
}
//--------------------------------------------------------------
//! 入力チェック
//--------------------------------------------------------------
bool Controller::GetPadState(PAD_STATE p_state)
{
XINPUT_STATE state; // コントローラ情報取得用
ZeroMemory( &state, sizeof(XINPUT_STATE) ); // 初期化
DWORD dwResult; // 関数結果判定用
// 情報取得
dwResult = XInputGetState(_controllerNum,&state);
if(dwResult == ERROR_SUCCESS){ // 情報がとれたら
CheckMode(p_state); // アナログモードかデジタルかチェック
// モードによって入力チェック切替
switch(mode){
case ANALOG: // アナログ
if(GetAnalogState(state,p_state)){return true;}
break;
case DIGITAL: // デジタル
if(GetDigitalState(state,p_state)){return true;}
break;
}
}
return false;
}
//--------------------------------------------------------------
//! デジタルの入力チェック
//--------------------------------------------------------------
bool Controller::GetDigitalState(XINPUT_STATE state, PAD_STATE p_state)
{
To_XInput(p_state); // XINPUTに変換
// 入力チェック
if(state.Gamepad.wButtons & p_state){return true;}
return false;
}
//--------------------------------------------------------------
//! アナログの入力チェック
//--------------------------------------------------------------
bool Controller::GetAnalogState(XINPUT_STATE state, PAD_STATE p_state)
{
// トリガーの入力無視範囲設定
int TRIGGER_DEADZONE = 100;
// スティックの入力無視判定設定
int L_STICK_THUMB_DEAD = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
int R_STICK_THUMB_DEAD = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
// 入力の状態によって入力チェック切替
switch(p_state){
// トリガー
case PAD_LT:
if(state.Gamepad.bLeftTrigger > TRIGGER_DEADZONE){return true;}
break;
case PAD_RT:
if(state.Gamepad.bRightTrigger > TRIGGER_DEADZONE){return true;}
break;
// 左スティック
case PAD_LEFT_U_STICK:
if(state.Gamepad.sThumbLY > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_D_STICK:
if(state.Gamepad.sThumbLY < -L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_R_STICK:
if(state.Gamepad.sThumbLX > L_STICK_THUMB_DEAD ){return true;}
break;
case PAD_LEFT_L_STICK:
if(state.Gamepad.sThumbLX < -L_STICK_THUMB_DEAD ){return true;}
break;
// 右スティック
case PAD_RIGHT_U_STICK:
if(state.Gamepad.sThumbRY > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_D_STICK:
if(state.Gamepad.sThumbRY < -R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_R_STICK:
if(state.Gamepad.sThumbRX > R_STICK_THUMB_DEAD ){return true;}
break;
case PAD_RIGHT_L_STICK:
if(state.Gamepad.sThumbRX < -R_STICK_THUMB_DEAD ){return true;}
break;
}
return false;
}
//--------------------------------------------------------------
//! XINPUTに変換
//--------------------------------------------------------------
void Controller::To_XInput(PAD_STATE &p_state)
{
// 入力状態によってその後の処理切替
p_state = (PAD_STATE)XInputPadState[p_state];
}
//--------------------------------------------------------------
//! 入力モードチェック
//--------------------------------------------------------------
void Controller::CheckMode(PAD_STATE p_state){
int stateNum = p_state;
int LastDigitalNum = PAD_Y;
if( stateNum > LastDigitalNum ){
mode = ANALOG;
}else{
mode = DIGITAL;
}
}
//--------------------------------------------------------------
//! 振動開始
//! @param [in] L_vib 左振動値(0.0f ~ 1.0f)
//! @param [in] R_vib 右振動値(0.0f ~ 1.0f)
//--------------------------------------------------------------
void Controller::EnableVibration( f32 L_vib, f32 R_vib )
{
// 振動値を0.0~1.0fから 0 ~ 65535に変換
L_vib = 65535 * L_vib;
R_vib = 65535 * R_vib;
// 振動用の構造体
XINPUT_VIBRATION vibration;
// 初期化
ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );
// 振動値代入
vibration.wLeftMotorSpeed = L_vib;
vibration.wRightMotorSpeed = R_vib;
// 結果転送
XInputSetState( _controllerNum, &vibration);
}
//--------------------------------------------------------------
//! 振動停止
//--------------------------------------------------------------
void Controller::DisableVibration()
{
// 振動用の構造体
XINPUT_VIBRATION vibration;
// 初期化
ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );
// 振動値代入
vibration.wLeftMotorSpeed = 0;
vibration.wRightMotorSpeed = 0;
// 結果転送
XInputSetState( _controllerNum, &vibration);
}
そのため自前の列挙体もXInputと同じ並びにしました。
アナログかデジタルかは元の列挙体の並びをアナログとデジタルで分けているので、
デジタルの最後の列挙体の番号より大きければアナログ、そうでなければデジタルという分け方にしてみました。
すこしやり方が汚いと思うので、教えてほしいことがあります。
1 以前おっしゃっていた配列でのやり方というのはどのようなやり方なのでしょうか?
2 このやり方はプログラムとして悪いやり方ですか?
この2点を教えてください。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ジョイパッドの入力状態を取得するプログラム
前よりスッキリしたと思います。
これ以上は無理して縮める必要はないんじゃないでしょうか。
これ以上は無理して縮める必要はないんじゃないでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。