0

这一切都在 STEP 事件中。

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

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

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

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.
    }
}

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

4

2 回答 2

0

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

这里的 YoYo 文档有一些关于 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 {

}
于 2019-01-25T05:39:31.110 回答
0

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

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

于 2019-01-03T08:08:32.723 回答