2012-02-02 35 views
2

所以我最近发现了诅咒(特别是PDcurses),我正在进入它。现在我正在尝试写一个空间射击游戏类型的小游戏,目前它的渲染和获取菜单类型输入的效果很好,但是现在当我进入游戏时,我注意到关键重复对于动作类游戏。我需要能够保存密钥并移动我的头像每一个关键帧关闭的帧。我知道如何用普通的Win32应用程序来做到这一点,但我没有窗口,因此我没有wndproc,我无法控制控制台收到的消息:/如何关闭或忽略我的curses应用程序的重复键?

我没有希望这是诅咒能够处理的东西,但如果它可能会非常棒,我真的只是寻找一种可以很好地与诅咒玩的解决方法。

我试过cbreak(),nodelay()和raw()无济于事。

附加信息:

  • 微软的Visual Studio 2010旗舰版
  • PDcurses 3.4,从预编译的二进制
  • 的Windows 7 64位旗舰版
+2

我想一个更有趣的问题是,“你怎么知道钥匙什么时候被释放? 'getch()'不会告诉你这一点。我怀疑这两个问题的答案都是一样的:设计你的输入法,所以这个烦恼并不重要。 – Managu 2012-02-02 01:14:46

+0

那么你有解决方案吗?在win32控制台中完全避免键弹出的方法?因为我所能想到的所有输入方式都需要一个窗口(例如SDL,RAW输入,dinput) – 2012-02-02 01:39:47

+0

我在想:“记住最近按下的按键,忽略按键” – Managu 2012-02-02 01:48:58

回答

2

这是远从一个完整的解决方案,我不知道它将如何与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; 
      } 
     } 
    } 
} 
+0

我想这样做,但它与curses的兼容性可能为零,我会尝试。 'mode&=〜(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);''实际上可以通过'noecho()'和'cbreak()'函数通过curses获得,但是'ENABLE_WINDOW_INPUT'标志可能是问题的真正根源。我会看看'getch()'是否受它影响。And thanks :) – 2012-02-02 04:11:57

+0

唉,'getch()'不在意:(我猜窗口函数是你应该在Windows上使用的东西,我经常在我尝试将UNIX库应用于Windows然后在窗户不起作用时生气 – 2012-02-02 04:34:21

+0

我认为重点在于,UNIX终端的设计不是提供这样的功能(关键通知)。如果您有兴趣用curses编写游戏,它应该如果没有“hold-the-key-down”控制,那么这是一个合理的选择 – Managu 2012-02-02 05:37:19