【问题标题】:movementspeed not updating in a state machine运动速度不在状态机中更新
【发布时间】:2018-12-31 01:44:35
【问题描述】:

这一切都在 STEP 事件中。

我目前正在尝试为一些敌方 AI 创建我的第一个状态机。作为 gml 和 gamemaker studio 2 的新手,我的代码非常基础,因为我不知道如何实现内置函数。

在我的状态之一,即rush状态,敌人应该追赶玩家。我通过创造一些条件来做到这一点,如果玩家在敌人的左边,敌人就会向左跑。如果玩家向右,敌人就会向右跑。这在理论上是我编写的代码,但是当我进入游戏时,有时它会起作用,但随后会痉挛并走另一条路。

如果我的角色在圆圈中,它不会向玩家跑去而是跑开。如果我颠倒条件,这不会改变。

case  behaviour.rush:
{
    //radius in square
        if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
         { 
             //direction to face player
             if (behaviourState == behaviour.rush && playerObject.x           >.     warriorx) hsp = -4;
              else if (behaviourState == behaviour.rush &&     
  playerObject.x <= warriorx) hsp = 4;
            x = x + hsp;
         }

    if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
    {
        behaviourState = behaviour.idle;    
    }
}

我的完整代码:

image_speed = 1;
vsp = vsp+grv;
Print(behaviourState);
if (hsp > 0) image_xscale = 3; else if (hsp < 0) image_xscale = -3; 

//animation
if (behaviourState == behaviour.idle) sprite_index =     tikiAxeWarriorIdle;
if (hsp == 2 || hsp == -2)sprite_index = tikiAxeWarriorWalk;

if (hsp == 4 || hsp == -4) sprite_index = tikiAxeWarriorRush;

if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{ 
   Print("in circle");
}
Print(hsp);

switch(behaviourState)
{
    case behaviour.idle:
    {
        //stand still
         if (alarm[1] <= 0) alarm[1] = room_speed * 4;

         if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
         { 
             behaviourState = behaviour.rush;
         }
    }

    case behaviour.wander:
    {
        if (alarm[0] <= 0) alarm[0] = room_speed * 3;

        //move
        if (!place_meeting(x + hsp,y,wallObject)) 
        {
            x = x + hsp;
        }

        if (place_meeting(x + hsp,y,wallObject))//checking frame before.
        {   
            hsp = -hsp;
        }

        //check for behaviour.rush.
        if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
        { 
            behaviourState = behaviour.rush;
        }
    }

    case  behaviour.rush:
    {
        //radius in square
        if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
        { 
            //direction to face player
            if (behaviourState == behaviour.rush && playerObject.x > warriorx) hsp = -4;
            else if (behaviourState == behaviour.rush && playerObject.x <= warriorx) hsp = 4;
            x = x + hsp;
        }

        if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
        {
            behaviourState = behaviour.idle;    
        }
    }
    case behaviour.attack:
    {
        //attack.   
        //if player is hit, he dies.
    }
}

预期的结果是敌人“冲”向我的玩家位置,当超过时,面向另一个方向。如果我的玩家离开圈子,它应该会回到空闲状态。

【问题讨论】:

    标签: gml game-maker-studio-2


    【解决方案1】:

    hsp = -hsp 听起来对痉挛非常敏感。并且由于它会影响整个hsp,它也会影响place_meeting(x + hsp,y,wallObject) 部分。 我不马上知道解决方案,但我认为你应该看看那个部分。

    我个人也更喜欢将您当前的hsp 拆分为两个变量:方向和速度,其中方向的值是1-1,速度类似于hsp,但返回一个正数价值。然后使用speed * direction 组合它们。
    这样,您可以在不考虑方向的情况下计算速度,反之亦然。这也可能解决您当前遇到的冲突。

    【讨论】:

      【解决方案2】:

      使用switch语句,我相信你需要添加“break;”在每个案例之间。

      YoYo 文档here 有一些关于 switch 语句的好信息。现在,这可能无法使您的代码完全按照您的希望运行,但它会让您在实现目标时减少一个错误。

      链接的相关部分指出:
      "...在第一个具有正确值的 case 语句之后继续执行,直到遇到 break 语句....break 不是必需的,并且如果没有 break 语句,则执行将继续执行下一个 case 语句的代码"

      所以本质上,如果没有 break 语句,代码将从匹配当前值的 case 块开始,然后遍历它下面的所有 case 的代码,直到遇到“break;”。

      这是您的代码在使用“break;”时的样子添加到正确的位置。

      image_speed = 1;
      vsp = vsp+grv;
      Print(behaviourState);
      if (hsp > 0) image_xscale = 3; else if (hsp < 0) image_xscale = -3; 
      
      //animation
      if (behaviourState == behaviour.idle) sprite_index =     tikiAxeWarriorIdle;
      if (hsp == 2 || hsp == -2)sprite_index = tikiAxeWarriorWalk;
      
      if (hsp == 4 || hsp == -4) sprite_index = tikiAxeWarriorRush;
      
      if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
      { 
         Print("in circle");
      }
      Print(hsp);
      
      switch(behaviourState)
      {
          case behaviour.idle:
          {
              //stand still
               if (alarm[1] <= 0) alarm[1] = room_speed * 4;
      
               if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
               { 
                   behaviourState = behaviour.rush;
               }
          }
          break;
          case behaviour.wander:
          {
              if (alarm[0] <= 0) alarm[0] = room_speed * 3;
      
              //move
              if (!place_meeting(x + hsp,y,wallObject)) 
              {
                  x = x + hsp;
              }
      
              if (place_meeting(x + hsp,y,wallObject))//checking frame before.
              {   
                  hsp = -hsp;
              }
      
              //check for behaviour.rush.
              if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
              { 
                  behaviourState = behaviour.rush;
              }
          }
          break;
          case  behaviour.rush:
          {
              //radius in square
              if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
              { 
                  //direction to face player
                  if (behaviourState == behaviour.rush && playerObject.x > warriorx) hsp = -4;
                  else if (behaviourState == behaviour.rush && playerObject.x <= warriorx) hsp = 4;
                  x = x + hsp;
              }
      
              if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
              {
                  behaviourState = behaviour.idle;    
              }
          }
          break;
          case behaviour.attack:
          {
              //attack.   
              //if player is hit, he dies.
          }
          break;
      }
      

      希望这会有所帮助!

      另外,一个快速提示! 我在您的代码中注意到的一件事是您多次重复几个表达式。为了便于阅读,我建议尽可能将它们分配给变量。例如:

      var in_circle = point_in_circle(playerObject.x,playerObject.y,x,y,200);
      
      if in_circle {
      
      }
      if !in_circle {
      
      }
      

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 Read this.
      • 有道理!有机会我会尽快更新答案!
      • 我会等待那一刻?
      猜你喜欢
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 2011-05-15
      • 2019-08-15
      • 2013-05-28
      • 1970-01-01
      相关资源
      最近更新 更多