0
\$\begingroup\$

I'm making a 2D game with two spaceships flying around shooting each other. One spaceship is controlled by the user, the by an AI. I want to use a simple Finite State Machine (FSM) for the AI.

I'm trying to make the AI ship follow the player's ship and stop at a given radius from it.

I've got a GetInsidePlayersRadius state, and a StopMoving state. But so far I got a weird bug involving the AI ship moving a few pixels, then stopping for a moment, than moving again, creating very fragmented movement.

The AI can move up, down, left, right, up-left, up-right, down-left, or down-right, just like the player.

What could create this fragmented movement behavior, generally when an AI agent is constantly trying to get inside a certain radius from an object, and stop when it's inside it?

How would you implement a following behavior of an AI as part of a Finite State Machine?

\$\endgroup\$
7
  • \$\begingroup\$ A FSM isn't right for everything. In fact, this is probably a poor application of a FSM. Check out red3d.com/cwr/steer \$\endgroup\$
    – user41442
    Feb 6, 2014 at 20:29
  • \$\begingroup\$ @Jason I think that an FSM is the best way to implement the AI for the spaceship, in general. Please tell me if you agree based on this description: This basic AI agent is going to have to do four things: 1- Get inside a certain radius from the player. 2- Stop when inside that radius. 3- Shoot at the player. 4- Dodge bullets. Do you agree that an FSM would be a good way to implement this? If so, than are you suggesting that instead of using a different state for "moving to radius" and for "stopping at radius", I would make a function to do this, and use it inside a state of the FSM? \$\endgroup\$ Feb 6, 2014 at 20:35
  • 1
    \$\begingroup\$ You can almost certainly just look at the current state (by this I mean velocity, distance to player, weapon loadout, etc.) and decide what to do. If (within gun radius) shoot(); if(bulletIsGoingToHit) { applyThrust(awayFromBullet()) } else { if(outside gun radius * 0.95) applyThrust(vectorTowardsPlayer()); }. No classes, just functions. You can predict what to do based on the current relative positions of everything. At most you might have "attacking", "fleeing", and "refueling" states, but not ones for "am i close?" "shooting", etc. (where everything above is under "attacking") \$\endgroup\$
    – user41442
    Feb 6, 2014 at 20:43
  • \$\begingroup\$ @Jason So basically you're suggesting to use kind of an FSM, but with functions instead of classes? If so, than your suggestion is to implement all the getting-into-radius stuff inside a function, and call this function when needed inside the state "attacking"? (aka not include the stages of preparing for an attack as states themselves, but rather as functions used in more general states). Is this correct? \$\endgroup\$ Feb 6, 2014 at 20:48
  • \$\begingroup\$ Jason is correct; there is no need to use FSM for every part of the AI, or even the same FSM. You could have a state run a complex function (as Jason stated), or a decision tree, or a behavior tree, or a neural net... you could even embed your FSM in some other FSM, and so on. \$\endgroup\$ Feb 7, 2014 at 0:45

1 Answer 1

1
\$\begingroup\$

In my opinion it is perfectly fine to model the behavior with a FSM. Oftentimes we create inferior models with cluttered if-statements like suggested in the comments. But the FSM is not the problem.

To me it seems like you are experiencing jittering movement because your AI ship is always just at the border between "too far" and "close enough". Think about widening this border by using too different radii. One for getting a bit closer than absolutely necessary (r1=50m) and one for "oh I'm no longer close enough" (r2=80m). Where r1 < r2 and r2 = your original radius.

Go to state StopMoving once you are within r1 and only go back to GetInsidePlayersRadius when you are within r2 no longer. In the meantime fire at the player and dodge bullets.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged .