You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下C语言+ncurses开发Chrome恐龙游戏:实现无阻塞键盘监听

解决ncurses下恐龙游戏的非阻塞输入与游戏循环问题

要实现游戏世界持续运行同时监听键盘输入,核心是把ncurses设置为非阻塞输入模式,结合固定帧率的主循环来处理逻辑。以下是具体实现步骤:

1. 配置ncurses的非阻塞输入

在初始化ncurses时,添加以下关键设置,替代默认的阻塞式输入:

initscr();          // 初始化ncurses环境
cbreak();           // 禁用行缓冲,直接响应单个按键输入
noecho();           // 不回显输入的字符到屏幕
nodelay(stdscr, TRUE); // 将标准窗口设为非阻塞模式,getch()无输入时立即返回ERR
keypad(stdscr, TRUE);  // 支持识别方向键等特殊按键

其中nodelay(stdscr, TRUE)是核心:它让getch()不再阻塞程序执行,没有按键输入时会立刻返回ERR,确保游戏循环能持续运行。

2. 构建非阻塞的游戏主循环

主循环需要按「输入处理→状态更新→画面渲染→帧率控制」的顺序执行,确保游戏逻辑和输入监听并行:

// 定义恐龙和障碍物的状态结构体
typedef struct {
    int y;
    int velocity;
    int is_jumping;
} Dino;

typedef struct {
    int x;
    int y;
    int speed;
} Obstacle;

#define JUMP_FORCE 5
#define GRAVITY 1
#define OBSTACLE_SPEED 2

int main() {
    // 初始化ncurses
    initscr();
    cbreak();
    noecho();
    nodelay(stdscr, TRUE);
    keypad(stdscr, TRUE);

    // 初始化游戏对象状态
    Dino dino = {10, 0, FALSE};
    Obstacle obstacle = {COLS, 10, OBSTACLE_SPEED};

    while (1) {
        // 1. 处理键盘输入
        int ch = getch();
        if (ch != ERR) { // 仅当有输入时处理
            if (ch == KEY_UP || ch == ' ') { // 空格或上方向键触发跳跃
                if (!dino.is_jumping) {
                    dino.velocity = -JUMP_FORCE;
                    dino.is_jumping = TRUE;
                }
            } else if (ch == 'q') { // 按q键退出游戏
                break;
            }
        }

        // 2. 更新游戏状态
        // 模拟恐龙跳跃与重力落地
        if (dino.is_jumping) {
            dino.y += dino.velocity;
            dino.velocity += GRAVITY;
            // 落地检测,重置跳跃状态
            if (dino.y >= 10) {
                dino.y = 10;
                dino.is_jumping = FALSE;
                dino.velocity = 0;
            }
        }

        // 移动障碍物,出界后重置位置
        obstacle.x -= obstacle.speed;
        if (obstacle.x < 0) {
            obstacle.x = COLS;
        }

        // 简单碰撞检测
        if (dino.y == obstacle.y && obstacle.x <= 5 && obstacle.x >= 0) {
            mvprintw(LINES/2, COLS/2 - 5, "Game Over!");
            refresh();
            usleep(2000000);
            break;
        }

        // 3. 渲染游戏画面
        clear();
        mvprintw(dino.y, 0, "X"); // 绘制恐龙
        mvprintw(obstacle.y, obstacle.x, "#"); // 绘制障碍物
        refresh();

        // 4. 控制帧率(约60帧/秒,每帧间隔16ms)
        usleep(16667);
    }

    // 清理ncurses资源
    endwin();
    return 0;
}

关键注意事项

  • 忽略getch()返回的ERR:没有按键输入时,getch()会返回ERR,此时直接跳过输入处理逻辑即可。
  • 强制帧率控制:必须用usleep()或nanosleep()限制循环速度,否则游戏会因CPU运行过快导致逻辑和画面异常。
  • 跳跃状态锁:添加is_jumping标志,避免玩家连续触发跳跃导致恐龙异常升空。

内容的提问来源于stack exchange,提问作者Andrej Rišian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:31:12