【问题标题】:Move ghost toward player in maze if player is nearby?如果玩家在附近,将鬼魂移向迷宫中的玩家?
【发布时间】:2015-03-17 20:45:49
【问题描述】:

我认为这是一个相当容易实现的事情,但我只是希望幽灵一次开始向玩家移动一个空间,如果玩家在幽灵的 5 个空间内。在我的 if 语句中 move_to_x_y 是应该添加更改的地方。如何根据玩家所在的位置执行 if 语句来移动?

这是检查幽灵是否在五个空格内的函数:

bool Game::nearby (Ghost & ghost) const
{
if (abs(m_player->get_x() - ghost.get_x()) < 5)
    return true;
if (abs(m_player->get_y() - ghost.get_y()) < 5)
    return true;
return false;
}

那么这里是鬼的移动功能,他通常只是向随机方向移动,当玩家不在五个空间内时是这种情况:

void Ghost::move (Game & game) {
Floor *     floor;
int         r;
bool        moved = false;

floor = game.get_curr_floor();
do
{
    if (game.nearby(*this))
        r = //WHAT TO ADD HERE???
    else {
    r = rand() % 4;
    switch (r)
    {
    case 0:
        moved = floor->move_to_x_y (game, *this, 1, 0);
        break;
    case 1:
        moved = floor->move_to_x_y (game, *this, 0, -1);
        break;
    case 2:
        moved = floor->move_to_x_y(game, *this, -1, 0);
        break;
    case 3:
        moved = floor->move_to_x_y(game, *this, 0, 1);
        break;
    }
    }
}
while (! moved);
}

因此,根据玩家所在的位置,向上、向下、向左或向右移动。

感谢您的帮助!

【问题讨论】:

  • 还有……你有什么问题?
  • 已编辑。抱歉,不清楚。 “如何根据玩家的位置执行 if 语句来移动?”
  • 另外,为什么会有循环?哦,rand()。知道了。我可能不会那样做。给它一个fallthrough,所以如果它尝试向右移动但失败了,它会尝试向下,然后向左,然后向上。
  • 哦,好的。好吧,它应该能够穿过墙壁,所以我不太担心 rand(),因为幽灵可以在地图上的任何地方移动。
  • 这是一个非常糟糕的距离测试,顺便说一句。您可能应该同时考虑 x 和 y 距离(或者添加它们,或者采用欧几里得距离)。否则,重影可能位于屏幕的另一侧,但如果水平或垂直排列,仍会被视为“附近”。

标签: c++ maze


【解决方案1】:

我可能会这样做:

if (game.nearby(*this))
{
    int x = player_position_x - ghost_position_x;
    int y = player_position_y - ghost_position_y;

    if (abs(x) > abs(y))
    {
        assert(x != 0);
        x = x / abs(x);
        y = 0;
    }
    else
    {
        assert(y != 0);
        x = 0;
        y = y / abs(y);
    }

    floor->move_to_x_y (game, *this, x, y);
    moved = true;
}

【讨论】:

    【解决方案2】:

    您的函数返回玩家是否在附近,但不提供有关玩家所在方向的信息。将返回值从 bool 更改为 int,或指示方向的其他值。例如:

    int Game::nearby (Ghost & ghost) const
    {
    if (ghost.get_x() - m_player->get_x() < 5 && ghost.get_x() - m_player->get_x() > 0)
        return 2;
    if (m_player->get_x() - ghost.get_x() < 5 && m_player->get_x() - ghost.get_x() > 0)
        return 0;
    if (ghost.get_y() - m_player->get_y() < 5 && ghost.get_y() - m_player->get_y() > 0)
        return 3;
    if (m_player->get_y() - ghost.get_y() < 5 && m_player->get_y() - ghost.get_y() > 0)
        return 1;
    return -1;
    }
    

    这将返回已经对应于你希望他在你的 switch 语句中移动的方向的数字。因此,您在 move 函数中所要做的就是将 r 设置为 int "nearby" 返回,如果返回 -1,则像以前一样将其设置为随机方向。

    r = game.nearby(*this);
    if (r == -1)
        r = rand() % 4;
    
    switch (r) .... etc
    

    【讨论】:

    • 啊,好吧,这句话if (r == -1) 是鬼向玩家移动的地方吗?这似乎仍然没有“then”元素,比如 if == -1,向玩家移动,你只是让它做一个随机移动,不是吗?
    • 不,幽灵会使用你的 switch 语句移动到玩家身上。唯一的区别是 'r' 被设置为什么。如果玩家在幽灵的范围内,r 被设置为在你的 switch 语句中做出正确大小写所需的数字。但是如果玩家超出范围,r会被设置为-1,然后会被设置为一个随机数。
    • 哦,好吧,有什么理由说 -> 即使我们传入 ghost 作为参考,它也没有指针类型 'Ghost'?不知道为什么会这样。
    • 你不应该使用幻数。要么返回向量,要么使用枚举作为方向,
    • 如果 (r == -1) r = rand() % 4;只需选择一个随机数,就像您之前所做的那样。您还应该添加检查以确保幽灵不在地图边缘,如果是,请不要让它越过边缘。
    【解决方案3】:

    如果玩家在附近,我会更改 bool Game::nearby 以返回指南针点。


    编辑:对设计误解的评论

    Game::nearby() 并不是为了强制移动幽灵。它旨在为幽灵提供有关玩家位置的信息。如何使用这些信息取决于幽灵策略。所以附近应该以度数、罗盘点或距离矢量的形式返回方向。然后幽灵可能决定接近玩家或坐下来躲避。在吃豆人游戏中,所有 4 个怪物都可以使用此功能,但采用不同的策略。

    【讨论】:

    • 使用这个方法,如果玩家是上两个右一个,但是鬼的正上方有一堵墙,游戏就会卡住。需要更多建议。
    • @moo:OP 说幽灵会穿墙而过。但这不是重点。鬼得到了正确的信息。然后他决定如何处理这些信息。
    【解决方案4】:

    解决方案:

    对于每次更新的每个幽灵:

    1. 尝试获取玩家位置。
    2. 如果无法获得玩家位置(被墙挡住),在本次更新中不要为这个幽灵做任何事情 (return/continue)
    3. 测量到玩家的距离。
    4. 如果距离高于最大“感知范围”,则在本次更新中对这个幽灵不采取任何措施 (return/continue)
    5. 向玩家的方向移动。

    另外,不要在代码中使用“幻数”(case 0:)。使用枚举或常量。

    所以,去掉“附近”并用返回玩家位置的函数替换它。

    【讨论】:

      【解决方案5】:

      两部分。首先,尽量靠近玩家

      void Ghost::move (Game & game) {
          Floor *     floor game.get_curr_floor();
          bool        moved = false;
      
          if (game.nearby(*this)) {
              //try to move closer in x direction
              if (game.get_player()->get_x() > ghost.get_x())
                  moved = floor->move_to_x_y (game, *this, 1, 0);
              else if (ghost.get_x() > game.get_player()->get_x())
                  moved = floor->move_to_x_y (game, *this, -1, 0);
              //if we haven't moved, try to move closer in y direction
              if (!moved && game.get_player()->get_y() > ghost.get_y())
                  moved = floor->move_to_x_y (game, *this, 0, 1);
              else if (!moved && ghost.get_y() > game.get_player()->get_y())
                  moved = floor->move_to_x_y (game, *this, 0, -1);
          }
      

      如果失败或玩家距离太远,请尝试随机移动。如果随机方向失败,请按顺序尝试下一个方向。这意味着我们将最多尝试四个方向,而不会出现无限循环。这在三向交叉点有轻微的偏差,但这可能并不明显。它还有一个副作用,如果幽灵真的不能移动,游戏就不会冻结。

          //if not moved closer, move randomly
          if (!moved) {
              int r = rand() % 4; //pick random direction
              switch(r) {
              case 0: 
                  if(floor->move_to_x_y (game, *this, 1, 0))
                      break; //if it failed, try the next one
              case 1: 
                  if(floor->move_to_x_y (game, *this, -1, 0))
                      break; //if it failed, try the next one
              case 2: 
                  if(floor->move_to_x_y (game, *this, 0, 1))
                      break; //if it failed, try the next one
              case 3: 
                  if(floor->move_to_x_y (game, *this, 0, -1))
                      break; //if it failed, try the next one
              default: 
                  //if it was case 3, need to try all other directions still
                  if(floor->move_to_x_y (game, *this, 1, 0))
                      break; //if it failed, try the next one
                  if(floor->move_to_x_y (game, *this, -1, 0))
                      break; //if it failed, try the next one
                  floor->move_to_x_y (game, *this, 0, 1);
                  //at this point, all directions have been tried. We're done.
              }//switch             
          } //if
      }
      

      评论指出nearby 函数中有一个错误,它认为同一 x 轴上的任何东西都是“接近”的。

      【讨论】:

      • 所以你建议像我一样离开附近()?然后实现你在 move 函数中列出的所有内容?然后传入m_player?
      • 第一:ghost没有玩家成员,设计不错。其次,偏见是一场灾难,因为如果试图离开地图,gost 总是可以预见的。
      • @aishere:哦,我没有注意到他们是不同类别的成员。您可以使用game.getPlayer() 或其他东西。
      • @stefan:一场灾难?它只影响三向路口和拐角处。在“走廊”和四路交叉口,这是完全随机的。拐角是最坏的情况,即使这样,他也有 25% 的时间在“罕见”的方向移动。
      • @moo:如果到达地图的边缘并且落差是“向右跟随边缘”,则有 1/4 的机会离开边缘,并有 3/4 的机会坚持下去。跨度>
      猜你喜欢
      • 1970-01-01
      • 2022-10-17
      • 1970-01-01
      • 2023-02-25
      • 2016-07-13
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多