さて、私は非推奨のDirectInputの使用を避けようとしています。
しかし、ゲームの「フレーム」または「反復」ごとに、それに応じて行動できるように、すべての主要な状態を奪う必要があります。たとえば、プレーヤーがVK_RIGHTキーを押している場合、そのフレーム上でsmidgenだけを右に移動します。
WM_INPUTメッセージの問題は、ゲームループの記述方法が原因で、フレームごとに予測できない回数表示される可能性があることです。
MSGメッセージ; while(1) {{ if(PeekMessage(&message、NULL、0、0、PM_REMOVE)) {{ if(message.message == WM_QUIT) {{ 壊す ; //WM_QUIT時に保釈 } TranslateMessage(&message); DispatchMessage(&message); } そうしないと {{ //メッセージがないので、ゲームを実行します。 アップデート() ; 描く() ; } }
したがって、複数のWM_INPUTメッセージがそこにスタックされている場合、それらはすべてUpdate()/ Draw()の前に処理されます。
BOOLの配列を使用して、どのキーがダウンしていたかを記憶することで、この問題を解決しました。
bool array_of_keys_that_are_down [256]; ケースWM_INPUT: if(そのキーボード入力) {{ array_of_keys_that_are_down [VK_CODE] = TRUE; }
Update()関数がチェックするため、これは正常に機能します
void Update() {{ if(array_of_keys_that_are_down [VK_RIGHT]) {{ //プレーヤーを少し右に動かします } }
しかし、問題は、WM_INPUTメッセージが十分な頻度で生成されないことです。プレーヤーがずっと指を下に置いていたとしても、VK_RIGHTの最初の押下とその後のVK_RIGHTメッセージの間に約1秒の遅延があります。これは、DirectInputとは異なりますkeyboard->GetDeviceState( 256, (void*)array_of_keys_that_are_down );
(1回の呼び出しで各フレームのすべてのキー状態をスナッチアウトします)
だから私は迷子になりました。監視する必要のある各キーに対してGetAsyncKeystate()関数呼び出しを使用する以外に、フレームごとにすべてのキー状態を確実に取得できない場合は、DirectInputの使用を回避する方法はありません。
DirectInputはこの問題に対する非常に優れた解決策であるように思われますが、非推奨になった場合は、Win32APIのみを使用してこれを便利に行う方法が本当に必要です。
現在array_of_keys_that_are_down
、すべてのFALSEのすべてのフレームにリセットされます。
memset(array_of_keys_that_are_down、0、sizeof(array_of_keys_that_are_down));
*編集
私はこの問題に取り組んできましたが、1つの解決策は、キーの状態が解放されたら、それをリセットすることだけです。
ケースWM_INPUT: if(そのキーボード入力) {{ if(そのダウンプレス) array_of_keys_that_are_down [VK_CODE] = TRUE; そうしないと array_of_keys_that_are_down [VK_CODE] = FALSE; }
それは薄っぺらなように見えるので、私はこの解決策が好きではありません。ユーザーがキーを押しているときにアプリケーションから離れると、アップストロークWM_INPUTメッセージが表示されないため、ユーザーがスイッチを戻して同じキーをもう一度押すまで、そのキーは「スタック」します。それは奇妙な「スティッキーキー」のバグになります。