如何关闭或忽略诅咒应用程序的按键重复?

发布于 2025-01-01 17:25:12 字数 525 浏览 0 评论 0原文

所以我最近发现了curses(特别是PDcurses)并且我刚刚开始研究它。现在我正在尝试用它编写一个小型太空射击游戏,到目前为止它在渲染和获取菜单类型输入方面工作得很好,但现在当我进入游戏时,我注意到按键重复对于动作游戏。我需要能够按住按键并在按键按下的每一帧移动我的头像。我知道如何使用普通的 Win32 应用程序执行此操作,但我没有窗口,因此我没有 wndproc,并且我无法控制控制台收到的消息:/

我不希望这是这样的对于要处理的诅咒,如果可以的话那就太棒了,我真的只是在寻找一种可以很好地处理诅咒的解决方法。

我尝试过 cbreak()、nodelay() 和 raw(),但均无济于事。

附加信息:

  • Microsoft Visual Studio 2010 Ultimate
  • PDcurses 3.4,来自预构建的二进制文件
  • Windows 7 x64 Ultimate

So I recently found curses (specifically PDcurses) and I'm just getting into it. Right now I'm trying to write a little space shooter type game with it and it's worked fine so far for rendering and getting menu type input, but now when I go into the game, I've noticed that key repeat is pretty bad for action games. I need to be able to hold the key and move my avatar every single frame that the key is down. I know how to do this with a normal Win32 application, but I don't have a window and therefore I don't have a wndproc and I can't control the messages the console recieves :/

I don't expect this is something for curses to handle, though if it can that would be awesome, I was really just looking for a work-around that plays nicely with curses.

I have tried cbreak(), nodelay() and raw() to no avail.

Additional info:

  • Microsoft Visual Studio 2010 Ultimate
  • PDcurses 3.4, from prebuilt binaries
  • Windows 7 x64 Ultimate

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

在你怀里撒娇 2025-01-08 17:25:12

这远不是一个完整的解决方案,我不知道它将如何与 PDCurses 交互,但它是一种尝试:

总之,使用 GetStdHandle() 获取控制台的句柄,将其配置为原始使用 SetConsoleMode() 读取,然后使用 ReadConsoleInput() 一次读取一个键。我使用 std::set 来跟踪当前按下的键,从而忽略重复。

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    BOOL success;
    success=GetConsoleMode(h, &mode);
    assert(success);
    mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
    mode |= ENABLE_WINDOW_INPUT;
    success=SetConsoleMode(h, mode);
    assert(success);

    INPUT_RECORD buffer[10];
    std::set<WORD> keys_down;
    while (true)
    {
        DWORD count=0;
        success=ReadConsoleInput(h, buffer, 10, &count);
        if (!success)
        {
            continue;
        }
        for (size_t i=0;i<count;++i)
        {
            switch (buffer[i].EventType)
            {
            case KEY_EVENT:
            {
                WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
                if (buffer[i].Event.KeyEvent.bKeyDown)
                {
                    if (keys_down.find(keycode)==keys_down.end())
                    {
                        std::cout<<"Key down: "<<keycode<<std::endl;
                        keys_down.insert(keycode);
                    }
                }
                else
                {
                    if (keys_down.find(keycode)!=keys_down.end())
                    {
                        std::cout<<"Key up:"<<keycode<<std::endl;
                        keys_down.erase(keycode);
                    }
                }
                break;
            }
            default: 
                break;
            }
        }
    }
}

This is far from a complete solution, and I don't know how it'll interact with PDCurses, but it's an attempt:

In summary, grab the console's handle with GetStdHandle(), configure it for raw reading with SetConsoleMode(), and then read keys one at a time with ReadConsoleInput(). I use a std::set to keep track of the currently pressed keys and so ignore repeats.

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    BOOL success;
    success=GetConsoleMode(h, &mode);
    assert(success);
    mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
    mode |= ENABLE_WINDOW_INPUT;
    success=SetConsoleMode(h, mode);
    assert(success);

    INPUT_RECORD buffer[10];
    std::set<WORD> keys_down;
    while (true)
    {
        DWORD count=0;
        success=ReadConsoleInput(h, buffer, 10, &count);
        if (!success)
        {
            continue;
        }
        for (size_t i=0;i<count;++i)
        {
            switch (buffer[i].EventType)
            {
            case KEY_EVENT:
            {
                WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
                if (buffer[i].Event.KeyEvent.bKeyDown)
                {
                    if (keys_down.find(keycode)==keys_down.end())
                    {
                        std::cout<<"Key down: "<<keycode<<std::endl;
                        keys_down.insert(keycode);
                    }
                }
                else
                {
                    if (keys_down.find(keycode)!=keys_down.end())
                    {
                        std::cout<<"Key up:"<<keycode<<std::endl;
                        keys_down.erase(keycode);
                    }
                }
                break;
            }
            default: 
                break;
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文