我需要关于SDL键盘事件处理的建议。
我有一个第一人称相机,可以向前走,向后走,左右扫射,用鼠标环顾四周,这很棒。这是我的processEvents函数:
void processEvents()
{
int mid_x = screen_width >> 1;
int mid_y = screen_height >> 1;
int mpx = event.motion.x;
int mpy = event.motion.y;
float angle_y = 0.0f;
float angle_z = 0.0f;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_w:
objCamera.Move_Camera( CAMERASPEED);
break;
case SDLK_s:
objCamera.Move_Camera(-CAMERASPEED);
break;
case SDLK_d:
objCamera.Strafe_Camera( CAMERASPEED);
break;
case SDLK_a:
objCamera.Strafe_Camera(-CAMERASPEED);
break;
default:
break;
}
break;
case SDL_MOUSEMOTION:
if( (mpx == mid_x) && (mpy == mid_y) ) return;
SDL_WarpMouse(mid_x, mid_y);
// Get the direction from the mouse cursor, set a resonable maneuvering speed
angle_y = (float)( (mid_x - mpx) ) / 1000;
angle_z = (float)( (mid_y - mpy) ) / 1000;
// The higher the value is the faster the camera looks around.
objCamera.mView.y += angle_z * 2;
// limit the rotation around the x-axis
if((objCamera.mView.y - objCamera.mPos.y) > 8) objCamera.mView.y = objCamera.mPos.y + 8;
if((objCamera.mView.y - objCamera.mPos.y) <-8) objCamera.mView.y = objCamera.mPos.y - 8;
objCamera.Rotate_View(-angle_y);
break;
case SDL_QUIT:
quit = true;
break;
case SDL_VIDEORESIZE:
screen = SDL_SetVideoMode( event.resize.w, event.resize.h, screen_bpp, SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE );
screen_width = event.resize.w;
screen_height = event.resize.h;
init_opengl();
std::cout << "Resized to width: " << event.resize.w << " height: " << event.resize.h << std::endl;
break;
default:
break;
}
}
}
字符串
现在,虽然这是工作,它有一些局限性。2最大的一个和我的问题的目的是,它似乎只处理最近被按下的关键。3所以,如果我拿着's'向后走,我按'd'扫射的权利,我最终扫射的权利,但不倒退。
有人能为我指出正确的方向,让我用SDL更好地处理键盘,一次支持多个按键吗?
6条答案
按热度按时间bz4sfanl1#
SDL跟踪所有键的当前状态。您可以通过以下方式访问此状态:
SDL_GetKeyState()
所以,每次迭代你都可以根据关键点状态更新移动。为了使移动平滑,你应该根据更新之间经过的时间更新移动幅度。
72qzrwbm2#
一个好的方法是编写一个键盘(“input”)处理程序,它将处理输入事件并将事件的状态保存在某种结构中(关联数组听起来不错- key[keyCode])。
每当键盘处理程序收到一个“keypressed”事件时,它将键设置为启用(true),当它收到一个keydown事件时,它将其设置为禁用(false)。
然后,您可以一次检查多个键,而无需直接提取事件,并且您将能够在整个框架中重用键盘,而无需将其传递给子例程。
一些快速的伪代码:
字符串
omvjsjqw3#
如果您使用的是SDL 2,则使用
SDL_GetKeyboardState
。范例:
字符串
ac1kyiln4#
而不是只看keydown事件,任何解决方案,这将是关心多个键在一次将不得不看keydown和keyup事件,并保持跟踪的状态键的问题。
因此,代替(pseudocode):
字符串
相反,你会得到更像(又是伪代码)的东西:
型
然后,
updateMovement
例程将查看keystates
,并根据所有移动键的状态计算出一个复合移动。omtl5h9j5#
使用SDL_GetKeyState获取键盘状态
nwwlzxa76#
我知道以前的答案很好地解决了这个问题,但我想分享我的方式,区分KeyUp,KeyDown和KeyHold任何键。我所做的基本上是在两个数组中保存所有的键状态,称为Previous和Current,这样我就可以检测到keydown,up并同时继续按键。
字符串
然后我在game循环中使用feed函数,如下所示:
型
最后,这里是代码片段,您可以在任何.cpp上使用它来控制按键
型
GetKeyUp和GetKeyDown也是以同样的方式工作的。希望对你有帮助!