【问题标题】:How do I make something happen on the screen even without a key being pressed?即使没有按键,我如何在屏幕上发生某些事情?
【发布时间】:2012-09-24 15:42:37
【问题描述】:

我正在使用 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 条件下向下移动。

【问题讨论】:

  • 设置这样一个条件,当用户移动 pacman 时,它会进入一个循环,只有当它到达墙壁时才会停止并等待下一条指令。
  • 但我希望每当按下另一个键时,pacman 都会改变它的方向。

标签: c++ game-physics ncurses


【解决方案1】:

此问题的标准解决方案是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;
    // ...
    }
}

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • +1 表示 O_NONBLOCK,我已经有一段时间没有接触这些 C API了。
    【解决方案3】:

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

    编辑:查看 ncurses 函数 nodelay 和 cbreak。它们启用异步输入。

    【讨论】:

    • 我无法将 kbhit() 与 ncurses 一起使用。
    • 您使用的是什么操作系统,您使用什么编译器?
    • g++ 编译器。我正在使用腻子软件连接我的大学服务器。
    • 你是用windows通过Putty连接的,但是代码是在服务器上运行的,而且服务器可能是某种Linux。
    【解决方案4】:

    我建议你看看model-view-controller 模型,它将帮助你解决这个问题以及如果你继续这样的程序会遇到的所有其他问题。

    编辑:快捷方式

    要连续移动你的 pacman,你需要一个单独的线程来控制它并让它移动。看看 pthreads。

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

    【讨论】:

    • 这个答案太宽泛,并没有真正回答问题。
    • 我是初学者,时间不够。请问您能告诉我其他解决方案吗?
    • 你能告诉我一个更简单的方法吗?
    • 您可以在主运行循环中增加 pacman 的位置,但我认为您的教授不会对这个解决方案感到满意
    【解决方案5】:

    很简单
    为每个方向制作 4 个功能 并在函数内部,放入由kbhit激活的其他3个方向函数。

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


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

    【讨论】:

    • 其他答案至少试图解决这个问题并提供具体的解决方案。另一方面,您只是从您自己的(封闭的)问题中粘贴了相同格式错误的代码,没有任何解释或指导。请查看有关 SO 的其他问题和答案,以了解该站点的工作原理。不要把这当成个人,我知道你可以做得更好。干杯。
    • 我不知道为什么 every1 一直说它的格式很糟糕,我怎样才能让它变得更好???
    • 最明显的格式问题是缩进和括号。它们出现在看似随机的位置,并且在您的代码中不一致。编译器不关心格式,但它有助于(或损害)人类读者快速理解结构和控制流的能力。为什么你的一些函数出现在main()之前,而其他密切相关的函数出现在之后?它看起来像一个没有计划或组织的随机混乱。您的单字符变量名称无法说明其用途,并且声明的变量从未使用过。
    猜你喜欢
    • 2022-01-06
    • 2016-02-06
    • 1970-01-01
    • 2018-04-04
    • 2020-12-11
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多