1

我正在使用 Ncurses 库在 C++ 中制作 Pacman。我可以用我的代码移动 Pacman,但我想移动它,这样即使我没有按任何键,当我按下另一个方向键时,pacman 也会继续移动,它会改变方向。现在,当我按下一个键时,pacman 只需要一步。此外,在 pacman 朝那个方向移动之前,我必须按下一个键 2 或 3 次。

if (ch==KEY_LEFT)
{
    int b,row,column;
    getyx(stdscr,row,column);
    int h; 
    do    // do-whileloop to move the pacman left until it hits the wall
    {
        column-=1;
        mvprintw(row,column,">");  //print the ">" symbol
        refresh();
        waitf(0.1);      //this pauses the game for 0.1sec
        attron(COLOR_PAIR(1));      
        mvprintw(row,column,">");
        attroff(COLOR_PAIR(1));
        refresh();
        waitf(0.1);
        mvprintw(row,(b),"O");  //showing the open mouth of pacman
        refresh();
        waitf(0.1);
        attron(COLOR_PAIR(1));a
        mvprintw(row,column,"O");
        attroff(COLOR_PAIR(1));
        h = getch();
    }
    while(h == KEY_LEFT);
}

right = getch();

循环在 if 条件下向右移动

up = getch();

在 if 条件下循环向上移动

down = getch();

oop 在 if 条件下向下移动。

4

5 回答 5

5

对此的标准解决方案是有限状态机。角色有六种左右的可能状态:站立、上移、右移、下移、左移、死亡。而不是按键直接移动角色,按键应该改变角色的状态。

在这样一个小型应用程序中,您可以使用一个非常简单的实现,而不是实现一个非常灵活的有限状态机:

enum PlayerState {
    Standing,
    MovingUp,
    MovingRight,
    MovingDown,
    MovingLeft,
    Dead
};

然后,在您的游戏循环中,您可以添加一个非常简单的状态检查,然后对帧采取适当的行动。

switch(state) {
case Standing:
    break;
case MovingUp:
    player.PositionY += 1;
    break;
// ...
}

最后一步是挂钩输入,这取决于您检索输入的方法。使用回调,一个例子是:

void KeyDown(Key k) {
    switch(k) {
    case UpArrow:
        if(state != Dead)
            state = MovingUp;
        break;
    case RightArrow:
        if(state != Dead)
            state = MovingRight;
    // ...
    }
}

您可以看到为什么在一个更大的项目中实现更灵活的有限状态机很重要,但希望这个示例给了您一个易于理解的想法。

于 2012-09-24T15:54:25.573 回答
3

你需要一个等价的kbhit,即。一个非阻塞的getch. 这确实给出了解决方案,设置O_NONBLOCK在输入上。请参阅此处的示例。一旦你有了这个,只需连续循环并检查按键,无需等待实际按键。

于 2012-09-24T15:59:09.797 回答
1

功能getch被阻止,直到按下某个键。如果您不想被阻止,请_kbhit在之前调用,getch确保输入缓冲区中有内容。

编辑:看看 ncurses 函数nodelaycbreak. 它们启用异步输入。

于 2012-09-24T15:56:14.010 回答
0

我建议您看一下模型-视图-控制器模型,它将帮助您解决这些问题以及如果您继续这样的程序会遇到的所有其他问题。

编辑:快捷方式

要连续移动您的 pacman,您将需要一个单独的线程来控制它并使其移动。看看 pthreads 。

如果您只在程序的主运行循环中保留用户输入,那么您必须按几次键的问题也会消失(这里的问题是处理器必须在 getch() 行时按键,否则检测不到。

于 2012-09-24T15:44:32.513 回答
0

每个方向很容易
制作4个功能,在功能内部,放入由kbhit激活的其他3个方向功能。

并放置一个 else 语句,如果你不点击按钮,它会继续前进,即 (!kbhit()); 然后将所有这些放在一个循环中。


如果你对所有方向函数都这样做,你应该能够得到理想的结果。

于 2013-01-23T15:00:06.347 回答