トップページ > 記事閲覧
ゲームパッドについて
名前:だみあん 日時: 2014/02/08 01:29

ゲームパッドについて、いくつかの要望と提案、ならびにバグ報告させて戴きます。 環境はWinXP sp3 vc++2010 DXライブラリver3.11e を使用しています。 まずバグ報告です。 ジョイパッドのデバイス登録名と製品登録名を取得するGetJoypadName関数で 関数の返値からは取得に成功しているようなのですが デバイス登録名と製品登録名どちらも空白が返ってきます。 DXライブラリのソースコードを拝見したところ、 該当部分をみるにどうも文字コード周りでバグがあるようにおもえたので 試しに文字セットをマルチバイトにしてみたところ、正常に文字列が取得出来ました。 どうやら文字セットをUnicodeにした場合では文字コード変換に失敗して? デバイス登録名と製品登録名が空白で返ってくるようです。 DXライブラリのログに記載される 接続中のパッド情報のところも同じ症状です。 なのでGetJoypadName関数の使い方が間違っているということではなさそうです。 残念ながらゲームパッドは一つしか持っていないので 他のデバイスだとどうなるのかという比較は出来ないのですが、 デバイス名に問題がある文字列が含まれているかも知れないので マルチバイト版で取得出来ているデバイス名を記載しておきます。 以下DXライブラリのログより抜粋 ジョイパッドの初期化... 347: 入力装置を見つけました 348: デバイスの登録名:ELECOM JC-PS101U series 349: デバイスの製品登録名:ELECOM JC-PS101U series つぎに要望なのですが 接続されたジョイパッドにたいして、そのパッドがXInputなのかどうかを返す関数を追加して欲しいです。 POVスイッチや右スティック周りの処理を XInputと非XInputで処理を分けるのに利用する為です。 掲示板ログ:Xbox360用コントローラーの動作について ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=3100 を参考にして現状ではとりあえず本来の用途ではない int GetJoypadXInputState( int InputType, XINPUT_STATE *XInputState ) ; を一度実行してみて、-1が返ってきたらXInputではない。 というような方法で対応しておりますが。 つぎに提案なのですが DXライブラリのソースコードを拝見するに XInput利用時にはXInputの状態を従来のDirectInput(GetJoypadInputStateで取得出来るかたち)に 置き換える処理がされていますが、現在の状況的には逆の方が良いのではないでしょうか。 XInputのほうはゲームパッドに特化した仕組みなのですし。 そもそもDirectInputのパッド関係はPOVのような フライトシミュレーター用の名残が残っているような古い規格ですし。 XInputの生情報をベースとした ボタン16個(十字キー、スタート、セレクト、ABXY(プレステでいうところの:●×▲■)、LR各1〜3の計16ボタン) 左右アナログスティック 左右トリガー を標準的な仮想コントローラとして保持するデータ構造を追加。 XInputの情報はほぼそのまま利用できるとして DirectInputのほうの入力を、この仮想コントローラの入力に置き換える方法のが良いように思われます。 その際に povスイッチ使用フラグ。 右スティックにどの軸を使うのか設定する関数。 等で置き換え方法を弄れるようにする必要がありますが。 (その部分はコンフィグ設定で対応) この方法のメリットはXInput、DirectInputどちらの場合にも ゲームプログラム本体から 単一のインターフェースで押下チェックが出来るのと ボタンの割り当てコンフィグも、仮想コントローラに対するキーコンフィグ設定で 済んでしまうと言うところでしょうか。 さらには2Pコントローラなども この仮想コントローラを複数持つだけで簡単に実現できるとおもいます。 DXライブラリでは標準で4つまでパッドの接続を許可している様ですが 仮想コントローラの場合はいくつでも増やせるというメリットもあります (そんないっぱいあっても意味無いでしょうけど) さらに提案なのですが 現行のint GetJoypadInputState( int InputType )の返値から ビット演算で単に該当ボタンが押下されているかだけをチェックする形式に対して ボタン毎にint型などで情報を持つカウンタ方式を採用して戴けたらなとおもいます。 具体的には、 押された瞬間に1、押され続けるとカウンタがインクリメントしていくようなタイプです。 (押してないときはをカウンタリセット) int GetJoypadInputState( int InputType, int ButtonID ); のようなかんじで返値にボタンの状態(カウンタの値) つまりは、標準で「押した瞬間」「押しっぱなし」「一定時間押された場合」 などのチェックが出来る形に対応して戴ければなとおもいます。 現状ではその部分は自前で組んでいますが、おそらく方法は違えど みなさんも標準的に同じような「押した瞬間」or「押しっぱなし」チェック付きの 押下チェック機構は作られていることとは思います。 DXライブラリ上の統一インターフェースとして 上記の仮想コントローラのような物が採用されるのであれば あわよくばそのような押下チェックも付いててくれないかなとおもいまして。 さらに図々しくの提案なのですが 現在では、パッド識別子 DX_INPUT_KEY_PAD1 において パッドのボタンに対してキーボードのキーを一つ割り当てることで パッドとキーボードの両方同時チェックを実現していますが、 これも逆にされてはどうでしょうか。 キーボードのボタンに対して、上記の仮想コントローラのボタンを割り当てるという感じの方法です。 たとえばEnterキーが押されていたら、 仮想コントローラのAボタンが押されたことにする。 と言う形です。 とはいえ、この部分をライブラリで実装して欲しいというわけではなく (この部分はキーコンフィグで対応する部分ですし) 現状、パッド情報は取得関数のみなのですけども それが仮想コントローラだとすると話は別です。 状態取得関数だけでなく Enterキーが押されていたら、 仮想コントローラのAボタンの状態を 「押されている」状態に変更するというような機能があると キーボード(だけでなくマウスの4ボタン以降などにもつかえる)と両対応が容易になると思います。 さらには たとえは仮想コントローラのAボタンをプログラム上「決定ボタン」と規定したという前提で キーコンフィグ設定により Enterキー、Spaceキー、zキーがおされたら仮想コントローラのAボタンをONにする というような、複数のキーボタンとパッド情報とのリンクも簡単に実現できるかと。 パッドの十字キーについても キーボードの矢印キーにWASDキー、テンキーの8426を十字キー等にいずれでも対応 というようなものまで楽に設定出来たりします。 この機能があれば ゲームパッドを使用せず、キーボードのみ使用の場合でも ゲームプログラム本体から単一のインターフェースで 押下状態のチェックが出来る用になるという メリットがあります。 長々と色々書いてしまいましたが 現行では要望の部分はXInput周りを除いて自前ですでに実装しているのですが (XInputに対応してみようとこの辺りを組み直し始めたのが契機だったりします) DXライブラリのソースコードを拝見するに DirectInputとXInputの生情報を共通のインターフェースに落とし込む部分のソースが ライブラリ内部にあるコードとほとんど同一の処理を車輪の再発明的に 自前のプログラム内でも記述しているところに、 なんだか無駄な労力つかっているなという気になったりもしまして(汗 現状ではDirectInputではPOVスイッチと右スティック XInputでは左右トリガーへの対応の為だけに 生情報を直接弄るハメになっているので。 そこでいっそのこと、新しい規格であるXInputを基準とした 新しいパッド周りのインターフェースを ライブラリ側で用意して戴けないかなと思い、今回の提案をするに至たりました。 入力機器関連という基本的な部分だけに 古いソースとの互換性問題などで難しいのかもしれませんが 今回の提案についてご一考いただけると幸いです。
メンテ

Page: 1 |

Re: ゲームパッドについて ( No.1 )
名前:管理人 日時:2014/02/08 16:07

ご報告ありがとうございます Unicode版では Unicode用の DirectInput を使用しているのにデバイス情報を受け取る API にマルチバイト用の構造体を渡していたのが原因でした 修正版をアップしましたので、よろしければお使いください m(_ _;m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) 接続されているパッドが XInput に対応しているかどうかを取得するための関数も 追加しましたので、よろしければお使いください // 指定の入力デバイスが XInput に対応しているかどうかを取得する // 戻り値 TRUE:XInput対応の入力デバイス FALSE:XInput非対応の入力デバイス -1:エラー // 接続されていないパッドの番号が指定された場合や、DX_INPUT_KEY や DX_INPUT_KEY_PAD1 など // キーボードが絡むタイプを InputType に渡すとエラーとなり -1 を返します int CheckJoypadXInput( int InputType ) ; > DXライブラリのソースコードを拝見するに > XInput利用時にはXInputの状態を従来のDirectInput(GetJoypadInputStateで取得出来るかたち)に > 置き換える処理がされていますが、現在の状況的には逆の方が良いのではないでしょうか。 Xbox360 Controller 以外のコントローラーはアナログスティックの無いもの、 あってもアナログ、デジタルで切り替えられるもの、L2, R2 がアナログになっているもの、 デジタルになっているもの、Xbox360 Controller での A,B,X,Y に当たるボタンがあるもの、ないもの、 あっても順番がコントローラー毎に違ったり、そもそもPS1から始まる ABXY(×○□△)ボタン+L1R1L2R2+2スティックの形態ではないファミコン型コントローラなど、様々です なので、Xbox360 Controller の形態を仮想的なコントローラーの形態にしても、 Xbox360 Controller 以外は Xbox360 Controller とは殆どの場合ボタン配置が異なるので 結局 GetJoypadDirectInputState を使用して入力をチェックする必要が発生します また、ライブラリ利用者の方がすべからく Xbox360 Controller を想定して ゲームを作成していればDXライブラリ側が用意する仮想 Xbox360 Controller 型コントローラの ボタン設定に割り当てる関数を使用して便利に使うことができますが、 そうではない場合は現状と同じく自前で仮想コントローラ構造体を用意することになります 現時点で GetJoypadInputState で若干仮想コントローラ的なことをしているので、 その仕様を変更する、若しくは関数を無くすと GetJoypadInputState を使用している 既存のプログラムが動作しなくなる為 Xbox360 Controller 型の仮想コントローラ機能を 追加する場合は新たに別の関数を追加することになりますが、前述の理由で 使用する方がどのくらい居るか分からない状態では無駄に関数が増えるだけになる 可能性があり、躊躇するところです > 現行のint GetJoypadInputState( int InputType )の返値から > ビット演算で単に該当ボタンが押下されているかだけをチェックする形式に対して >  > ボタン毎にint型などで情報を持つカウンタ方式を採用して戴けたらなとおもいます。 押され続けた場合にカウンタがインクリメントされるとのことですが、 インクリメントされるタイミングは何時でしょうか? DXライブラリ自身は『ゲームの処理が1フレーム経過した』かどうかを検出する ことができないので、『前のフレームでボタンが押されていたが、今回のフレームでは ボタンが押されていない』などの処理を行うことができないんです > さらに図々しくの提案なのですが > 現在では、パッド識別子 DX_INPUT_KEY_PAD1 において > パッドのボタンに対してキーボードのキーを一つ割り当てることで > パッドとキーボードの両方同時チェックを実現していますが、 > これも逆にされてはどうでしょうか。 仰る通り上下左右の入力にテンキーの8246や方向キー、WSADキーなど複数対応できるのは良さそうです ただ、現状では前述の通りの状況なので、仮想系の機能は抜本的な変更をしない限りは 今の仮想系の機能に追加しても意味があまりないかなと思っています まだ電器店には Xbox360 Controller 以外のコントローラーも売っていますし、 XboxOne も発売されれば Xbox360 Controller にあった STARTボタンと BACKボタンは 使えなくなるなど、Xbox360 Controller 自体も古いものになっていきます というか、個人的には XInput が、色々なコントローラーを想定している DirectInput の進化版のような仕様だったら DirectInput の代わりに XInput を使えたのに・・・と思っています ( 例えば DirectInput には一つしかない方向入力情報が複数あって、POVや回転軸情報などに 割り当てなくても複数の軸入力に対応できて、且つPOVをPOVとして、回転軸情報を回転軸情報として 使用するデバイスにも対応できるようにPOVや回転情軸報なども残してあるなど ) 現状では XInput でしか取得できない情報や、DirectInput でしか取得できない情報が 混ざっているので、全てのデバイスに対応したい場合に結局どちらも使うしかない状態です・・・ なので、本格的に対応したいと思われた方は恐らくだみあんさんのように XInput と DirectInput の情報をどちらも取得して独自の入力システムを作成すると思いますので、 中途半端な仮想コントローラ機能を追加するのはやめておいたほうが良いかな、と思っています 直ぐには動けないと思いますが、自分の中でもモヤモヤしている入力関係について 考えることができました、ありがとうございます
メンテ
Re: ゲームパッドについて ( No.2 )
名前:だみあん 日時:2014/02/09 14:12

GetJoypadName関数のほう確認しました。 ただ、プログラム内でのGetJoypadName関数による取得では 正常に文字列を取得出来るようになったのですが 345: ジョイパッドの初期化... 356: 入力装置を見つけました 357: デバイスの登録名:E 358: デバイスの製品登録名:E と、DXライブラリのログ出力の方だけ このように先頭の1文字しか表示されない状態になっております。 プログラムの実行には影響の無い部分ではありますが報告まで。 >接続されているパッドが XInput に対応しているかどうかを取得するための関数も >追加しましたので、よろしければお使いください ありがとうございます。 XInput使用の機材を持っておりませんので とりあえずFALSEが返ってくるのだけですが確認しました(^^ >使用する方がどのくらい居るか分からない状態では無駄に関数が増えるだけになる >可能性があり、躊躇するところです GetJoypadInputStateで取れる情報とはべつに似たような情報ももつことになり たしかにいろいろと無駄ですね……。 ライブラリ側で用意するべきモノではないというのが判りました。 今回きっちりとXInputかどうか判定する判別方法も追加されたことですし DirectInput用とXInput用で処理を分ける事にします。 >まだ電器店には Xbox360 Controller 以外のコントローラーも売っていますし、 >XboxOne も発売されれば Xbox360 Controller にあった STARTボタンと BACKボタンは >使えなくなるなど、Xbox360 Controller 自体も古いものになっていきます Xbox360用のも、もう古い……のですか。 おもわず遠い目になってしまいました(ぉ >というか、個人的には XInput が、色々なコントローラーを想定している >DirectInput の進化版のような仕様だったら DirectInput の代わりに >XInput を使えたのに・・・と思っています 完全に上位互換とかだったらよかったのに……て感じですね。 ボタンの入力関係についてですが やはりいろいろと考えた結果 もともと低レベルなAPI関数群といった感じのDXライブラリには 大仰すぎる気がしてきました。 あまりやり方を強制されず、 1から自由に組めるのがDXライブラリの良いところだと思いますし。 ただ、キー入力という基本部分だけに重要な所でありながら ゲームプログラミングはじめたばかりの方とかは キーコンフィグ周りや、押した瞬間のみの取得といったところで 躓く方も多い部分でもあったりします。 なにげにゲームを公開している方(DXライブラリ使用でない場合含む)でも パッドのみ対応だったり コンフィグ対応無しだったりというのが結構多いのも その辺の煩雑さを表しているように思えます。 そんなところでちょっと 思う所があったので書いてみた部分でした。 >押され続けた場合にカウンタがインクリメントされるとのことですが、 >インクリメントされるタイミングは何時でしょうか? >DXライブラリ自身は『ゲームの処理が1フレーム経過した』かどうかを検出する >ことができないので、『前のフレームでボタンが押されていたが、今回のフレームでは >ボタンが押されていない』などの処理を行うことができないんです についてはキーボード入力の例をとると (例なので無駄の多い感じになってます) #define DX_KEY_MAX 256 int keyState[DX_KEY_MAX]; //ぐろーばる //キーボード入力チェック void GetKeyState(){ char key[DX_KEY_MAX]; GetHitKeyStateAll( key ); for(int i=0;i<DX_KEY_MAX;++i){ if(key[i]==1){ keyState[i]++; } else { keyState[0]=0; } } } こんなかんじで、GetKeyState()を ゲームループの先頭、フレーム開始時に呼んでいます そのときに押されていたら押され続けているフレーム数を加算するというかんじです。 //押した瞬間 bool On(int ButtonID){ return (keyState[ButtonID] == 1) ? true : false;} //長押し判定有り デフォ=120 60fpsなら約2秒 メニュー選択などで使う bool KeepOn(int KeyID, int frame=120){return (keyState[ButtonID] == 1 || keyState[ButtonID] > frame) ? true : false;} //押しっぱ bool isOn(int KeyID){ return (keyState[ButtonID] >= 1) ? true : false;} と言うようなキー入力チェックが行えるようになります。 上記の例の int keyState[DX_KEY_MAX]; の部分を各入力デバイス共通の「仮想コントローラ」(正確には仮想入力バッファというべきか)的にあつかえば キーボードやゲームパッドの入力に対して「仮想コントローラ」のどのボタンが押されたかに 対応する部分をキーコンフィグとして設定することで どのデバイスのどのボタンが押されているかを それぞれに問い合わせることなく 単純に仮想入力バッファの値をチェックするという という単一のインターフェースで実現出来るようになります。 が、やはりこの辺りは従来の通り各デバイス毎に > ビット演算で単に該当ボタンが押下されているかだけをチェックする形式 のような低レベルな、ON・OFFだけを取得するだけの機能にとどめておき この仮想入力バッファや そのインターフェース、並びにキーコンフィグ周りのようなものは 自前で好きなように各自で実装するべきかなとか思い直しました。
メンテ
Re: ゲームパッドについて ( No.3 )
名前:管理人 日時:2014/02/11 00:09

> と、DXライブラリのログ出力の方だけ > このように先頭の1文字しか表示されない状態になっております。 ご指摘ありがとうございます 修正したバージョンをアップしましたので、よろしければお使いください m(_ _;m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用 http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用 http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) > ただ、キー入力という基本部分だけに重要な所でありながら > ゲームプログラミングはじめたばかりの方とかは > キーコンフィグ周りや、押した瞬間のみの取得といったところで > 躓く方も多い部分でもあったりします。 仰る通りです 多分、最善の対応は参考になるキーコンフィグのサンプルを作成することなんだと思います ( サンプルでしたらライブラリの機能と違いずっとそのまま残しておかなければ ならないということもありませんし・・・ ) > 上記の例の > int keyState[DX_KEY_MAX]; > の部分を各入力デバイス共通の「仮想コントローラ」(正確には仮想入力バッファというべきか)的にあつかえば > キーボードやゲームパッドの入力に対して「仮想コントローラ」のどのボタンが押されたかに対応する部分を > キーコンフィグとして設定することでどのデバイスのどのボタンが押されているかをそれぞれに問い合わせることなく > 単純に仮想入力バッファの値をチェックするという単一のインターフェースで実現出来るようになります。 なるほど、解説ありがとうございます > が、やはりこの辺りは従来の通り各デバイス毎にビット演算で単に該当ボタンが押下されているかだけを > チェックする形式のような低レベルな、ON・OFFだけを取得するだけの機能にとどめておき > この仮想入力バッファやそのインターフェース、並びにキーコンフィグ周りのようなものは > 自前で好きなように各自で実装するべきかなとか思い直しました。 そうですね、DXライブラリの機能として考えるとちょっと「ユーザーが実装する処理」寄りのような 気がします( まあ、既にDXライブラリにはそういう中途半端な立ち位置の機能がちらほらあって しまっていますが・・・ )
メンテ
Re: ゲームパッドについて ( No.4 )
名前:だみあん(解決) 日時:2014/02/13 05:40

unicode版のジョイパッドのデバイス登録名と製品登録名の件 修正確認しました。 ありがとうございました(ぺこり
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存