我正在开发一个小游戏引擎,无法决定如何处理键盘输入。到目前为止,我一直在通过从窗口过程中捕获WM_KEYDOWN
和WM_KEYUP
消息来处理键盘输入,但是在我看来这并不是处理键盘输入的好方法。
我非常喜欢Infinity Ward 3.0引擎,您可以使用简单的配置文件或使用游戏控制台轻松更改每个键操作。我想这样做。
以下是来自IW 3.0引擎的配置文件的片段:
bind TAB "+scores"
bind ESCAPE "togglemenu"
bind SPACE "+gostand"
bind ALT "gocrouch"
bind CTRL "goprone"
bind SHIFT "+breath_sprint"
bind 1 "weapnext"
bind 2 "weapnext"
bind 4 "+smoke"
bind 5 "+actionslot 3"
bind 6 "+actionslot 4"
bind 7 "+actionslot 2"
bind ` "toggleconsole"
bind A "+moveleft"
bind B "mp_QuickMessage"
bind D "+moveright"
bind E "+leanright"
您甚至可以将其他操作分配给键,例如聊天中的内容:
bind F3 "say Hello, World!"
我已经有了配置文件,我正在游戏启动时阅读,之后我会初始化所有操作键。它有效,但将所有键分配给所有操作真的很不舒服。对于像A, B, C, D, E
这样的键,这很容易,因为每个字符的ASCII码对应WM_KEYDOWN/UP
消息,但对于像SPACE, CTRL, SHIFT
这样的键则不然。
所以我的问题是:
答案 0 :(得分:2)
很抱歉迟到了回复帖子,我在最近2天没有回家。 我已经完成了这个问题。根据我的第一个问题,我选择原始键盘输入,如果有兴趣的话,这里是代码:
std::map<string, bool> myKey;
bool KEYBOARD_INPUT::GetRawKeyboardData(LPARAM lParam)
{
char buffer[sizeof(RAWINPUT)];
UINT size = sizeof(RAWINPUT);
GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(buffer);
if(raw->header.dwType == RIM_TYPEKEYBOARD)
{
const RAWKEYBOARD& rawKeyboard = raw->data.keyboard;
unsigned int scanCode = rawKeyboard.MakeCode;
unsigned int flags = rawKeyboard.Flags;
const bool E0 = ((flags & RI_KEY_E0) != 0);
const bool E1 = ((flags & RI_KEY_E1) != 0);
const bool KeyDown = !((flags & RI_KEY_BREAK) != 0);
UINT key = (scanCode << 16) | (E0 << 24);
char buffer[32];
GetKeyNameText((LONG)key, buffer, 32);
if(KeyDown) // Press
{
myKey[buffer] = true;
}
else // Release
{
myKey[buffer] = false;
}
}
return true;
}
这是获取实际按键状态的功能:
bool KEYBOARD_INPUT::KeyPressed(string key, int mode)
{
if(mode == ONLYONCE)
{
if(myKey[key] && pressed_onlyonce[key] == false)
{
pressed_onlyonce[key] = true;
return true;
}
if(!myKey[key])
{
pressed_onlyonce[key] = false;
return false;
}
}
else if(mode == CONTINUOUS)
{
if(myKey[key] == true)
{
return true;
}
else
{
return false;
}
}
else if(mode == TOGGLE)
{
if(myKey[key] && pressed_toggle[key] == false)
{
pressed_toggle[key] = true;
released_toggle[key] = !released_toggle[key];
return released_toggle[key];
}
else if(!myKey[key])
{
pressed_toggle[key] = false;
return released_toggle[key];
}
}
return false;
}
我认为代码也是我其他问题的答案。 如果有人对此课程的完整源代码感兴趣,请在评论部分告诉我。
我想,我可以关闭这个帖子,我特别感谢@IInspectabl ,非常感谢你!
答案 1 :(得分:-3)
有很多方法。捕获密钥的好方法是使用ReadConsoleInput()
然后
处理switch
语句中的密钥代码。正如您在下面的代码中看到的那样
您也可以“绑定”switch
语句中的键。
#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD mode; /* Preserved console mode */
INPUT_RECORD event; /* Input event */
BOOL EXITGAME = FALSE; /* Program termination flag */
unsigned int counter = 0; /* The number of times 'Esc' is pressed */
/* Get the console input handle */
HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );
/* Preserve the original console mode */
GetConsoleMode( hstdin, &mode );
/* Set to no line-buffering, no echo, no special-key-processing */
SetConsoleMode( hstdin, 0 );
while (!EXITGAME)
{
if (WaitForSingleObject( hstdin, 0 ) == WAIT_OBJECT_0) /* if kbhit */
{
DWORD count; /* ignored */
/* Get the input event */
ReadConsoleInput( hstdin, &event, 1, &count );
cout<<"Key Code = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n";
}
/* Only respond to key release events */
if ((event.EventType == KEY_EVENT)
&& !event.Event.KeyEvent.bKeyDown)
{
switch (event.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
EXITGAME = TRUE;
break;
case VK_SPACE:
break;
case VK_RETURN:
break;
case VK_LEFT:
// left key move player left
cout<<"VK_LEFT = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n";
break;
case VK_RIGHT:
// right key move player right
cout<<"VK_RIGHT = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n";
break;
case VK_UP:
// up key move player up
cout<<"VK_UP = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n";
break;
case VK_DOWN:
// up key move player down
cout<<"VK_DOWN = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n";
break;
}//switch
event.Event.KeyEvent.wVirtualKeyCode=-1;
}
}
return 0;
}
虚拟键列表:https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
ReadConsoleInput:https://msdn.microsoft.com/en-us/library/windows/desktop/ms685035(v=vs.85).aspx