Roy Triesscheijn’s Weblog

My programming world

Collision avoidance, path finding and smooth following, 3D snippet (C#/XNA)

Posted by Roy Triesscheijn on January 13th, 2010

Today I converted my “Swarm Like collision avoidance, path finding and smooth following”- project (what a mouth full) to work with 3D coordinates, if you understood the code, you would know this wasn’t much of a problem. Anyway I did it for you today :) . (original article here).

public static void Attract(GameTime gameTime, Object3D ship, Object3D[] obstacles, Object3D target)
        {
            float pullDistance = Vector3.Distance(target.Position, ship.Position);

            //Only do something if we are not already there
            if (pullDistance > ((ship.Radius + target.Radius) * 1.5f))
            {
                Vector3 pull = (target.Position - ship.Position) * (1 / pullDistance); //the target tries to 'pull us in'
                Vector3 totalPush = Vector3.Zero;

                int contenders = 0;
                for (int i = 0; i < obstacles.Length; ++i)
                {

                    //draw a vector from the obstacle to the ship, that 'pushes the ship away'
                    Vector3 push = ship.Position - obstacles[i].Position;

                    //calculate how much we are pushed away from this obstacle, the closer, the more push
                    float distance = (Vector3.Distance(ship.Position, obstacles[i].Position) - obstacles[i].Radius) - ship.Radius;
                    //only use push force if this object is close enough such that an effect is needed
                    if (distance < ship.Radius * 3)
                    {
                        ++contenders; //count that this object is actively pushing

                        if (distance < 0.0001f) //prevent division by zero errors and extreme pushes
                        {
                            distance = 0.0001f;
                        }
                        float weight = 1 / distance;
                        totalPush += push * weight;
                    }
                }

                pull *= Math.Max(1, 4 * contenders); //4 * contenders gives the pull enough force to pull stuff trough (tweak this setting for your game!)
                pull += totalPush;

                //Normalize the vector so that we get a vector that points in a certain direction, which we van multiply by our desired speed
                pull.Normalize();
                //Set the ships new position;
                ship.Position += (pull * ship.Speed) * (float)gameTime.ElapsedGameTime.TotalSeconds;
            }
        }

6 Responses to “Collision avoidance, path finding and smooth following, 3D snippet (C#/XNA)”

  1. Q Says:

    Hi,
    I want to thank you for the wonderful peice you did on Winform and Xna integration on your old blog. I just have one question – where would I put the drawing code if I wanted to draw something inside the Xna window (which is on the winform) by clicking a button on the winform?

    Any help you can provide would be much appreciated as I am new to Xna and am getting to grips with it.

    Again – thnx for the best example of Xna and Winform code on the net.

    I will check back on this page to see if you have responded. If you dont want to respond – please say so, so that I can stop checking.

    Regards

    Q

  2. Roy Triesscheijn Says:

    Hey Q,

    The most simplest place to put your code is in a timer event. Let the timer fire every 15ms and you get roughly 60 updates per second :) . However take a look at the XNA WinForms sample code at http://creators.xna.com , since I’ve written my old article they have improved their code, to be more easy and better at integrating with winforms than my code.

    Good luck, and if you have any further questions, you can always ask :) .

  3. Q Says:

    Hi Roy. Thanks for responding. I have further questions – since you dont mind me asking Ill go ahead and ask them :)

    So what you are saying is that I should create and start a timer from within my button (which is on the form). This timer should run an override of the Draw() method in order to draw something different?

    Thanks again for the help.

    Regards

    Q

  4. Roy Triesscheijn Says:

    Hey Q,

    Indeed just create a timer that fires every 15ms. Then treat the method that you call in the timer as your Draw and Update methods (loops) or let them call your Game1.Update() and Game1.Draw() methods and work from there as normal with XNA :) .

  5. Q Says:

    Thanks again Roy.

  6. Roy Triesscheijn Says:

    No problem, I’m glad you find my blog useful! When you got something to show, be sure to post me a link!





Or leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>