运动速度不在状态机中更新
Posted
技术标签:
【中文标题】运动速度不在状态机中更新【英文标题】: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.
预期的结果是敌人“冲”向我的玩家位置,当超过时,面向另一个方向。如果我的玩家离开圈子,它应该会回到空闲状态。
【问题讨论】:
【参考方案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. 有道理!有机会我会尽快更新答案! 我会等待那一刻?以上是关于运动速度不在状态机中更新的主要内容,如果未能解决你的问题,请参考以下文章