ジョイパッドの入力状態を取得するプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
EKISUKE
記事: 108
登録日時: 13年前

ジョイパッドの入力状態を取得するプログラム

#1

投稿記事 by EKISUKE » 12年前

ジョイパッドの入力を取得するプログラムをC++のみで出来ますか?
調べてるとDXライブラリを使ったものは出てくるのですが、C++のみで取得することはできないのでしょうか?
それとXbox360コントローラーの入力の取得や、振動、などもしたいので、XInputも勉強したいのですが、C++で参考になるサイトがあれば教えて欲しいです。
回答お願いします。

nil
記事: 428
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#2

投稿記事 by nil » 12年前

C++のみで可能かどうかは分かりませんが、
XInputやDirectInputを用いれば可能です。
MSDNにはXInputやDirectInputも載っています。
DirectInputは情報が多いので、検索すればすぐにいろいろ出てきます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#3

投稿記事 by softya(ソフト屋) » 12年前

C++単体ではパッドにアクセスすることはできません。
そこはDirectXAPIなり、Win32APIなどを使う必要性があります。

「joyGetPosEx 関数」 Win32APIの場合。
http://msdn.microsoft.com/ja-jp/library/cc410475.aspx

XInputは名前の通りDirectXの機能の一部です。ここが参考になるでしょう。
「XInput」
http://msdn.microsoft.com/ja-jp/library ... s.85).aspx

Xbox360コントローラがどの様なドライバで動いているかわかりませんので動作を確認してみてください。
※ 公式・非公式のドライバがあるのと、コントローラ自体もWindows正式版とX360専用板があるため

【補足】
>DirectInputは情報が多いので、検索すればすぐにいろいろ出てきます。
DirectInputはXbox360コントローラをフル活用する気なら問題があると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#4

投稿記事 by EKISUKE » 12年前

softya(ソフト屋) さんが書きました:C++単体ではパッドにアクセスすることはできません。
そこはDirectXAPIなり、Win32APIなどを使う必要性があります。

「joyGetPosEx 関数」 Win32APIの場合。
http://msdn.microsoft.com/ja-jp/library/cc410475.aspx

XInputは名前の通りDirectXの機能の一部です。ここが参考になるでしょう。
「XInput」
http://msdn.microsoft.com/ja-jp/library ... 44(v=vs.85).aspx

Xbox360コントローラがどの様なドライバで動いているかわかりませんので動作を確認してみてください。
XInputの方のサイトが見つからないようです・・・

Xbox360コントローラーはfor Windowsのものを使用しています。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#5

投稿記事 by softya(ソフト屋) » 12年前

失礼しました。後半がリンクと見なされなかったようです。マイクロソフトでよくあるんですよね。
http://msdn.microsoft.com/ja-jp/library ... s.85).aspx
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

naohiro19
記事: 256
登録日時: 15年前
住所: 愛知県

Re: ジョイパッドの入力状態を取得するプログラム

#6

投稿記事 by naohiro19 » 12年前

Xbox360コントローラはDirectInputは非推奨になっているようなのでXInputを使うしかありません。
それ以外のコントローラはDirectInputで使用できます。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#7

投稿記事 by EKISUKE » 12年前

とりあえず、普通のコントローラーも持っているので、
普通のコントローラーの入力を取得したいと思います。

なのでWin32APIのサイトを見たのですが、どういうふうに状態を取得して、使えばいいのかがわかりません。
一応プログラムを組んでは見たのですが、MMSystem.hのほうでエラーが出ます。

多分、こういう感じではないと思うので、サンプルプログラムが乗っているサイトがあれば教えて欲しいです。
上記のサイトだけでは理解できませんでした。すみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#8

投稿記事 by softya(ソフト屋) » 12年前

そのエラーが出るコードとエラーメッセージを見せてもらったほうが早そうです。
私が検索してもEKISUKEさんが検索しても見つかるものは大差ないはずですからね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#9

投稿記事 by EKISUKE » 12年前

今書いた分はこれだけです。

Controller.h

コード:

#pragma once
#include <MMSystem.h>

class Controller
{
public:
	LPJOYINFOEX pji;
};
エラーは以下のものです。少し長いです。

1>------ ビルド開始: プロジェクト: Controller_sample, 構成: Debug Win32 ------
1> main.cpp
1> Controller.cpp
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(105): error C2146: 構文エラー : ';' が、識別子 'MMVERSION' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(105): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(105): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(109): error C2059: 構文エラー : 'return'
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(113): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(113): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(123): error C2146: 構文エラー : ';' が、識別子 'ms' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(123): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(123): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(124): error C2146: 構文エラー : ';' が、識別子 'sample' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(124): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(124): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(125): error C2146: 構文エラー : ';' が、識別子 'cb' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(125): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(125): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(126): error C2146: 構文エラー : ';' が、識別子 'ticks' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(126): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(126): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(131): error C2146: 構文エラー : ';' が、識別子 'hour' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(131): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(131): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(132): error C2146: 構文エラー : ';' が、識別子 'min' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(132): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(132): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(133): error C2146: 構文エラー : ';' が、識別子 'sec' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(133): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(133): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(134): error C2146: 構文エラー : ';' が、識別子 'frame' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(134): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(134): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(135): error C2146: 構文エラー : ';' が、識別子 'fps' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(135): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(135): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(136): error C2146: 構文エラー : ';' が、識別子 'dummy' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(136): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(136): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(138): error C2146: 構文エラー : ';' が、識別子 'pad' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(138): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(138): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(145): error C2146: 構文エラー : ';' が、識別子 'songptrpos' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(145): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(145): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C2377: 'FAR' : 再定義されています。typedef は他のどのシンボルでもオーバーロードできません
1> c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(113) : 'FAR' の宣言を確認してください。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(287): error C2065: 'HDRVR' : 定義されていない識別子です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(287): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(300): error C2146: 構文エラー : ';' が、識別子 'dwDCISize' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(300): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(300): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(301): error C2146: 構文エラー : ';' が、識別子 'lpszDCISectionName' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(301): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(301): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(302): error C2146: 構文エラー : ';' が、識別子 'lpszDCIAliasName' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(302): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(302): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(303): error C2146: 構文エラー : ';' が、識別子 'dnDevNode' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(303): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(303): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C2371: 'NEAR' : 再定義されています。異なる基本型です。
1> c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148) : 'NEAR' の宣言を確認してください。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C2086: 'int FAR' : 再定義されました。
1> c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148) : 'FAR' の宣言を確認してください。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(304): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(338): error C2146: 構文エラー : ';' が、識別子 'dwDCISize' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(338): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(338): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(339): error C2146: 構文エラー : ';' が、識別子 'lpszDCISectionName' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(339): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(339): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(340): error C2146: 構文エラー : ';' が、識別子 'lpszDCIAliasName' の前に必要です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(340): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(340): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C2371: 'NEAR' : 再定義されています。異なる基本型です。
1> c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148) : 'NEAR' の宣言を確認してください。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C2143: 構文エラー : ';' が '*' の前にありません。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C2086: 'int FAR' : 再定義されました。
1> c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(148) : 'FAR' の宣言を確認してください。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(341): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(358): error C2065: 'CALLBACK' : 定義されていない識別子です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(358): error C2065: 'DRIVERPROC' : 定義されていない識別子です。
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(358): error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
1>c:\program files\microsoft sdks\windows\v7.0a\include\mmsystem.h(358): fatal error C1903: 直前のエラーを修復できません。コンパイルを中止します。


まだプログラムが全然組めてなかったので載せてませんでした。すみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#10

投稿記事 by softya(ソフト屋) » 12年前

#include <windows.h>

#include <MMSystem.h>
の前に必要です。

それと
#include <mmsystem.h>
が正しいです。Windowsのファイルシステムは大文字小文字は区別しませんけどね。
あとで混乱を招くことはしない方です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#11

投稿記事 by EKISUKE » 12年前

ありがとうございます。
先ほどのエラーはなくなりました。

とりあえず、今入力されているボタンをcoutで表示しようと思って、プログラムを組んでみたのですが、エラーが出てしまいます。
あと、このような感じであってるのでしょうか?

Controller.h

コード:

#pragma once
#include <windows.h>
#include <mmsystem.h>
class Controller
{
public:
	Controller();
	~Controller();
	void update();
private:
	UINT		uJoyID;
	LPJOYINFOEX pji;
};
Controller.cpp

コード:

#include <iostream>
using namespace std;
#include "Controller.h"

Controller::Controller()
{
	
}

Controller::~Controller()
{
}

void Controller::update()
{	
	switch(joyGetPosEx(uJoyID,pji)){
	case MMSYSERR_NODRIVER:
		// ドライバが存在しません。
		break;
	case MMSYSERR_INVALPARAM:
		// 無効なパラメーターが渡されました。
		break;
	case MMSYSERR_BADDEVICEID:
		// 指定されたジョイスティック識別子は無効です。
		break;
	case JOYERR_UNPLUGGED:
		// 指定されたジョイスティックはシステムに接続されていません。
		break;
	default:
		// 成功
		cout<< pji->dwButtons <<endl;
		break;
	}
}
main.cpp

コード:

#include "Controller.h"
Controller	control;
int main()
{
	control.update();
	return 0;
}
エラー
1>Controller.obj : error LNK2019: 未解決の外部シンボル __imp__joyGetPosEx@8 が関数 "public: void __thiscall Controller::update(void)" (?update@Controller@@QAEXXZ) で参照されました。

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: ジョイパッドの入力状態を取得するプログラム

#12

投稿記事 by へにっくす » 12年前

1>Controller.obj : error LNK2019: 未解決の外部シンボル __imp__joyGetPosEx@8 が関数 "public: void __thiscall Controller::update(void)" (?update@Controller@@QAEXXZ) で参照されました。
未解決のシンボルと出たら、大抵はライブラリがないか、関数を定義していないかのどちらかです。
今回の場合はwinmm.libを追加ライブラリに指定していないからでしょう。
ジョイスティックで入力しよう
検索する癖をつけた方がよいですよ?
written by へにっくす

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#13

投稿記事 by EKISUKE » 12年前

へにっくす さんが書きました:
1>Controller.obj : error LNK2019: 未解決の外部シンボル __imp__joyGetPosEx@8 が関数 "public: void __thiscall Controller::update(void)" (?update@Controller@@QAEXXZ) で参照されました。
未解決のシンボルと出たら、大抵はライブラリがないか、関数を定義していないかのどちらかです。
今回の場合はwinmm.libを追加ライブラリに指定していないからでしょう。
ジョイスティックで入力しよう
ありがとうございます。一応joyGetPosの方での入力はできました。
しかし、joyGetPosの方では右スティックと十字キーの入力が取得できないようなので、
joyGetPosExを使おうと思って調べて見たのですが、次のサイトのコードがいまいち理解できないです。

http://lesson.ifdef.jp/A05.html

このサイトの以下の部分がわからないです。

コード:

if((joyinfo.dwPOV > JOY_POVLEFT)
	|| (joyinfo.dwPOV < JOY_POVRIGHT) )
{
		pos |= 0x01;//UP
}
pos |= 0x01;というのは何をしているのでしょうか?
今はこの状態だと十字キーの上が押されたという認識でプログラムを組んでます・・・
へにっくす さんが書きました:検索する癖をつけた方がよいですよ?
すみません。検索はしているのですが・・自分の理解できるサイトをうまく見つけれなくて、質問させていただきました。
もっと、調べるようにします。

それといま組んでいるプログラムは以下の通りです。

Controller.h

コード:

#pragma once
#include <windows.h>
#include <mmsystem.h>
class Controller
{
public:
	Controller();
	~Controller();
	int	 init();
	void update();
private:
	JOYINFOEX	joyinfo;
	UINT		wNumDevs,wDeviceID;
	BOOL		bDev1Attached,bDev2Attached;
	MMRESULT	result;
	LPJOYINFOEX pji;
	int			pos;
};
Controller.cpp

コード:

#include <iostream>
using namespace std;
#include "Controller.h"

Controller::Controller()
{
	
}

Controller::~Controller()
{
}

int Controller::init()
{
	if(joyGetNumDevs()==0)
		return -1;	// デバイスなし
	if(joyGetPosEx(JOYSTICKID1, &joyinfo) == JOYERR_UNPLUGGED)
		return -2;	// 接続なし
	// 取得する情報をセット
	joyinfo.dwSize = sizeof(JOYINFOEX);
	joyinfo.dwFlags = JOY_RETURNALL;
#if 0
	if((wNumDevs = joyGetNumDevs()) == 0)
		return -1; // ドライバーがない

	bDev1Attached = joyGetPos(JOYSTICKID1, &joyinfo) != JOYERR_UNPLUGGED;
	bDev2Attached = wNumDevs == 2 && joyGetPos(JOYSTICKID2, &joyinfo) != JOYERR_UNPLUGGED;

	if(bDev1Attached || bDev2Attached)	{//	どのjoysticIDを使うか決定する
		wDeviceID = bDev1Attached ? JOYSTICKID1 : JOYSTICKID2;
	}else{
		return -2;	// joystickがつながっていない
	}
#endif
}

void Controller::update()
{	
	result = joyGetPosEx(wDeviceID,&joyinfo);

	if( result == JOYERR_NOERROR ){

		if(joyinfo.dwPOV != JOY_POVCENTERED )
		{
			if((joyinfo.dwPOV > JOY_POVLEFT)
				||(joyinfo.dwPOV < JOY_POVRIGHT) )
			{
				MessageBox(0,"十字キーの上","",MB_OK);
			}
		}
	}
#if 0
	MMRESULT r = joyGetPos(wDeviceID,&joyinfo);
	if(r==JOYERR_NOERROR)
	{
		// ボタン
		if(joyinfo.wButtons & JOY_BUTTON1)
		{
			MessageBox(0,"ボタン1が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON2)
		{
			MessageBox(0,"ボタン2が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON3)
		{
			MessageBox(0,"ボタン3が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON4)
		{
			MessageBox(0,"ボタン4が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON5)
		{
			MessageBox(0,"ボタン5が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON6)
		{
			MessageBox(0,"ボタン6が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON7)
		{
			MessageBox(0,"ボタン7が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON8)
		{
			MessageBox(0,"ボタン8が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON9)
		{
			MessageBox(0,"ボタン9が押されました","",MB_OK);
		}
		if(joyinfo.wButtons & JOY_BUTTON10)
		{
			MessageBox(0,"ボタン10が押されました","",MB_OK);
		}
		
		//方向パッド
		if(joyinfo.wButtons& JOY_POVRIGHT)
		{
			MessageBox(0,"右キーが押されました","",MB_OK);
		}
		// 左スティック
		if(joyinfo.wXpos>0xbfff)
		{
			MessageBox(0,"左スティックの右","",MB_OK);
		}
		if(joyinfo.wXpos<0x3fff)
		{
			MessageBox(0,"左スティックの左","",MB_OK);
		}
		if(joyinfo.wYpos<0x3fff)
		{
			MessageBox(0,"左スティックの上","",MB_OK);
		}
		if(joyinfo.wYpos>0xbfff)
		{
			MessageBox(0,"左スティックの下","",MB_OK);
		}
	
		// トリガー
		if(joyinfo.wZpos<0x3fff)
		{
			MessageBox(0,"右トリガーが押されました","",MB_OK);
		}
		if(joyinfo.wZpos>0xbfff)
		{
			MessageBox(0,"左トリガーが押されました","",MB_OK);
		}
	}
#endif
}
上の状態だとresultの値がjoyGetPosExを使うと165という値が返って来ていて、
if( result == JOYERR_NOERROR )の部分をマスクすると、if((joyinfo.dwPOV > JOY_POVLEFT)||(joyinfo.dwPOV < JOY_POVRIGHT) )このif文が通ってしまいます。

下の#if0 の中の if(joyinfo.wButtons & JOY_BUTTON1) の部分を
if(joyinfo.dwButtons & JOY_BUTTON1)と変えてみたりしたのですが、それだとこのif文が通ってしまいます。
joyGetPos関数とjoyGetPosExとでは全然扱いが異なるのでしょうか・・・?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#14

投稿記事 by softya(ソフト屋) » 12年前

まず、調べ方を説明します。
dwPOV を理解しないといけないので、これをキーワードで検索しましょう。
それとdwPOV の値を表示してみたりして値とパッドの関係を色々と調べます。
そのものズバリのサンプルコードを探してばかりで、説明が書いてあるサイトなどから理解しようとしていない感じがします。
これはツマヅキますし、未知のものにチャンレジできません。
MSDNしか情報がないものもたくさんあるんですよ。

>JoyGetPosExを使うと165

それはエラーです。
私のリンクのMSDNの説明をちゃんと読んでいないと思います。

[補足]
ローカル変数で構わないものを無闇にprivate変数にするのもグローバル変数と同じぐらい悪いクセだとおもいます。
joyinfoってprivate変数にするひつようがありますでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#15

投稿記事 by EKISUKE » 12年前

JoyGetPosExのエラーは、initの方で設定していたので、なぜエラーが出るのか悩んでいましたが・・・int main の方で読んでいないだけでした。
上のわからなかった条件式も、dwPOVについて調べればわかることでした。すみません。
softya(ソフト屋) さんが書きました:そのものズバリのサンプルコードを探してばかりで、説明が書いてあるサイトなどから理解しようとしていない感じがします。
これはツマヅキますし、未知のものにチャンレジできません。
MSDNしか情報がないものもたくさんあるんですよ。
そうですね、すみません。聞いてばかりでした。
softya(ソフト屋) さんが書きました:[補足]
ローカル変数で構わないものを無闇にprivate変数にするのもグローバル変数と同じぐらい悪いクセだとおもいます。
joyinfoってprivate変数にするひつようがありますでしょうか?
クラスのメンバはprivateにできるだけすべきというふうに認識をしていたのでprivateにしていました。
そこら辺は自分で判断すべきなのでしょうが、調べずに理解できていなかったため、privateにしていたと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#16

投稿記事 by softya(ソフト屋) » 12年前

厳しいことを書きましたが、未知のものにチャンジする以上は良く分からないのは当たり前なんです。
ここで回答している人も分からないものを理解するために色々考えながら突破してきたわけですが、今回はアプローチの仕方を変えれば分かってくることも見えていないようなので書かせていただきました。このアプローチの方法を色々考えるのはアルゴリズムを考えたりプログラムをデバッグ出来るかどうかの能力とも関わってきます。
鍛えることで伸びるので考えるの止めるのが一番上達を妨げると思いますよ。なのでヒントを頼りできるだけ考えてみて下さい。

探している途中で目にするものも無駄にならないですし別のことのヒントにもなります。
未知のものでも大抵はヒントは転がっています。
がんばってください。

それでも分からなかったら、そこまで調べたことも含めて記載して質問して下さい。そうすれば回答者の手間も減るので回答が得やすくなります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#17

投稿記事 by EKISUKE » 12年前

softya(ソフト屋) さんが書きました:厳しいことを書きましたが、未知のものにチャンジする以上は良く分からないのは当たり前なんです。
ここで回答している人も分からないものを理解するために色々考えながら突破してきたわけですが、今回はアプローチの仕方を変えれば分かってくることも見えていないようなので書かせていただきました。このアプローチの方法を色々考えるのはアルゴリズムを考えたりプログラムをデバッグ出来るかどうかの能力とも関わってきます。
鍛えることで伸びるので考えるの止めるのが一番上達を妨げると思いますよ。なのでヒントを頼りできるだけ考えてみて下さい。

探している途中で目にするものも無駄にならないですし別のことのヒントにもなります。
未知のものでも大抵はヒントは転がっています。
がんばってください。

それでも分からなかったら、そこまで調べたことも含めて記載して質問して下さい。そうすれば回答者の手間も減るので回答が得やすくなります。
ありがとうございます。
おかげさまで、コントローラーの入力を取得することができました。

今のコードの状態は以下です。(Xbox360 for windowsでやってます)
Controller.h

コード:

#pragma once
#include <windows.h>
#include <mmsystem.h>
class Controller
{
public:
	Controller();
	~Controller();
	int	 init();
	void update();
};
Controller.cpp

コード:

#include <iostream>
using namespace std;
#include "Controller.h"

JOYINFOEX	joyinfo;
Controller::Controller()
{
	
}

Controller::~Controller()
{
}

int Controller::init()
{
	if(joyGetNumDevs()==0)
		return -1;	// デバイスなし
	if(joyGetPosEx(JOYSTICKID1, &joyinfo) == JOYERR_UNPLUGGED)
		return -2;	// 接続なし
	// 取得する情報をセット
	joyinfo.dwSize = sizeof(JOYINFOEX);
	joyinfo.dwFlags = JOY_RETURNALL;
}

void Controller::update()
{	
	MMRESULT	result;
	UINT		wDeviceID = 0;
	result = joyGetPosEx(wDeviceID,&joyinfo);

	if( result == JOYERR_NOERROR ){


		// ボタン
		if(joyinfo.dwButtons & JOY_BUTTON1){MessageBox(0,"Aが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON2){MessageBox(0,"Bが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON3){MessageBox(0,"Xが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON4){MessageBox(0,"Yが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON5){MessageBox(0,"LBが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON6){MessageBox(0,"RBが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON7){MessageBox(0,"Backが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON8){MessageBox(0,"Startが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON9){MessageBox(0,"左スティックが押されました","",MB_OK);}
		if(joyinfo.dwButtons & JOY_BUTTON10){MessageBox(0,"右スティックが押されました","",MB_OK);}
		
		// 左スティック
		if(joyinfo.dwXpos>0xbfff){MessageBox(0,"左スティックの右","",MB_OK);}
		if(joyinfo.dwXpos<0x3fff){MessageBox(0,"左スティックの左","",MB_OK);}
		if(joyinfo.dwYpos<0x3fff){MessageBox(0,"左スティックの上","",MB_OK);}
		if(joyinfo.dwYpos>0xbfff){MessageBox(0,"左スティックの下","",MB_OK);}
		// 右スティック
		if(joyinfo.dwUpos>0xbfff){MessageBox(0,"右スティックの右","",MB_OK);}
		if(joyinfo.dwUpos<0x3fff){MessageBox(0,"右スティックの左","",MB_OK);}
		if(joyinfo.dwRpos<0x3fff){MessageBox(0,"右スティックの上","",MB_OK);}
		if(joyinfo.dwRpos>0xbfff){MessageBox(0,"右スティックの下","",MB_OK);}
		// トリガー
		if(joyinfo.dwZpos<0x3fff){MessageBox(0,"RTが押されました","",MB_OK);}
		if(joyinfo.dwZpos>0xbfff){MessageBox(0,"LTが押されました","",MB_OK);}

		if(joyinfo.dwPOV != JOY_POVCENTERED )
		{
			// 十字キー
			if((joyinfo.dwPOV > JOY_POVLEFT)
				||(joyinfo.dwPOV < JOY_POVRIGHT) )
			{
				MessageBox(0,"十字キーの上","",MB_OK);//UP
			}
			if((joyinfo.dwPOV > JOY_POVFORWARD)
				&& (joyinfo.dwPOV < JOY_POVBACKWARD) )
			{
				MessageBox(0,"十字キーの右","",MB_OK);//RIGHT
			}
			if((joyinfo.dwPOV > JOY_POVRIGHT) 
				&& (joyinfo.dwPOV < JOY_POVLEFT) )
			{
				MessageBox(0,"十字キーの下","",MB_OK);//DOWN
			}
			if(joyinfo.dwPOV > JOY_POVBACKWARD)
			{
				MessageBox(0,"十字キーの左","",MB_OK);//LEFT
			}
		}
	}
	//cout<<joyinfo.dwPOV<<endl;
}
main.cpp

コード:

#include "Controller.h"

Controller	control;
	
	
int main()
{
	control.init();
	while(true){
		control.update();
		if(GetKeyState(VK_ESCAPE) &0x80) break;
	}
	//return 0;
}
あとは、dwUposはたまたま入れてできたものなので、調べてみます。

XInputの方も調べながらやっていたらできたのですが、スティックの遊び?部分をマジックナンバーで入れているので、調べてやってみます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#18

投稿記事 by softya(ソフト屋) » 12年前

MSDNの説明によると「dwSize メンバおよび dwFlags メンバの値は必ず設定してください。設定しない場合、この関数は失敗します。」とあるのでController::init()のjoyGetPosEx()は違反していることになります。たまたま、うまく動いているようですが良くないです。
それとJOYINFOEX joyinfo;をグローバル変数にしたようですが、これだと複数のインスタンスを作れません。前にも書いた通りローカル変数で良いのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#19

投稿記事 by EKISUKE » 12年前

softya(ソフト屋) さんが書きました:MSDNの説明によると「dwSize メンバおよび dwFlags メンバの値は必ず設定してください。設定しない場合、この関数は失敗します。」とあるのでController::init()のjoyGetPosEx()は違反していることになります。たまたま、うまく動いているようですが良くないです。

コード:

int Controller::init()
{
	// 取得する情報をセット
	joyinfo.dwSize = sizeof(JOYINFOEX);
	joyinfo.dwFlags = JOY_RETURNALL;

	if(joyGetNumDevs()==0)
		return -1;	// デバイスなし
	if(joyGetPosEx(JOYSTICKID1, &joyinfo) == JOYERR_UNPLUGGED)
		return -2;	// 接続なし
}
こういうことですか?
softya(ソフト屋) さんが書きました:それとJOYINFOEX joyinfo;をグローバル変数にしたようですが、これだと複数のインスタンスを作れません。前にも書いた通りローカル変数で良いのでは?
すみません。ローカル変数というのはクラスの中に書くということですか・・?それともinit,updateにそれぞれ書くということですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#20

投稿記事 by softya(ソフト屋) » 12年前

MSDNに書いてあるとこに従えば、そう言うことになります。
元のままでも多分大丈夫でしょうが、わざわざバグる危険を犯すことも無いでしょう。
EKISUKE さんが書きました: すみません。ローカル変数というのはクラスの中に書くということですか・・?それともinit,updateにそれぞれ書くということですか?
ローカル変数というには関数の中に定義する変数のことです。つまり、init,updateにそれぞれ必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#21

投稿記事 by EKISUKE » 12年前

丁寧にありがとうございます。そうですね、バグの原因になりそうなことは、避けるべきですね。

あとdwUposについてですが、Xbox360コントローラーはdwZposをトリガーで使うため5つ目のdwUposを使わないといけないんですね。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#22

投稿記事 by EKISUKE » 12年前

教えてほしいことがあるのですが、さっきのコードをゲーム上で使うとき、どういうふうに導入するのがいいでしょうか?

使い方としてはGetKeyStateみたいな感じで使いたいのですが、その場合joyinfoををクラスのメンバにして、クラスを継承?かインスタンス化して

コード:

if(joyinfo.dwButtons & JOY_BUTTON1){
       // 行いたい処理
}
という風にするのがベストですか?それとも、対応する処理のキーをプログラムで入力できるようにして導入するのがベストでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#23

投稿記事 by softya(ソフト屋) » 12年前

XinputであるとかjoyGetPosEx であるとか使っているAPIの実体を隠すのがクラスの役目だと思います。
なので、元の素性はできるだけ隠すことを目標にしてください。

それとメンバ変数を表に出すと書き換えられるおそれがある(グローバル変数と同等になる)ので、演算子オーバーロードでクラスのインスタンス自体を変数に見せかけるとか、値を参照するためだけのメソッドを用意すべきだと思います。
クラス自体をシングルトンにして、唯一無二のインスタンスにしたほうが良いとも思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#24

投稿記事 by EKISUKE » 12年前

まだイメージがつかめず今はとりあえず、思いつくようにプログラムを組んでいるのですが、以下のプログラムで書き方としてまずいところを教えていただけないでしょうか?
XInputを使ってます。

Controll.h

コード:

#pragma once
#pragma comment(lib,"XInput.lib")
#include <windows.h>
#include <Xinput.h>
#include "KeyFunc.h"
class Controller
{
public:
	enum PAD_STATE{
		PAD_A			= XINPUT_GAMEPAD_A,
		PAD_B			= XINPUT_GAMEPAD_B,
		PAD_X			= XINPUT_GAMEPAD_X,
		PAD_Y			= XINPUT_GAMEPAD_Y,
		PAD_L_SHOULDER	= XINPUT_GAMEPAD_LEFT_SHOULDER,
		PAD_R_SHOULDER	= XINPUT_GAMEPAD_RIGHT_SHOULDER,
		PAD_BACK		= XINPUT_GAMEPAD_BACK,
		PAD_START		= XINPUT_GAMEPAD_START,
		PAD_LEFT_THUMB	= XINPUT_GAMEPAD_LEFT_THUMB,
		PAD_RIGHT_THUMB	= XINPUT_GAMEPAD_RIGHT_THUMB,
		PAD_T_STICK		= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE,
		PAD_D_STICK		= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE,
		PAD_TRIGGER		= 100,
		PAD_DOWN		= XINPUT_GAMEPAD_DPAD_DOWN,
		PAD_UP			= XINPUT_GAMEPAD_DPAD_UP,
		PAD_RIGHT		= XINPUT_GAMEPAD_DPAD_RIGHT,
		PAD_LEFT		= XINPUT_GAMEPAD_DPAD_LEFT,
	};
public:
	void init();
	bool GetPadState(PAD_STATE p_state);
};
Controll.cpp

コード:

#include <iostream>
#include "Controller.h"
using namespace std;


void Controller::init()
{
	XINPUT_STATE state;
	ZeroMemory( &state, sizeof(XINPUT_STATE) );
}
bool Controller::GetPadState(PAD_STATE p_state)
{
	XINPUT_STATE state;
	ZeroMemory( &state, sizeof(XINPUT_STATE) );
	DWORD dwResult;
	DWORD user;
	user = 0;
	dwResult = XInputGetState(user,&state);
	if(dwResult == ERROR_SUCCESS)
	{
		// ボタン
		if(state.Gamepad.wButtons & p_state){return true;}
		// スティック
		//---- 左
		if( state.Gamepad.sThumbLX > p_state ) {return true;}
		if( state.Gamepad.sThumbLX < p_state ) {return true;}
		if( state.Gamepad.sThumbLY > p_state ) {return true;}
		if( state.Gamepad.sThumbLY < p_state ) {return true;}
		//---- 右
		if( state.Gamepad.sThumbRX > p_state ) {return true;}
		if( state.Gamepad.sThumbRX < p_state ) {return true;}
		if( state.Gamepad.sThumbRY > p_state ) {return true;}
		if( state.Gamepad.sThumbRY < p_state ) {return true;}
		// トリガー
		if( state.Gamepad.bRightTrigger > p_state) {return true;}
		if( state.Gamepad.bLeftTrigger > p_state) {return true;}
	}
	
	return false;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#25

投稿記事 by softya(ソフト屋) » 12年前

これ、ちゃんと動きますか?
問題があるとしか思えません。

【補足】
enumは範囲のある値と比較をするための物ではありません。
ちゃんと、範囲指定の値とビット処理の値の定義や処理は分けて下さい。
以下のものが動いていたとしてもトリッキーな組み方でバグを内包します。

コード:

        if( state.Gamepad.sThumbLX > p_state ) {return true;}
        if( state.Gamepad.sThumbLX < p_state ) {return true;}
        if( state.Gamepad.sThumbLY > p_state ) {return true;}
        if( state.Gamepad.sThumbLY < p_state ) {return true;}
        //---- 右
        if( state.Gamepad.sThumbRX > p_state ) {return true;}
        if( state.Gamepad.sThumbRX < p_state ) {return true;}
        if( state.Gamepad.sThumbRY > p_state ) {return true;}
        if( state.Gamepad.sThumbRY < p_state ) {return true;}
        // トリガー
        if( state.Gamepad.bRightTrigger > p_state) {return true;}
        if( state.Gamepad.bLeftTrigger > p_state) {return true;}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#26

投稿記事 by EKISUKE » 12年前

http://www.codeproject.com/Articles/269 ... ith-XInput

このサイトを見ながら一応できたのですが、これでいいんでしょうか?
Controller.h

コード:

#pragma once
#pragma comment(lib,"XInput.lib")
#include <windows.h>
#include <Xinput.h>
class Controller
{
public:
	int _controllerNum;
public:
	Controller(int playerNum);
	XINPUT_STATE GetState();
};
Controller.cpp

コード:

#include "Controller.h"



Controller::Controller(int playerNum)
{
	_controllerNum = playerNum -1;
}

// XInputの情報を取得
XINPUT_STATE Controller::GetState()
{
	XINPUT_STATE state;
	ZeroMemory( &state, sizeof(XINPUT_STATE) );

	XInputGetState(_controllerNum, &state);

	return state;
}
main.cpp

コード:

#include "Controller.h"
#include <iostream>
using namespace std;
Controller* control;

int main()
{
	
	control = new Controller(1);
	while(true)
	{	
		if(control->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A){
			cout<<"Aボタンがおされました"<<endl;
		}

		if(GetKeyState(VK_ESCAPE) & 0x80 )
		{
			break;
		}
	}
	return 0;
}
理解はできているつもりですが、ほとんど丸写しみたいな状態なので、力がついてるのか心配なのと、これで問題無いのか教えて欲しいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#27

投稿記事 by softya(ソフト屋) » 12年前

うーん。サンプルに頼りすぎです。
自分の設計コンセプト、クラスを使う意図を考えるべきですね。
あと元のサンプルが非常に良くないです。XINPUT_STATEを公開したらクラスでカプセル化している意味がほとんどありません。

>力がついてるのか
それが重要なら自分でクラスのインターフェイスを設計すべきですね。
まず、使う側でどの様に使ったら良いかを考えてからクラスを作るようにしましょう。

たとえば、
control->GetState().Gamepad.wButtons & XINPUT_GAMEPAD_A
よりは前の
control->GetPadState(PAD_A)
の方が分かりやすいですよね? ここは良かったですよ。
悪かったのはデジタル入力とアナログ入力を同時に扱おうとして、ちゃんと扱えてなかったことです。

なので、まずイメージとしてmain側を書いてみたらどうでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#28

投稿記事 by EKISUKE » 12年前

main側にどう書くのかわからなかったので、すごい物量作戦になってしまったのですが、以下の通りになりました。まだまとめれそうな気がしますが・・・
以下長くなります。

Controll.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_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,	//	右トリガー
        PAD_UP,		//	十字キーの上
		PAD_DOWN,	//	十字キーの下
		PAD_LEFT,	//	十字キーの左
        PAD_RIGHT,	//	十字キーの右
    };

	enum STATE_TYPE{
		STATE_BUTTON,
		STATE_TRIGGER,
		STATE_LEFT_U_STICK,
		STATE_LEFT_D_STICK,
		STATE_LEFT_L_STICK,
		STATE_LEFT_R_STICK,
		STATE_RIGHT_U_STICK,
		STATE_RIGHT_D_STICK,
		STATE_RIGHT_L_STICK,
		STATE_RIGHT_R_STICK,
	};
public:
    Controller(int playerNum);
    bool GetPadState(PAD_STATE p_state);
private :
	int _controllerNum;
};
Control.cpp

コード:

#include "Controller.h"

Controller::Controller(int playerNum)
{
	_controllerNum = playerNum -1;
}

bool Controller::GetPadState(PAD_STATE p_state)
{
	STATE_TYPE type;		//	タイプ用
	XINPUT_GAMEPAD	pad;	//	比較用
	ZeroMemory( &pad,sizeof(XINPUT_GAMEPAD));	// 初期化
	switch(p_state){
	//---- ボタン
	case PAD_A:	//	Aボタン
		pad.wButtons = XINPUT_GAMEPAD_A;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_B:	//	Bボタン
		pad.wButtons = XINPUT_GAMEPAD_B;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_X:	//	Xボタン
		pad.wButtons = XINPUT_GAMEPAD_X;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_Y:	//	Yボタン
		pad.wButtons = XINPUT_GAMEPAD_Y;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_L_SHOULDER: //	LB
		pad.wButtons = XINPUT_GAMEPAD_LEFT_SHOULDER;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_R_SHOULDER: //	RB
		pad.wButtons = XINPUT_GAMEPAD_RIGHT_SHOULDER;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_BACK:	//	Back
		pad.wButtons = XINPUT_GAMEPAD_BACK;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_START:	//	Start
		pad.wButtons = XINPUT_GAMEPAD_START;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_UP:	//	十字キーの上
		pad.wButtons = XINPUT_GAMEPAD_DPAD_UP;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_DOWN:	//	十字キーの下
		pad.wButtons = XINPUT_GAMEPAD_DPAD_DOWN;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_LEFT:	//	十字キーの左
		pad.wButtons = XINPUT_GAMEPAD_DPAD_LEFT;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_RIGHT:	//	十字キーの右
		pad.wButtons = XINPUT_GAMEPAD_DPAD_RIGHT;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_LEFT_THUMB:	//	左スティック
		pad.wButtons = XINPUT_GAMEPAD_LEFT_THUMB;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
	case PAD_RIGHT_THUMB:	//	右スティック
		pad.wButtons = XINPUT_GAMEPAD_RIGHT_THUMB;
		type = STATE_BUTTON;	// タイプをボタンに
		break;
		
	case PAD_L_TRIGGER:	//	左トリガー
		pad.bLeftTrigger = 100;
		type = STATE_TRIGGER;
		break;
	case PAD_R_TRIGGER:	//	右トリガー
		pad.bRightTrigger = 100;
		type = STATE_TRIGGER;
		break;

	//---- スティック
	case PAD_LEFT_U_STICK:	//	左スティックの上
		 type = STATE_LEFT_U_STICK;
		 pad.sThumbLY = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 pad.sThumbLX = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 break;
	case PAD_LEFT_R_STICK:	//	左スティックの右
		 type = STATE_LEFT_R_STICK;
		 pad.sThumbLY = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 pad.sThumbLX = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 break;
	case PAD_LEFT_D_STICK:	//	左スティックの下
		 type = STATE_LEFT_D_STICK;
		 pad.sThumbLY = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 pad.sThumbLX = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 break;
	case PAD_LEFT_L_STICK:	//	左スティックの左
		 type = STATE_LEFT_L_STICK;
		 pad.sThumbLY = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 pad.sThumbLX = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
		 break;
		
		break;

	case PAD_RIGHT_U_STICK:	//	右スティックの上
		 type = STATE_RIGHT_U_STICK;
		 pad.sThumbRY = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 pad.sThumbRX = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 break;
	case PAD_RIGHT_R_STICK:	//	右スティックの右
		 type = STATE_RIGHT_U_STICK;
		 pad.sThumbRY = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 pad.sThumbRX = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 break;
	case PAD_RIGHT_D_STICK:	//	右スティックの下
		 type = STATE_RIGHT_U_STICK;
		 pad.sThumbRY = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 pad.sThumbRX = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 break;
	case PAD_RIGHT_L_STICK:	//	右スティックの左
		 type = STATE_RIGHT_U_STICK;
		 pad.sThumbRY = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 pad.sThumbRX = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
		 break;
	}

	XINPUT_STATE state;	// コントローラ情報取得用
    ZeroMemory( &state, sizeof(XINPUT_STATE) );	// 初期化
    DWORD dwResult;	// 関数結果判定用
	// 情報取得
    dwResult = XInputGetState(_controllerNum,&state);
    if(dwResult == ERROR_SUCCESS){
		switch(type){
		case STATE_BUTTON:
			if(state.Gamepad.wButtons & pad.wButtons){return true;}
			break;
		case STATE_TRIGGER:
			if(state.Gamepad.bLeftTrigger & pad.bLeftTrigger){return true;}
			if(state.Gamepad.bRightTrigger & pad.bRightTrigger){return true;}
			break;
		case STATE_LEFT_U_STICK:
			if(state.Gamepad.sThumbLY >  pad.sThumbLY ){return true;}
			break;
		case STATE_LEFT_D_STICK:
			if(state.Gamepad.sThumbLY < -pad.sThumbLY ){return true;}
			break;
		case STATE_LEFT_R_STICK:
			if(state.Gamepad.sThumbLX >  pad.sThumbLX ){return true;}
		case STATE_LEFT_L_STICK:
			if(state.Gamepad.sThumbLX < -pad.sThumbLX ){return true;}
			break;
		case STATE_RIGHT_U_STICK:
			if(state.Gamepad.sThumbRY >  pad.sThumbRY ){return true;}
			break;
		case STATE_RIGHT_D_STICK:
			if(state.Gamepad.sThumbRY < -pad.sThumbRY ){return true;}
			break;
		case STATE_RIGHT_R_STICK:
			if(state.Gamepad.sThumbRX >  pad.sThumbRX ){return true;}
			break;
		case STATE_RIGHT_L_STICK:
			if(state.Gamepad.sThumbRX < -pad.sThumbRX ){return true;}
			break;
		}
	}
	return false;
}
main.cpp

コード:

#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))
		{cout<<"左スティックの下"<<endl;}
		if(control->GetPadState(control->PAD_LEFT_L_STICK))
		{cout<<"左スティックの左"<<endl;}
		if(control->GetPadState(control->PAD_L_TRIGGER))
		{cout<<"左トリガー"<<endl;}
		if(control->GetPadState(control->PAD_BACK))
		{cout<<"Back"<<endl;}

		if(GetKeyState(VK_ESCAPE) & 0x80 )
		{
			break;
		}
	}
	return 0;
}
すごく物量作戦になって、コード量も多く見づらいので、どうやってもっとすっきりさせるか考え中です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#29

投稿記事 by softya(ソフト屋) » 12年前

メイン側でパッドをどう使うかが先ですよ。
ところでアナログ値は使わないんですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#30

投稿記事 by EKISUKE » 12年前

実はいまパッドをゲームにいきなり導入するのは、自分が混乱するかと思い、とりあえず、押されたキーがcoutで表示されるプログラムを作ろうと思っています。
それをメイン側から書くということはこういうことでしょうか?今は左スティックの状態の表示だけを書いています。

main.cpp

コード:

#include "Controller.h"
#include <iostream>
using namespace std;
Controller* control;

int main()
{
	
	control = new Controller(1);
	while(true)
	{	
		if(GetPadState(PAD_LEFT_D_STICK))
		{cout<<"左スティックの下が押されました。"<<endl;}
		if(GetPadState(PAD_LEFT_U_STICK))
		{cout<<"左スティックの上が押されました。"<<endl;}
		if(GetPadState(PAD_LEFT_L_STICK))
		{cout<<"左スティックの左が押されました。"<<endl;}
		if(GetPadState(PAD_LEFT_R_STICK))
		{cout<<"左スティックの右が押されました。"<<endl;}
		if(GetKeyState(VK_ESCAPE) & 0x80 )
		{
			break;
		}
	}
	return 0;
}
それと、アナログ値というのは
pad.bLeftTrigger = 100;
ということではないのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#31

投稿記事 by softya(ソフト屋) » 12年前

Xbox360コントローラならアナログ値をとれるのは、LRトリガーと2つのアナログスティックが取得出来ます。
LRトリガーは0 ~ 255、アナログスティックは -32768 ~ 32767の範囲の値です。
Windows用のゲームパッドでもアナログ値はありますよ。

今のプログラムは、強引にデジタル入力だけとして扱おうとしています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#32

投稿記事 by EKISUKE » 12年前

アナログとデジタルを分けるというイメージでやってみましたが、もう少し簡単にわけれそうですね・・・考え中です。

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;
};
Controller.cpp

コード:

#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;
}
main.cpp

コード:

#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;
}
Controller側のソースは短くなったのですが、逆に呼び出しの引数が2つになり、メイン側の呼び出しの楽差がなくなってしまっているので、
どうやって引数を一つで、まとめれるかを考え中です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#33

投稿記事 by softya(ソフト屋) » 12年前

(1)アナログ入力をデジタルのように使いたいのなら使うときに引数でアナログを意識するもは面倒なだけです。
(2)アナログ入力はアナログで使いたいのならアナログ値を返さないとダメです。
つまり、(1)でも(2)でも無くどっちつかずだと思います。
ちなみに、(2)を共通のメンバ関数で実現するには無理があるので止めて下さい。

クラス側の都合が使うときに意識されると言うことは、クラスが抽象化の役割を果たしていないことになります。
XInputをわざわざクラスで包み隠しているのですから、XInputをそのまま使ったほうが分かりやすいというような事態は避けなければ行けません。
何のためのクラスなのかをよく考えてみて下さい。

※ だからと言ってクラスの1メンバ関数のコードが長くなるのは避けてくださいね。privateなメンバ関数も使い関数分割をしましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#34

投稿記事 by ISLe » 12年前

Xbox360のコントローラーに対応したプログラムでPS3のコントローラーを使いたいとき、PS3のコントローラーでXbox360のコントローラーを操作して、その入力を受け取るようにしたらプログラムを変更しなくて済みます。

Aボタンしか必要のないゲームでは、Aボタンしかないコントローラーを前提に作ればプログラムがシンプルになります。
実際に押されたのが何のボタンでも(あるいはボタンでなくても)、プログラムからはAボタンが押されたように見えれば良いわけです。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#35

投稿記事 by EKISUKE » 12年前

GetPadStateのなかを関数で分け、アナログとデジタルをそれぞれ関数を持つようにしてみました。

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);
};
Controller.cpp

コード:

#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: ジョイパッドの入力状態を取得するプログラム

#36

投稿記事 by softya(ソフト屋) » 12年前

質問には作るクラスの用途が書いていないので確認したいんです。
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(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#37

投稿記事 by EKISUKE » 12年前

softya(ソフト屋) さんが書きました:質問には作るクラスの用途が書いていないので確認したいんです。
3DのFPSなどを作るならアナログ入力は必須で2Dでもシューティングやアクションで照準用として使っているゲームなんかもありますよね。
それこそ、どうコントローラのクラスをmainなど呼び出し側から使うのかって事です。
今の時点で使わないし汎用的に後でも使えるようなクラスを目指さないなら必要無いわけです。
このプログラムを何に使うかと言いますと、学校の制作展に使います。
最近企画変更があり、コントローラーを使うということは決まっているのですが、
操作方法も詳しく決まっていないので、サンプルプログラムでも組んでみようと思って質問させていただいました。
今後コントローラーを使うゲームを作るとき、このソースコードを持っていくだけで出来ればいいと思っていますが、
他にも今取り組んでいる制作展で、やることはあるはずなので、そちらを優先しようと思っています。
なので、今回はアナログ値を返すプログラムはやめておきます。また、必要になった時に悩んだり、質問させていただくかと思います。
softya(ソフト屋) さんが書きました:(1)に隠蔽できたいと思いますよ。
それとパッドの有無を調べるメソッドも必要だと思いますが如何でしょう?
(2)にする場合どういうふうになったのでしょうか?教えていただければ幸いです。
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);
};
Controller.cpp

コード:

#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;
	}
}
main.cpp

コード:

#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: ジョイパッドの入力状態を取得するプログラム

#38

投稿記事 by softya(ソフト屋) » 12年前

EKISUKE さんが書きました:(2)にする場合どういうふうになったのでしょうか?教えていただければ幸いです。
それがアナログ値を返すって事です。まぁメソッドを増やすことになるでしょう。
どう返すかは工夫の余地あるところですね。 → つまり使い方を想定してインターフェイス設計しないといけません。
EKISUKE さんが書きました:まだプログラムとして、なにか指摘ありましたら、お願いします。
To_XInput()とCheckMode()は配列を使うと短く出来るかもと言っておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#39

投稿記事 by EKISUKE » 12年前

返信遅くなりました。

今回はコントローラーの入力もとれ、どこに持って行ってもすぐにコントローラーが使えるようなソースファイルが作れました。
なので、解決とさせて頂きます。
コードの長さを短縮させる方法は今やっている他のことが落ち着いてから、考えてみます。
回答ありがとうございました。

EKISUKE
記事: 108
登録日時: 13年前

Re: ジョイパッドの入力状態を取得するプログラム

#40

投稿記事 by EKISUKE » 12年前

お久しぶりです。
すこしコントローラーの長かった部分を短縮してみました。
配列でのやり方が思い浮かばなかったので、違ったやり方ですが、これでできました。

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.cpp

コード:

//--------------------------------------------------------------
//!	コンストラクタ
//--------------------------------------------------------------
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のボタンが10進数で10と11以外の時は16進数の0x001の左シフトでいけるようなのでそうしました。
そのため自前の列挙体もXInputと同じ並びにしました。

アナログかデジタルかは元の列挙体の並びをアナログとデジタルで分けているので、
デジタルの最後の列挙体の番号より大きければアナログ、そうでなければデジタルという分け方にしてみました。

すこしやり方が汚いと思うので、教えてほしいことがあります。

1 以前おっしゃっていた配列でのやり方というのはどのようなやり方なのでしょうか?
2 このやり方はプログラムとして悪いやり方ですか?

この2点を教えてください。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ジョイパッドの入力状態を取得するプログラム

#41

投稿記事 by softya(ソフト屋) » 12年前

前よりスッキリしたと思います。
これ以上は無理して縮める必要はないんじゃないでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る