XNA RTS A* pathfinding issues
- by Slayter
I'm starting to develop an RTS game using the XNA framework in C# and am still in the very early prototyping stage. I'm working on the basics. I've got unit selection down and am currently working on moving multiple units. I've implemented an A* pathfinding algorithm which works fine for moving a single unit. However when moving multiple units they stack on top of each other. I tried fixing this with a variation of the boids flocking algorithm but this has caused units to sometimes freeze and get stuck trying to move but going no where.
Ill post the related methods for moving the units below but ill only post a link to the pathfinding class because its really long and i don't want to clutter up the page.
These parts of the code are in the update method for the main controlling class:
if (selectedUnits.Count > 0)
{
int indexOfLeader = 0;
for (int i = 0; i < selectedUnits.Count; i++)
{
if (i == 0)
{
indexOfLeader = 0;
}
else
{
if (Vector2.Distance(selectedUnits[i].position, destination) < Vector2.Distance(selectedUnits[indexOfLeader].position, destination))
indexOfLeader = i;
}
selectedUnits[i].leader = false;
}
selectedUnits[indexOfLeader].leader = true;
foreach (Unit unit in selectedUnits)
unit.FindPath(destination);
}
foreach (Unit unit in units)
{
unit.Update(gameTime, selectedUnits);
}
These three methods control movement in the Unit class:
public void FindPath(Vector2 destination)
{
if (path != null)
path.Clear();
Point startPoint = new Point((int)position.X / 32, (int)position.Y / 32);
Point endPoint = new Point((int)destination.X / 32, (int)destination.Y / 32);
path = pathfinder.FindPath(startPoint, endPoint);
pointCounter = 0;
if (path != null)
nextPoint = path[pointCounter];
dX = 0.0f;
dY = 0.0f;
stop = false;
}
private void Move(List<Unit> units)
{
if (nextPoint == position && !stop)
{
pointCounter++;
if (pointCounter <= path.Count - 1)
{
nextPoint = path[pointCounter];
if (nextPoint == position)
stop = true;
}
else if (pointCounter >= path.Count)
{
path.Clear();
pointCounter = 0;
stop = true;
}
}
else
{
if (!stop)
{
map.occupiedPoints.Remove(this);
Flock(units);
// Move in X ********* TOOK OUT SPEED **********
if ((int)nextPoint.X > (int)position.X)
{
position.X += dX;
}
else if ((int)nextPoint.X < (int)position.X)
{
position.X -= dX;
}
// Move in Y
if ((int)nextPoint.Y > (int)position.Y)
{
position.Y += dY;
}
else if ((int)nextPoint.Y < (int)position.Y)
{
position.Y -= dY;
}
if (position == nextPoint && pointCounter >= path.Count - 1)
stop = true;
map.occupiedPoints.Add(this, position);
}
if (stop)
{
path.Clear();
pointCounter = 0;
}
}
}
private void Flock(List<Unit> units)
{
float distanceToNextPoint = Vector2.Distance(position, nextPoint);
foreach (Unit unit in units)
{
float distance = Vector2.Distance(position, unit.position);
if (unit != this)
{
if (distance < space && !leader && (nextPoint != position))
{
// create space
dX += (position.X - unit.position.X) * 0.1f;
dY += (position.Y - unit.position.Y) * 0.1f;
if (dX > .05f)
nextPoint.X = nextPoint.X - dX;
else if (dX < -.05f)
nextPoint.X = nextPoint.X + dX;
if (dY > .05f)
nextPoint.Y = nextPoint.Y - dY;
else if (dY < -.05f)
nextPoint.Y = nextPoint.Y + dY;
if ((dX < .05f && dX > -.05f) && (dY < .05f && dY > -.05f))
stop = true;
path[pointCounter] = nextPoint;
Console.WriteLine("Make Space: " + dX + ", " + dY);
}
else if (nextPoint != position && !stop)
{
dX = speed;
dY = speed;
Console.WriteLine(dX + ", " + dY);
}
}
}
}
And here's the link to the pathfinder: https://docs.google.com/open?id=0B_Cqt6txUDkddU40QXBMeTR1djA
I hope this post wasn't too long. Also please excuse the messiness of the code. As I said before this is early prototyping. Any help would be appreciated. Thanks!