0

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

到目前为止,我已经获得了移动和击落,但我遇到了一个问题。

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

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

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

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

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

3 回答 3

0

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

当我的程序进入战斗功能时,它也会进入 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);

}

于 2014-07-11T03:51:07.217 回答
0

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

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 */
}
于 2014-07-10T06:52:39.240 回答
0

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

一个肮脏的黑客可能是:

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