我使用Ncurses库在C ++中制作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条件下向下移动。
答案 0 :(得分:5)
标准解决方案是finite-state machine。角色有六种可能的状态:站立,向上移动,向右移动,向下移动,向左移动,死亡。按键应该改变角色的状态,而不是直接移动角色的按键。
在如此小的应用程序中,您可以使用非常简单的实现,而不是实现一个非常灵活的有限状态机:
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;
// ...
}
}
你可以看到为什么在一个更大的项目中实现一个更灵活的有限状态机是很重要的,但希望这个例子给你一个易于理解的想法。
答案 1 :(得分:3)
您需要等效的kbhit
,即。非阻塞getch
。这确实给出了解决方案,在输入上设置O_NONBLOCK
。查看示例here。一旦你有这个,只需连续循环,只需检查按键命中,无需等待实际按键。
答案 2 :(得分:1)
功能getch
被阻止,直到按下某个键。如果您不想被阻止,请在_kbhit
之前调用getch
,确保输入缓冲区中有内容。
编辑:看看ncurses函数nodelay
和cbreak
。它们启用异步输入。
答案 3 :(得分:0)
我建议你看一下model-view-controller模型,它会帮助你解决这个问题,以及如果你继续这样的程序你会遇到的所有其他问题。
编辑:快捷方式
要持续移动你的pacman,你需要一个单独的线程来控制它并让它移动。看看pthreads吧。
如果你只在程序的主运行循环中保留用户输入,你必须按几次键的问题也会消失(这里的问题是处理器必须在getch上( )按键时行,否则将无法检测到。
答案 4 :(得分:0)
很容易 为每个方向做4个功能 在函数内部,放入由kbhit激活的另一个3方向函数。
如果你没有按下按钮,那么就把它继续前进的else语句(!kbhit()); 然后将所有这些放在一个循环中。如果对所有方向功能执行此操作,您应该能够获得理想的结果。