即使没有按下键,我如何在屏幕上发生某些事情
How do I make something happen on the screen even without a key being pressed?
我正在C++用Ncurses库制作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();
哎呀,在 if 条件下向下移动。
对此的标准解决方案是有限状态机。角色有六种左右可能的状态:站立、向上移动、向右移动、向下移动、向左移动、死亡。不是直接按键移动字符,而是应该更改字符的状态。
在这样一个小的应用程序中,与其实现一个非常灵活的有限状态机,不如使用一个非常简单的实现,如下所示:
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;
// ...
}
}
您可以看到为什么在更大的项目中实现更灵活的有限状态机很重要,但希望此示例为您提供了一个易于理解的想法。
你需要一个等价的kbhit
,即非阻塞getch
。这真正给出了解决方案,在输入上设置O_NONBLOCK
。请参阅此处的示例。一旦你有了这个,只需连续循环,只检查按键命中,没有等待实际按键。
功能getch
被阻止,直到按下某个键。如果您不想被阻止,请在getch
之前调用_kbhit
,并确保输入缓冲区中有一些内容。
编辑:看看ncurses函数nodelay
和cbreak
。它们启用异步输入。
我建议你看看模型-视图-控制器模型,它将帮助您解决此问题以及如果您继续这样编程将遇到的所有其他问题。
编辑:快捷方式
要连续移动你的吃豆人,你需要一个单独的线程来控制它并让它移动。看看pthreads。
如果你只在程序的主运行循环中保留用户输入,你必须按几次键的问题也会消失(这里的问题是当你按下键时处理器必须在 getch() 行上,否则它不会被检测到。
这很容易
每个方向使 4 个功能在函数内部,放入由kbhit激活的其他3个方向函数。
并放置一个 else 语句,如果您不点击按钮,它将继续前进,即 (!kbhit());然后将所有这些放在一个循环中。
如果对所有方向函数执行此操作,您应该能够获得所需的结果。
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 使用 SFML 和 C++ 将 Pixel 打印到屏幕上
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- Winapi:屏幕截图未显示在窗口中
- 如何在快板的屏幕中显示子位图的绘制?
- 按回车键后输出屏幕关闭
- 要在屏幕上绘制一些小瓷砖,我应该使用 QQuickItem 还是 QQuickPaintedItem?
- SFML 向下移动时如何围绕屏幕中心旋转?
- 截取屏幕截图后程序卡住
- C++鼠标单击时的屏幕截图不起作用
- 屏幕插入运算符<<的运算符过载问题
- 获取网格中心的屏幕位置
- SFML 中的字体.信息不显示在屏幕上.显示的不是信息,而是点
- 如何在屏幕上环绕x和y?
- GetDIBits 在屏幕捕获函数中多次迭代后返回零
- OpenGL ES 2.0将纹理绘制到屏幕上是行不通的
- GTKMM:拍摄绘图区域的屏幕截图?
- OpenGL - 添加第二个着色器属性会导致空白屏幕
- 使用 C++将文本光标移动到屏幕中不可见的行