I have created enemies that chase the player around a game, but there is a problem. The enemies are too perfect and quickly converge on each other when they get close to the player. This is because they just move in the direction of the player each time the game updates.
I would like to introduce some randomness into the enemies, probably with the angle of motion. This is what I have so far (I haven’t optimized it as it’s not done yet, so I’m aware of the high overhead):
Angle = (float)Math.Atan2((HeroPosition - Position).Y, (HeroPosition - Position).X)// Positions are Vector2s
GlobalForce Propellant = new GlobalForce((float)Math.Cos(Angle) / 2, (float)Math.Sin(Angle) / 2);
ApplyForce(Propellant);
If I try to add a random number to the angle there are a couple of problems:
-
They all get updated so quickly after each other that the seed time is the same for all of them
-
The random number is so different on each update that the angle of the enemy jumps around erratically.
So what I want to know is: How do most games get around this problem? How should I make the enemies take different paths (without having access to the list of other enemies)?
EDIT:
This is the code I am using after the suggestions below for future passers by:
Angle = (float)Math.Atan2((HeroPosition - Position).Y, (HeroPosition - Position).X);
GlobalForce Propellant = new GlobalForce((float)Math.Cos(Angle) / 2, (float)Math.Sin(Angle) / 2);
ApplyForce(Propellant);
foreach (Enemy e in OtherEnemies)
{
if (e != this)
{
if ((e.Position - Position).Length() < 64)
{
float angleBetween = MathHelper.TwoPi-(float)Math.Atan2((e.Position-Position).Y, (e.Position-Position).X);
GlobalForce avoidance = new GlobalForce((float)Math.Cos(angleBetween)*2, (float)Math.Sin(angleBetween)*2);
ApplyForce(avoidance);
}
}
}
Most games get around this by having the enemies block each other, so that they don’t move onto the same space.
This can be implemented as either a hard constraint (e.g. only one enemy is allowed in each square, no other enemies can move into an already occupied square) or a soft constraint (some hidden “force” that pushes enemies apart if they get too close to each other).