【问题标题】:how to print two things simultaneously with ncurses如何用ncurses同时打印两件东西
【发布时间】:2014-07-10 03:17:52
【问题描述】:

我正在制作一个类似于太空入侵者的 ncurses 游戏。

到目前为止,我已经移动并击落,但我遇到了问题。

当玩家发射激光时,我正在使用 usleep 调用来延迟激光在屏幕上的移动,这样它就不会只从屏幕的一端显示到另一端。

使用 usleep 来延迟激光的问题意味着玩家在激光穿过屏幕时无法移动,直到循环退出。

我的问题是,是否有另一种方法可以打印在屏幕上移动的激光,同时通过用户输入移动播放器/光标?

当用户按下“f”键时,以下代码会在屏幕上移动线条(激光)。但是,在激光离开屏幕之前,用户不能再次移动:

void combat(int y, int x)
{
    do
    {
        mvprintw(y -1, x, "|");
        refresh();
        y--;
        usleep(50000);
        mvprintw(y , x, " ");   
    }
    while(y>0);
}

【问题讨论】:

    标签: c printing ncurses usleep


    【解决方案1】:

    如果没有外部线程,这个问题无法轻易解决。通过将激光的移动绑定到输入来移除睡眠功能(这样只有在应该通过外部输入刷新屏幕时才更新位置)是行不通的,因为您需要激光独立于其他一切。

    一个肮脏的黑客可能是:

    • 通过int nodelay(WINDOW *win, bool bf) 非阻塞输入函数,这样输入函数就不会阻塞任何东西
    • 给定的(足够高的)刷新率,例如 10 FPS(100 毫秒的睡眠)
    • 每帧更新一次激光位置,使其移动足够慢,但能够足够频繁地轮询输入

    【讨论】:

      【解决方案2】:

      最简单的解决方案是使用包含一条睡眠指令的循环编写程序,例如:

      frame_timer = 0;
      while (1) {
        if (player_is_alive) {
          move_player();
          move_aliens();
          move_laser_bullets();
          check_collisions();
        }
        else {
          draw_explosion();
          if (explosion_finished) break;
        }
        frame_timer++;
        usleep(20000);  /* Refresh at approximately 50fps */
      }
      

      【讨论】:

        【解决方案3】:

        我实际上已经找到了解决我自己问题的好方法,所以我将把它留在这里,以防将来有人遇到类似问题。

        当我的程序进入战斗功能时,它也会进入 nodelay 模式,生成一个非阻塞 getch()。当函数在睡眠中循环时,用户可以在任何时候输入一个字符,导致船移动,并且由于它处于无延迟模式,如果用户选择保持静止,getch() 不会阻止睡眠函数的执行。

        当用户按下'f'时执行的战斗功能:

        void combat(int y, int x)
        {
        int input;
        int y2 = y;
        int x2 = x;
        do
        {
            mvprintw(y2 -1, x2+1, "|");
            refresh();
            y2--;
            mvprintw(y2 , x2+1, " ");
            usleep(50000);
            nodelay(stdscr, TRUE);
            input = getch();
        
            switch(input)
            {
                case 'w':
                mvprintw(y, x,"   ");
                y--;
                mvprintw(y, x,"^V^");
                break;
        
                case 'a':
                mvprintw(y, x+2," ");
                x--;
                mvprintw(y, x,"^V^");
                break;
        
                case 's':
                mvprintw(y, x,"   ");
                y++;
                mvprintw(y, x,"^V^");
                break;
        
                case 'd':
                mvprintw(y, x," ");
                x++;
                mvprintw(y, x,"^V^");
                break;
        
            }
        
        }
        while(y2>0);
        movement(y,x);
        

        }

        【讨论】:

        • usleep(50毫秒)和nodelay的组合是多余的。您可以在 50 毫秒内使用 timeout() - 在循环之外 - 并获得相同的效果。另外,usleep 不是一个 curses 函数; curses 提供了 napms。使用睡眠的响应存在干扰重新绘制屏幕的问题。
        猜你喜欢
        • 1970-01-01
        • 2016-03-25
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        相关资源
        最近更新 更多