首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WM_KEYDOWN如何处理不同的密钥?

WM_KEYDOWN如何处理不同的密钥?
EN

Stack Overflow用户
提问于 2014-05-26 04:41:25
回答 1查看 1.5K关注 0票数 2

这是一个非常不寻常的问题,但我需要解释一下Win32如何处理不同的按键事件。

当您想要接收长按压时,可以使用WM_KEYDOWN,例如,如果您在游戏中,而您想向前移动,则按下箭头键或'W‘键,游戏中的字符将继续前进。您不必多次按键,因为有WM_KEYDOWN

我有一个3D OpenGL应用程序,基于win32,在这个应用程序中,我使用‘world’和arrow key在3D世界中移动。他们俩的工作方式都和他们应该做的一样。

尽管如此,当我身处3D世界时,我可以感觉到Win32处理WASD和箭头键的方式之间有着微妙的区别。

代码语言:javascript
运行
复制
    case UP_k: 
    f_zPosition-=CAM_MOVEMENT_SPEED; 
     break; 

同样的代码也用于case 'W':

但在游戏中,由于某种原因,箭头键所做的移动要比WASD键的移动平稳得多。

  1. Win32如何在内部处理这些事件?
  2. 如何使WASD的移动像箭头键一样平滑。

我想知道是否有人在Win32中注意到这一点,这是我的事件循环代码,按照注释中的要求。

代码语言:javascript
运行
复制
do
{
    window.displayGL();
    PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
    TranslateMessage(&msg);
    DispatchMessage (&msg);

}while(msg.message != WM_QUIT);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-26 05:17:59

win32应用程序上的普通消息处理循环调用两个函数:

代码语言:javascript
运行
复制
TranslateMessage(&msg);
DispatchMessage(&msg);

第一个函数,TranslateMessage查看虚拟密钥消息(例如WM_KEYDOWN消息),然后如果按下的键对应于字符键,则将字符消息添加到消息队列中。如果按下'W'键,就会生成大量的WM_KEYDOWN,因为它具有自动重复功能。箭头键也是如此,但是在'W‘的情况下,对于每个WM_KEYDOWN也会生成一个WM_CHAR,您的应用程序必须对其进行处理。

即使您的应用程序只是查看WM_CHAR并丢弃它们,由此产生的延迟也可能是显而易见的,特别是因为每次处理WM_KEYDOWN时都会移动摄像机。

有关更多信息,请查看

解决方案:

你应该使你的运动速度独立于你处理输入的速度。有两种主要方法可以做到这一点:

  • 固定帧:每秒更新屏幕固定次数。每次更新时,将相机/播放机移动相同的距离。
  • time frames尽可能多地更新屏幕,但是要测量迭代之间的时间。移动时,将移动速度乘以上次更新后的时间。

在这两种情况下,当您处理输入时,不会移动您的字符。相反,当您得到WM_KEYDOWN时,将布尔型playerIsMoving设置为true,并在得到WM_KEYUP时将其重置为false。然后,只有在变量在true中时,才会在生成下一个帧时应用该移动。

更新

看到主循环之后:尝试像这样修改它:

修改1:注释掉TranslateMessage。你不需要它,除非你想在你的应用程序中有文本框之类的东西。

修改2:添加一个单独的函数来更新世界状态。

代码语言:javascript
运行
复制
do
{
    UpdateWorld()
    window.displayGL();
    PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
    //TranslateMessage(&msg);
    DispatchMessage (&msg);

}while(msg.message != WM_QUIT); 

// I won't define exactly all of this, you can get an idea 
// what I'm doing by the names. playerIsMoving should be set
// and reset in the `WindowProcedure` when processing 'WM_KEYDOWN/UP':
void UpdateWorld(){
    float delta = timeSinceLastCall()
    if(playerIsMoving)
        player.pos += speed * delta;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23862825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档