WM_KEYDOWN如何处理不同的密钥?

时间:2014-05-26 04:41:25

标签: c++ winapi opengl game-engine

这是一个相当不寻常的问题,但我需要对Win32如何处理不同的keydown事件进行一些解释。

当你想要接受长按时,使用

WM_KEYDOWN,例如如果你在游戏中,并且想要向前移动,则按向上箭头键或“W”键,游戏中的角色继续前进。 由于WM_KEYDOWN

,您不必多次按键

我有一个基于win32的3D OpenGL应用程序,我在其中使用'W-A-S-D'和arrow key在3D世界中移动。他们都完全按照自己的工作方式工作。

据说,当我进入3D世界时,我可以感觉到Win32处理WASD和箭头键的方式之间存在细微差别。

    case UP_k: 
    f_zPosition-=CAM_MOVEMENT_SPEED; 
     break; 

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

但在游戏中,由于某种原因,箭头键完成的移动比WASD键的移动更顺畅。

  1. Win32如何在内部处理这些事件?
  2. 我该怎么做 WASD的移动像箭头键一样平滑。
  3. 我想知道是否有人在Win32中注意到这一点,这是我的事件循环代码,根据评论中的要求。

    do
    {
        window.displayGL();
        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        TranslateMessage(&msg);
        DispatchMessage (&msg);
    
    }while(msg.message != WM_QUIT);
    

1 个答案:

答案 0 :(得分:5)

在win32应用程序上处理循环的正常消息调用两个函数:

TranslateMessage(&msg);
DispatchMessage(&msg);

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

即使您的应用程序只是查看WM_KEYDOWN并丢弃它们,结果延迟也可能会很明显,尤其是因为每次处理WM_KEYDOWN时都会移动相机

有关详细信息,请查看this

解决方案:

您应该使移动速度与处理输入的速度无关。有两种主要方法:

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

在这两种情况下,在处理输入时都不会移动角色。相反,当您playerIsMoving设置布尔truefalse时},并在获得WM_KEYUP时将其重置为true。然后,仅当变量位于TranslateMessage

时,才会在生成下一帧时应用移动

<强> [UPDATE]

看到你的主循环后: 尝试修改它:

修改1 :注释掉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; } 。除非你想在你的应用程序中使用文本框等,否则你不需要它。

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

{{1}}
相关问题