トップページ > 記事閲覧
【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加
名前:通りすがりのオールドユーザー 日時: 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 |

Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.1 )
名前:管理人 日時:2021/05/15 02:01

新関数のご提案ありがとうございます ただ、ご提案頂いた関数を正しく使用できるのは、押した瞬間、離した瞬間の情報を取得する処理を GetHitKeyStateAll のみで正しく組める方だけかな…と思うので、 『関数は追加するものの、関数リファレンスには載せない』という方向で実装しようかと思います ( DxLib.h をご覧になられるような、ご提案の関数を正しく理解して使えるような 中級者以上の方が見つけて使用されるイメージです ) 関数名なのですが、通りすがりのオールドユーザーさんは CheckAllKey と書かれていますが、 CheckAllKey という名前の関数はありませんので、こちらは GetHitKeyStateAll のことを 指している、という認識で合っていますでしょうか? GetHitKeyStateAll に押し始めの変化、離した時の変化の情報を追加した関数ということで Hit を Toggle に変更して GetToggleKeyStateAll にしようかなと考えています ( ただ、この関数名だと『押しっぱなし』の情報が得られないような印象になってしまうので、 GetHitKeyStateAllEx や GetHitKeyStateAll2 などのベタな関数名にした方が良いかもしれませんが… )
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.2 )
名前:通りすがりのオールドユーザー 日時:2021/05/21 21:52

管理人さま 検討ありがとうございます。 細かいチェック抜けていてすみません、名前とかは一任いたします。 個人的には、変化点を取れるという点で、Toggle という名前が入っていたほうがいいかなと思います。
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.3 )
名前:あいおい? 日時:2021/05/22 16:40

離したを -1、押していないを 0、押したを 1、押し続けているを 2として、処理を組むと『押しっぱなし』の情報のも得られて良いと思います 言語は C# ですが自分はこんな感じで実装しています ttps://github.com/AioiLight/Amaoto/blob/amaoto-refined/Amaoto/Key.cs
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.4 )
名前:なんとなく 日時:2021/05/26 14:55

既に GetHitKeyStateAll なるものが用意されているなら せいぜい void UpdateKeyStateInfo( unsigned char *Buff ) //要素数256の配列を突っ込む { char CurrState[256]; GetHitKeyStateAll( CurrState ); for( int i=0; i<256; ++i ){ Buff[i] = (Buff[i]<<1) | CurrState[i]; } } みたいなのをユーザが自分の用途に従って書くだけで済むような話に見える. > そこそこ組まないといけない と訴えるほどのことでもないのでは?
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.5 )
名前:あいおい? 日時:2021/05/26 15:44

(まあ、自力で書けば済む話ではありますが ゲームエンジン的な側面も持ち合わせているので 入力制御の実装が弱いと言いたくなる気持ちは分かります)
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.6 )
名前:なんとなく 日時:2021/05/26 17:55

例えば,「押しっぱなし」の期間の長さを知りたい人にとっては提案された形の処理では役に立たないわけで. たった数行のコードを書けば必要なものを作れるだけのAPIを既に用意しているのに, さらに個々のわがままを聞いて無暗やたらとライブラリを拡張するのはどうなのかなぁ,とか.
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.7 )
名前:名無三 日時:2021/05/26 19:41

ゲームエンジン的側面と言うのもありますしそもそもDXLIBより低レベルのwin32APIでリリース取れるんですからあったほうが良いでしょうよ、使い所も少なくないですし
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.8 )
名前:ひろかず 日時:2021/05/26 23:22

個人的意見ですが、今更キー入力の拡張バージョンを追加されても使用される方がいらっしゃるのか疑問を感じます。 利用ユーザーそれぞれが使いやすいようにラッピングして使用しているかと思います。 もし、拡張されるのであれば、押しっぱなしのフレーム数が取得できると有り難いです。 あいおい?さんと、なんとなくさんのご意見を合体させて、 離した -1 押していない 0 押している 1〜(押しているフレーム数) という形ではいかがでしょうか?
メンテ
Re: 【提案】キーを押した瞬間と離した瞬間も検知できる関数の追加 ( No.9 )
名前:通りすがりのオールドユーザー 日時:2021/05/27 01:30

個人的には、公開からかなり経つものの、まだまだ初学者にかなり優しい取っつきやすいライブラリだと感じています。 昔々使い始めた頃に、キーを離した状態から押し下げた時の判定(例えば、インベーダーゲームのショットを撃つようなとき)の取り方が分からず、秒間60連射してしまってなかなか解決策が分からず困ったことがありました。 その後も、年単位で離れて、久々にちょこっと使う時に、(以前使ってたソースは使えない前提があって)いちいちそのラッピング関数とか、ラッピングするほどでもない時に処理を作るのもなーと思ってました。 そういう経緯から、その辺がラッピングされた関数がライブラリ側であったら便利だなとか、初学者でもすぐ使える関数あったら便利だろなという所からの提案です。
メンテ
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
メンテ

Page: 1 |

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

   クッキー保存