トップページ > 記事閲覧
【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加
名前:通りすがりのオールドユーザー 日時: 2021/05/15 00:33

キーを離した状態から押した瞬間、押した状態から離した瞬間、特に押した瞬間だけ反応して欲しいのは結構使うのに、それを検知しようとすると、そこそこ組まないといけないので、それを出来る関数を考えてみましたので、標準の関数に追加提案です。 ついでに、ちょっと扱いにくくなるものの、CheckAllKey() の代用も可。 概要: CheckAllKey() のキー変化も取得する拡張バージョン 第1引数: CheckAllKey() と同じ 第2引数: 前回キー状態を保持しておくための、char PrevKeyStateBuf[256]  この変数は、メインループ前やグローバル等、ループが回っても消えない変数を指定する。  この変数は、ユーザ側では原則操作しないようにする。  (どこか別の所に保持できるなら、引数にしなくていいです。) 説明: 基本は CheckAllKey() に準拠するためDXライブラリのリファレンスを参照。 違いは、押し下げた瞬間1回だけ2になり、離した瞬間だけ3になる。 変化を検出するには、毎フレーム、本関数を呼び出しておく必要がある。 int CheckAllToggleKey(char *KeyStateBuf, char *PrevKeyStateBuf) { const int NUM = 256; int IRet = 0; errno_t ERet = 0; // if ([その他失敗条件]) { // return -1; // } // 全キー状態を取得 char KeyStateBufTmp[NUM]; IRet = GetHitKeyStateAll(KeyStateBufTmp); if (IRet == -1) { return -1; } // 現在状態をコピー ERet = memcpy_s(KeyStateBuf, sizeof(char) * NUM, KeyStateBufTmp, sizeof(char) * NUM); if (ERet != 0) { return -1; } // 変化あったキーだけ上書きする for (int i = 0; i < NUM; i++) { // 前回押されておらず、今回押されている if (PrevKeyStateBuf[i] == 0 && KeyStateBufTmp[i] == 1) { KeyStateBuf[i] = 2; } // 前回押されており、今回離されている else if (PrevKeyStateBuf[i] == 1 && KeyStateBufTmp[i] == 0) { KeyStateBuf[i] = 3; } } // 前回キー保持 ERet = memcpy_s(PrevKeyStateBuf, sizeof(char) * NUM, KeyStateBufTmp, sizeof(char) * NUM); if (ERet != 0) { return -1; } return 0; }
メンテ

Page: 1 | 2 |

Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.10 )
名前:通りすがりのオールドユーザー 日時:2021/05/27 01:37

ちなみに個人的には、以下のひろかずさんの意見に賛成です。 >離した -1 >押していない 0 >押している 1〜(押しているフレーム数) どうせなら、マイナス側も離しているフレーム数入れちゃうとか。
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.11 )
名前:名無三 日時:2021/05/27 06:18

経過フレーム系はオーバーフロー怖くないですかね…その為にわざわざLONGLONG使うのもなんだかだし
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.12 )
名前:なんとなく 日時:2021/05/27 10:26

実際問題として,"ここら辺の入力処理を組むのに苦労するケースが多いのだ",ということならば, それをケアすること自体は良いとは思うけども, その方法としては「ライブラリが提供する関数として追加する」という形でなくとも良いのでは? 例えば, 「実装コード例」みたいなものとして示すような形でも良いのでは? (リファレンスで示す用例を補強するだとか)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.13 )
名前:なんとなく 日時:2021/05/27 11:10

> あいおい?さんと、なんとなくさんのご意見を合体させて、 念のため述べておくけども, 私は,「押している長さが取得できる関数を用意すべき」と主張しているのではないよ. "特定の固定実装をライブラリに追加しても何の助けにもならない例" として「長さ」を挙げただけで. 入力の扱いというのはケースバイケースなので, その中のある1つのケースだけを取り上げてライブラリとしてサポートすることにどれだけの意味があるのか?と. (良い言葉じゃないけども)「個々のわがまま」と称したのはそういう意味.
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.14 )
名前:ひろかず 日時:2021/05/28 22:42

> 通りすがりのオールドユーザーさん 確かにマイナス側もフレーム数を入れた方が良いなと感じました。 > 名無三さん 32bit符号付きだとしても1秒60フレーム換算で、オーバーフローに9942時間かかるので考慮する必要は無いかと思います。 > なんとなくさん その点については理解しております。 現状、私が作成しているゲームのキー入力処理が、押している長さが取得出来るようにラッピングしているので一意見として申し上げただけです。 キー入力に関しては確かにゲームのジャンルによって必要な情報が変わってくるので、新たに関数を設けるのではなく、 なんとなくさんがご提案されたように、「実装コード例」をリファレンスで提示した方が、応用が利いて良いのかもしれません。
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.15 )
名前:名無三 日時:2021/05/28 22:54

まあ高精度タイマーが30日しかもたないですし問題ないですわね(もやもやしますが)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.16 )
名前:なんとなく 日時:2021/05/31 13:51

オーバーフローが心配ならば,フローさせない,という方針もありますね. if( C < 0xFF )++C; //カウントは最大値で止めるよ 用途的には, if( C >= ある程度の長さに相当する値 ){ /* なんか処理する */ } みたいな形の書き方をするんでしょうし.
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.17 )
名前:管理人 日時:2021/06/10 00:09

ご返信が大変遅くなり申し訳ありません 皆様のご意見を集約して以下のような関数を追加しました // すべてのキーの押下状態を取得する // ( KeyStateArray:int型256個分の配列の先頭アドレス // 初回は配列の全要素に 0 が代入されている必要があります // 配列の各要素の状態 // // 0:押されていない // // 1 :押された1回め // 2以上:押され続けている回数 // // -1 :押されて離された1回め // -2以下:押されて離されてからの回数 ) int GetHitKeyStateAllEx( int *KeyStateArray ) ; 機能的に Toggle感が薄れたので安直に末尾に Ex を付けた関数名にしました また、どんなに押し続けていたり離しっぱなしにしてもオーバーフローしないように 2147483647 や -2147483647 で値がストップするようになっています ( 1フレーム1回呼び出しで144fpsでも172日間計測できます ) 上記の関数を追加した暫定最新版はこちらにアップしました https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい) あとこちらは全てのキーの状態を表示するサンプルです ( 一度でも押されたキーは二度と 0 にはならないのが少し引っ掛かりますが使用上の問題は無いと思います ) #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int i, j ; int KeyState[ 256 ] = { 0 } ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // 描画先を裏画面にする SetDrawScreen( DX_SCREEN_BACK ) ; // メインループ(何かキーが押されたらループを抜ける) while( ProcessMessage() == 0 ) { // 画面のクリア ClearDrawScreen() ; // GetHitKeyStateAllEx の結果を描画 GetHitKeyStateAllEx( KeyState ) ; for( i = 0; i < 16; i ++ ) { for( j = 0 ; j < 16 ; j ++ ) { DrawFormatString( j * 30, i * 20 + 32, GetColor( 255,255,255 ), "%3d", KeyState[ j + i * 16 ] ) ; } } // 裏画面の内容を表画面に反映 ScreenFlip() ; } // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; } # < 他スレッドの方へ > # 現在作業時間が非常に少なくなっています # 投稿の順番でご返信しますので今暫くお待ち下さい m(_ _)m
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.18 )
名前:なんとなく 日時:2021/06/14 10:43

今さらですが, > すべてのキーの押下状態を取得 したい場面は極めて稀で,ほとんどの場合はたかだか数個(?)のキーのみを用いるでしょうから, 例えば, //KeyCodes : 調べたいキーコード群 //KeyStateBuffer : 更新されるバッファ //n : KeyCodes と KeyStateBuffer のサイズ void XXX( const int *KeyCodes, int *KeyStateBuffer, size_t n ); みたいな形とかもあり得たかもしれませんね. (内側で処理する個数が減るのでやや軽くなるかな? 些細すぎる?)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.19 )
名前:通りすがりのオールドユーザー 日時:2021/06/20 17:47

管理人さま 色々な意見があり難しいですね。 それを受け入れてくださる管理人様に心服いたします。 ありがとうございました。 > なんとなくさん メインループの最初で本関数使えば、以下の方に最初にまとめて状態取ってから、色々使い分けできるので、個人的にはこれで良いかなと思います。 個別にやる手もありますが、保持変数も個別に用意する必要があるので、そこまでなると関数として用意されるメリットが薄くなるかなと・・・。 // 初期化 int KeyState[256] = {0}; while(1) { // 操作判定 GetHitKeyStateAllEx(KeyState); if (KeyState[KEY_INPUT_SPACE] == 1 || KeyState[KEY_INPUT_Z] == 1) { // ショット撃つ処理 } if (KeyState[KEY_INPUT_R] == 1) { // リロード処理 } // 以下、内部計算や描画処理など }
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.20 )
名前:たろう 日時:2021/06/20 22:19

通りすがりのオールドユーザーさん、 これだとキーコンフィグとか、後々大変じゃないでしょうか? パッドやマウスでの操作もできなくなりますし
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.21 )
名前:なんとなく 日時:2021/06/21 15:53

例えば使うキーが10個ならば GetHitKeyStateAllEx() 関数にはその10個のキーに関する処理だけをやってもらえば 常に256個分の処理をする実装と比較して微妙に軽くなるかも? (関数を使う側が用意せねばならないintな配列のサイズも10個に減るから,そこもちょっとだけ省メモリになるかな) …というだけの,単なる事後雑談(?)です. (作られた物の仕様に対して何かを主張しているわけではないです)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.22 )
名前:通りすがりのオールドユーザー 日時:2021/06/25 12:23

> たろうさん > これだとキーコンフィグとか、後々大変じゃないでしょうか? パッドやマウスでの操作もできなくなりますし 個別キー判定の方が、キーコンフィグしやすいという事でしょうか? キーコンフィグは、かなり色々なやり方あると思います。 例えば、割り当てたキーがONした瞬間やパッドやマウスクリックした瞬間に 1になる変数を用意しておいて、それが1ならショットを撃つとかでしょうか。 例: int Shot = 0; int Reload = 0; if ([割り当てたキーが押された瞬間だけtrueになる条件式]) || [割り当てたパッドが押された瞬間だけtrueになる条件式] || [割り当てたマウスキーが押された瞬間だけtrueになる条件式]) { Shot = 1; } if ([割り当てたキーが押された瞬間だけtrueになる条件式]) || [割り当てたパッドが押された瞬間だけtrueになる条件式] || [割り当てたマウスキーが押された瞬間だけtrueになる条件式]) { Reload = 1; } if (Shot == 1) { // ショット撃つ処理 } if (Reload == 1) { // リロード処理 } > なんとなくさん おそらく、CheckHitKeyAll()等の実装は、 GetKeyState() を256回呼び出しているのではなく、 GetKeyboardState() を1回呼び出しだと思うので、単純に256倍の負荷ではないと思います。 ( さらにキーボードドライバからどういう読み出しをするのかそこまでは知りませんが、memcpy(&Keyboard, &KeyArray, 256); みたいな処理ではないかと推測。 さらにさらにいうと、GetKeyState() も仮想キーボードから読んでるっぽいので、生のキーボードから何回も読むわけではなさそうなので、個別読み出しも特別重い訳でもなさそう。 検証したことはありませんが・・・。イメージ的には、全読み出しの負荷は、個別の2倍〜10倍くらいではないかと。 ) 感覚的な話になってしまいますが、負荷的に、個別に10回読むのと全キー読むのは、いまどきのPCやスマホなら誤差範囲って感じです。 メモリも、当たり前のように数GB使えるので、4バイト*256=1KB くらい誤差範囲って所ですねぇ・・・。 組み込み系と呼ばれるマイコン等で動く機械とかであれば、気にするところですが、それだとWindowsではないのでそもそもDXライブラリが動きませんw 参考になれば幸いです。
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.23 )
名前:たろう 日時:2021/06/25 13:44

[割り当てたパッドが押された瞬間だけtrueになる条件式]と [割り当てたマウスキーが押された瞬間だけtrueになる条件式] の部分ですが、これはGetHitKeyStateAllEx()を使うのであれば難しいのではないでしょうか? また、キーコンフィグで割り当てキーが変わってしまう事を前提にすると キーの押し離し時間の計測ではなくて、例えば「Shot」のTRUE or FALSEの時間を計測するのがベストな気がします それについてはどうでしょうか?
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.24 )
名前:名無三 日時:2021/06/25 19:36

そこをでstateallで取った配列を使えば済む話では?どう難しいんでしょうか? …と思ったら要は stateallではパッド、マウスの押しっぱなしなどの状態を得ることができないのが難しい と言うことですか?
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.25 )
名前:たろう 日時:2021/06/26 09:26

そうです。パッドやマウス操作などに対応させるために 自作でGetHitKeyStateAllEx()のような関数を作る事になると思うので、 そうすると結局は、キーごとの押し離しの時間を計測するのではなく 割り当てられたボタンが押されているときに、変数shotを1以上&増加の仕組みを作って そのshotが1の時に押した瞬間と判定する方式にするほかないんじゃないかな…という事なんですが あまり自信はないので、ほかに方法があれば知りたい気持ちもあります<(_ _)>
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.26 )
名前:名無三 日時:2021/06/26 10:29

GetHitKeyStateAll等々でマウス、パッドもまとめて取れるなら楽ではあるでしょうけど、難しいんですかね? というかここのレスに殆ど方法が書いてありますね
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.27 )
名前:なんとなく 日時:2021/06/28 13:19

> おそらく、CheckHitKeyAll()等の実装は、 > GetKeyState() を256回呼び出しているのではなく、 > GetKeyboardState() を1回呼び出しだと思うので、単純に256倍の負荷ではないと思います。 あ,私が言ってるのはそこ(キーの状態を取得してくる処理)じゃなくて, その後の処理(個々のキーについてのプラスマイナスがどうのいう結果値を作るところ)の話です. つまり,処理速度的にはもっと些細な差しかないであろう部分です. 富豪的プログラミング(っていうの?)的な価値観の上では,本当にどうでもいい部分. > パッドやマウス 本件は「キー入力のための」関数が作られたのだと思うので,パッドとかマウスとかいうのは考慮されていないでしょう. なので,例えば 「パッドとキーボードのどちらでも同じ操作を可能にしたい」というような話では > 自作でGetHitKeyStateAllEx()のような関数を作る事になる んじゃないでしょうかね. (結局,そういう話だよね,っていう)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.28 )
名前:通りすがりのオールドユーザー 日時:2021/07/06 02:24

> たろうさん パッドとマウスはこういう関数が用意されてないので、 >> 自作でGetHitKeyStateAllEx()のような関数を作る事になる 結局は、これになりますね。 キーボード、マウス、パッド含めたGetHitKeyStateAllEx()のような関数一個にするのか、 それぞれ別々に作って if文で ||(OR条件)で並べるのか、 そこは設計やプログラマー次第と言った所ですね・・・。 少なくともこのスレッドで、数の多いキーボードについては用意されたので、 今後は製作難易度が少し下がるかも、といったところでしょうか。 (これまでも、ライブラリで提供されてる関数で頑張れば作れますが。) > なんとなくさん > その後の処理(個々のキーについてのプラスマイナスがどうのいう結果値を作るところ)の話です. んー、そこはプログラマーの組み方次第じゃないですかね? 色んなキーで色んな事やろうとすると重くなるし、色んなキー使うけど少ない内容しかなければ軽いし。 ちょっとしたユーザーが書く処理よりも、DXライブラリの裏で動いてる処理の方が遙かに重いので、 どこをどう書くとどれくらい重くなるかは、計測してみると良いと思いますよ。 メモリ使用量も、タスクマネージャのプライベートワーキングセットとかコミットサイズにも現れるので。 ・・・という雑談ですね。
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.29 )
名前:通りすがりのオールドユーザー(解決済) 日時:2021/07/06 02:26

あ、すみません、ここの慣習なのですかね? 解決済は名前に記入した方が良さそうなので、追記です。
メンテ

Page: 1 | 2 |

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

   クッキー保存