简体   繁体   English

如何使用ncurses同时打印两件事

[英]how to print two things simultaneously with ncurses

I'm making a game in ncurses similar to space invaders. 我正在用类似于太空侵略者的游戏制作游戏。

Thus far I've gotten movement and shooting down but I've run into an issue. 到目前为止,我已经动弹不得,但是我遇到了一个问题。

When the player fires a laser I am using a usleep call to delay the laser moving across the screen so that it doesn't just show up from one end of the screen to the other. 当播放器发射激光时,我正在使用usleep通话来延迟激光在屏幕上的移动,以使它不仅仅从屏幕的一端显示到另一端。

The problem with using usleep to delay the laser means that the player cannot move around while the laser is travelling across the screen until the loop exits. 使用usleep延迟激光器的问题意味着,当激光器在屏幕上移动时,直到循环退出,播放器才能四处走动。

My question is, is there another way to print the laser moving across the screen while at the same time moving the player/cursor with user input? 我的问题是,是否有另一种方法可以打印在屏幕上移动的激光,同时通过用户输入来移动播放器/光标?

When the user presses the 'f' key the following code moves the line (laser) across the screen. 当用户按下“ f”键时,以下代码在屏幕上移动该行(激光)。 However the user cannot move again until after the laser has left the screen: 但是,直到激光离开屏幕后,用户才能再次移动:

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

This issue can't be solved easily without an external thread. 没有外部线程就无法轻松解决此问题。 Removing the sleep function by binding the movement of the laser to the input (so that the position is updated only when the screen should be refreshed by external input) wouldn't work because you need the laser to be independent from everything else. 通过将激光器的运动绑定到输入端来删除睡眠功能(以便仅在应该通过外部输入刷新屏幕时更新位置)将无法工作,因为您需要使激光器独立于其他一切。

A dirty hack could be to have: 肮脏的骇客可能是:

  • nonblocking input functions through int nodelay(WINDOW *win, bool bf) so that the input function won't block anything 通过int nodelay(WINDOW *win, bool bf)非阻塞输入函数int nodelay(WINDOW *win, bool bf)以便输入函数不会阻塞任何东西
  • a given (enough high) refresh rate, eg 10 FPS (sleep of 100 msec) 给定的(足够高的)刷新率,例如10 FPS(睡眠100毫秒)
  • updating the laser position only once every an amount of frames, to have it move enough slowly but being able to poll for input enough often 每隔一帧仅更新一次激光位置,以使其移动足够缓慢,但能够经常轮询输入

The easiest solution would be to write your program with a loop containing one sleep instruction, eg: 最简单的解决方案是使用包含一条睡眠指令的循环编写程序,例如:

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 */
}

I've actually found a decent solution to my own problem so I'll leave this here in case anyone has a similar issue in the future. 实际上,我已经为自己的问题找到了一个不错的解决方案,因此,如果将来有人遇到类似的问题,我将在此保留。

When my program enters the combat function it also enters into nodelay mode making a non blocking getch(). 当我的程序进入战斗功能时,它也会进入nodelay模式,并生成一个非阻塞的getch()。 As the function cycles through sleeps the user can enter a character at any time causing the ship to move and since it is in no delay mode the getch() does not block the sleep function from executing if the user chooses to stay still. 随着该功能在睡眠中循环,用户可以在任何时候输入一个字符,从而使飞船移动,并且由于它处于无延迟模式,因此如果用户选择保持静止,getch()不会阻止睡眠功能的执行。

The combat function which executes when the user presses 'f': 用户按下“ 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);

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM