Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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!

share|improve this question

3 Answers 3

You're over-complicating things. Just do some basic collision detection to make sure units don't overlap.

share|improve this answer
    
I just tried this by setting their position to their previous position but this seems to make them stop following the path –  Slayter Sep 20 '12 at 4:35

All right ,I didn't look very deeply to your code, however If for one unit you got it working, maybe you can try this: In order to make the group travel to the next point select the unit of the group which is closer to it and make it go. Then put every unit following that one, but only let a unit move until the place it will be in the next iteration has no one in a radius equal to the radius of the unit.

I'm sorry if this doesn't make sense in terms of how you're doing things.

share|improve this answer
    
I think i get the jist of what you are saying. I'll definitely mess around with that. –  Slayter Sep 20 '12 at 4:03

I'm not sure this is answering your question, but by one of your comments, I am guessing you need to implement proper collision detection and resolution first. When coliding with another unit, the unit should not return to the space it was occupying before. It should rather move as far along the direction it wants to go as possible.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.