C - 如何在 ncurses 库中使用 halfdelay(i)

C - How to use halfdelay(i) in the ncurses library

我正在尝试使用 ncurses 库在 C 中创建贪吃蛇游戏。我希望我的程序以恒定的滴答速度检测用户输入。如果在一定时间后没有输入,我希望我的程序继续(即更新游戏)。

这是我为测试 halfdelay(i) 函数而写的:

#include <ncurses.h>

int main(void)
{
    initscr();
    halfdelay(5);
    
    int user_input;

    do
    {
        user_input = getch();

        if (user_input != -1)
        {
            clear();
            printw("Key pressed: %d\n", user_input);
        }
        else
        {
            //printf("Timeout.\n");  
            printw("Timeout.\n");
        }
    } while (user_input != ESC);

    endwin();

    return 0;
}

编辑#1:
我想看看
超时。
超时。
超时。

使用的代码:

#include <ncurses.h>

int main(void)
{
    initscr();
    halfdelay(5);

int in;

    do
    {
        timeout(1);
        in = getch();

        if (in != -1)
        {
            clear();
            printw("Key pressed: %d\n", in);
        }
        else
        {
            //printf("Timeout.\n");  
            printw("Timeout.\n");
        }

        refresh();
    } while (in != 27);

    endwin();

    return 0;

}

先说点历史。

传统上,ESC 键值被用作 escape sequences 的前缀,表示可以解释为非图形字符的特殊字符序列(例如,箭头键、功能键等)

由于 (n)curses 专注于便携性(和电信),它开箱即用地支持这种转义序列的概念,因此按下 ESC 键可能有一些副作用。值得注意的是,当启用 keypad 时,程序会等待确定用户是简单地按下 ESC 还是需要等待更多信息来完成,因此存在内置延迟转义序列。这个时间可以通过 ESCDELAY 环境变量或 set_escdelay 函数来调整。

所有这些在您继续前进时都很重要,因为它是一款您可能希望最终启用 keypad 功能的游戏,这将在使用 ESC 时创建一些额外的步骤 键。

由于这一切,转义键没有 ESCKEY_ESC 宏。相反,它的原始代码是 27(或八进制 033)。

你对 halfdelay 函数的使用对我来说似乎非常好,只要知道参数是 十分之一秒 ,所以 5 是半秒钟。十分之一秒在游戏中可能达不到预期的效果,因此请考虑使用 timeout 函数,这样可以提高精度。

一个简单的工作示例:

#include <ncurses.h>

int main(void) {
    initscr();
    halfdelay(5);
    
    int user_input;
    
    while ((user_input = getch()) != 27) {                
        clear();                                     
                                                     
        if (user_input == ERR)
            printw("Timeout.");
        else
            printw("Key pressed: %d\n", user_input);                                                                  
                                                                                                                      
        refresh();                                                                                                    
    }                                                                                                                 
                                                                                                                      
    endwin();                                                                                                         
}

您更新的程序“有效”,只是不能正确清除屏幕。请注意,您可能不想混合调用 printwprintf,因为它会造成屏幕出现奇怪的混乱。

此外,您应该使用 halfdelay timeout,但不能同时使用。请记住,timeout 毫秒 为单位获取参数,即 1/1000 秒,并且它设置了 window 的阻塞延迟timeout 代表 stdscrwtimeout 代表特定的 windows)。这不是“睡眠”风格的功能。

一次使用一个延迟函数,将clear移到if语句之外,并使用printw。这在功能上与上面发布的程序相同,只是带有一个 do ... while 循环。

#include <ncurses.h>

int main(void) {
    initscr();
    /*
    noecho();
    scrollok(stdscr, TRUE);
    */
    timeout(500);
                   
    int in;        

    do {
        in = getch();
        
        clear();
        
        if (in != ERR)
            printw("Key pressed: %d\n", in);
        else
            printw("Timeout.\n");
        
        refresh();
    } while (in != 27);

    endwin();
}

如果您希望此程序的显示类似于

Timeout.
Timeout.
Key pressed: 65
Timeout.
...

就像一个更传统的终端,然后你只想一起删除 clear,并取消注释 noechoscrollok.