贪吃蛇游戏:快速响应 vs. 碰撞错误

Snake game: fast response vs. collision bug

我有一个用 SFML C++ 编写的贪吃蛇游戏,我在两个选项之间左右为难。如果像这样设置控件:

    if(event.type == sf::Event::KeyPressed && (event.key.code == sf::Keyboard::Up
            || event.key.code == sf::Keyboard::W) && move != Down)
        move = Up;

    else if(event.type == sf::Event::KeyPressed && (event.key.code == sf::Keyboard::Down
            || event.key.code == sf::Keyboard::S) && move != Up)
        move = Down;

    else if(event.type == sf::Event::KeyPressed && (event.key.code == sf::Keyboard::Left
            || event.key.code == sf::Keyboard::A)&& move != Right)
        move = Left;

    else if(event.type == sf::Event::KeyPressed && (event.key.code == sf::Keyboard::Right
            || event.key.code == sf::Keyboard::D) && move != Left)
        move = Right;

在这里,控件非常灵敏。问题是,例如,如果蛇向右移动,而您要极快地连续按向上键然后向左键,则蛇还不会向上移动,但是向上控制将被缓冲,因此蛇将被允许向左移动进入自身,从而死亡。

如果相反,我将这些移动条件包装在一个 if 语句中,该语句只允许每帧更新一次,错误已解决,但控件的流畅性和响应性要差得多。

所以我的问题是,如何保持让机芯快速更新的响应性,同时避免移动到自身的错误?

我没有游戏开发经验,我什至不确定我是否理解你的问题。

但是,我想知道您的代码的以下结构是否有助于控制更新过程:

inline void UpdateMoveUp(Move& move)      { if(move != Down)  { move = Up;    }}
inline void UpdateMoveDown(Move& move)    { if(move != Up)    { move = Down;  }}
inline void UpdateMoveLeft(Move& move)    { if(move != Right) { move = Left;  }}
inline void UpdateMoveRight(Move& move)   { if(move != Left)  { move = Right; }}
inline void UpdateMoveInvalid(Move& move) { move = Invalid; }

inline void HandleUpdate(const Code& code, Move& move) {

  switch(code) {

    case sf::Keyboard::Up:
      return UpdateMoveUp(move);
    case sf::Keyboard::W:
      return UpdateMoveUp(move);

    case sf::Keyboard::Down:
      return UpdateMoveDown(move);
    case sf::Keyboard::S:
      return UpdateMoveDown(move);

    case sf::Keyboard::Left:
      return UpdateMoveLeft(move);
    case sf::Keyboard::A:
      return UpdateMoveLeft(move);

    case sf::Keyboard::Right:
      return UpdateMoveRight(move);
    case sf::Keyboard::D:
      return UpdateMoveRight(move);

    default:
      return UpdateMoveInvalid(move);
  }
}

void HandleInput(const Event& event, Move& move) {
  // I assume that `move` comes from somewhere else
  if(event.type == sf::Event::KeyPressed) {
    return HandleUpdate(event.key.code, move);
  }
}

我的看法是,您将更新功能隔离到一个地方,您可以在那里向更新添加更多条件,而无需再次测试整个条件。

换句话说,您可以为每个 UpdateMoveXXXX 函数添加更多条件,例如 unbuffer 和 updatesave timestamp 和 move(然后仅当最后一个时间戳减去当前时间戳比某个数字 more/less 时才移动)。

那是你制作的贪吃蛇;问题不在于您的输入(但那些 "if's" 应该是一个 switch 语句),而是在与输入反应的对象内,例如。 "Snake_Object"。当按下一个方向时,正常游戏会强制进行一定数量的位置移动。如果你看比赛,如果你向上按,那么蛇会立即被迫在它之前的位置上方一个碰撞箱。这确保您不会立即发生不需要的碰撞,并且仍然保持正常的 fps 流。

所以当 move 变量被发送到 Snake 时,它​​应该首先将整个碰撞盒朝那个方向移动,然后以正常速度移动。