Snake游戏:快速响应与碰撞错误

时间:2015-08-04 00:39:39

标签: c++ sfml keyboard-events

我在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语句中,该语句只允许每帧更新一次错误,但控件的平滑性和响应性要差得多。

所以我的问题是,如何保持运动快速更新的响应能力,同时避免进入自身的错误?

2 个答案:

答案 0 :(得分:1)

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

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

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和update 保存时间戳并移动(然后仅在最后一个时间戳减去当前时间戳多于/少于某个数字。)

答案 1 :(得分:1)

做你的蛇;问题不在于你的输入(但是那些"如果"应该是一个switch语句),而是在对象中对输入作出反应,例如。 " Snake_Object"。正常游戏在按下方向时强制设定数量的位置移动。如果你观看比赛,如果你向上按,那么蛇就会被迫立即从上面的一个碰撞盒上方。这可以确保您无法进行不必要的即时碰撞,并且仍能保持常规的fps流量。

因此,当移动变量发送到Snake时,它应该在第一个实例中沿该方向移动整个碰撞盒,然后以正常速度移动。