1
\$\begingroup\$

I'm trying to do some obstacle avoidance. Yet somehow something is not going quite well. I've used the book "Programming Game AI by Example" to create a simular function in c# in combination with XNA.

This is what i'm doing right now:

public Vector2 ObstacleAvoidance(List<Obstacle> obstacles)
        {
            //the detection box length is proportional to the agent's velocity
            Owner.DetectionBox = Owner.MinDetectionBoxLength +
                                         ((Owner.Speed() / Owner.MaxSpeed) * Owner.MinDetectionBoxLength);
            //tag all obstacles within range of the box for processing
            TagObstaclesWithinViewRange(Owner);

            //this will keep track of the closest intersecting obstacle (CIB)
            BaseGameEntity ClosestIntersectingObstacle = null;

            //this will be used to track the distance to the CIB
            double DistToClosestIP = Double.MaxValue;

            //this will record the transformed local coordinates of the CIB
            Vector2 LocalPosOfClosestObstacle = new Vector2();

            foreach (Obstacle curOb in obstacles)
            {
                //if the obstacle has been tagged within range proceed
                if (curOb.Tag)
                {
                    //calculate this obstacle's position in local space
                    Vector2 LocalPos = HelperMethods.PointToLocalSpace(curOb.Position,
                                                           Owner.Heading,
                                                           Owner.Side,
                                                           Owner.Position);

                    //if the local position has a negative x value then it must lay
                    //behind the agent. (in which case it can be ignored)
                    if (LocalPos.X >= 0)
                    {
                        //if the distance from the x axis to the object's position is less
                        //than its radius + half the width of the detection box then there
                        //is a potential intersection.
                        double ExpandedRadius = curOb.BoundingRadius + Owner.BoundingRadius;
                        if (Math.Abs(LocalPos.Y) < ExpandedRadius)
                        {
                            //now to do a line/circle intersection test. The center of the 
                            //circle is represented by (cX, cY). The intersection points are 
                            //given by the formula x = cX +/-sqrt(r^2-cY^2) for y=0. 
                            //We only need to look at the smallest positive value of x because
                            //that will be the closest point of intersection.
                            double cX = LocalPos.X;
                            double cY = LocalPos.Y;

                            //we only need to calculate the sqrt part of the above equation once
                            double SqrtPart = Math.Sqrt(ExpandedRadius * ExpandedRadius - cY * cY);

                            double ip = cX - SqrtPart;

                            if (ip <= 0.0)
                            {
                                ip = cX + SqrtPart;
                            }

                            //test to see if this is the closest so far. If it is keep a
                            //record of the obstacle and its local coordinates
                            if (ip < DistToClosestIP)
                            {
                                DistToClosestIP = ip;

                                ClosestIntersectingObstacle = curOb;

                                LocalPosOfClosestObstacle = LocalPos;
                            }
                        }
                    }
                }
            }

            //if we have found an intersecting obstacle, calculate a steering 
            //force away from it
            Vector2 SteeringForce = Vector2.Zero;

            if (ClosestIntersectingObstacle != null)
            {
                //the closer the agent is to an object, the stronger the 
                //steering force should be
                double multiplier = 1.0 + (Owner.DetectionBox - LocalPosOfClosestObstacle.X) /
                                    Owner.DetectionBox;

                //calculate the lateral force
                SteeringForce.Y = (float) ((ClosestIntersectingObstacle.BoundingRadius -
                                            LocalPosOfClosestObstacle.Y) * multiplier);

                //apply a braking force proportional to the obstacles distance from
                //the vehicle. 
                double BrakingWeight = 0.2;

                SteeringForce.X = (float) ((ClosestIntersectingObstacle.BoundingRadius -
                                            LocalPosOfClosestObstacle.X) *
                                           BrakingWeight);
            }

            //finally, convert the steering vector from local to world space
            return HelperMethods.VectorToWorldSpace(SteeringForce,
                                      Owner.Heading,
                                      Owner.Side);
        }

When i'm seeing the wall i still go through it instead of changing directions. This has something to do with this specific line of code:

double ExpandedRadius = curOb.BoundingRadius + Owner.BoundingRadius;
if (Math.Abs(LocalPos.Y) < ExpandedRadius)

When i'm seeing the wall i should go into this if yet i'm not, and therefore going through the wall.

curOb = the wall and his boudingradius is 12.5. Owner = the player and his bounding radius is also 12.5. The LocalPos.Y value is something like 120 which is correct as the y position of the wall is at that exact location. How can i try to fix this so my player won't crash into walls?

Greets

EDIT

The Promised Picture - It should detect the wall and add it to closestIntersectionObstacle but it doesnt Promised picture

\$\endgroup\$
  • \$\begingroup\$ So if I'm reading this right, LocalPos is the wall's position relative to the player. But then you say the Y value is 120. If the wall is 120 units away from the player and the bound is only 25, why are you expecting it to detect a possible collision? \$\endgroup\$ – Tesserex Jun 26 '14 at 14:52
  • \$\begingroup\$ @Tesserex i will upload a photo for more detail in half an hour it'll describe what i think. In words: localpos.Y is the position in the world.. not relative to the player.. \$\endgroup\$ – Baklap4 Jun 26 '14 at 14:55
1
\$\begingroup\$

As per your comment my reading was wrong. I thought LocalPos was relative to the player, because I assumed that's what HelperMethods.PointToLocalSpace was supposed to be doing. But if LocalPos is still world coords, then your description at the end of the question gives it away.

Your if statement:

if (Math.Abs(LocalPos.Y) < ExpandedRadius)

can be translated into English like so:

if the wall's vertical position on the screen is less than the bounding distance...

Comparing an absolute position to a relative distance shouldn't make much sense intuitively.

It should be asking if the distance between the player and the wall is less than ExpandingRadius.

double playerDistance = /* Calculate distance between player and wall */
if (playerDistance < ExpandedRadius)
\$\endgroup\$
  • \$\begingroup\$ I've got it sort of working, yet now it doesn't work with the detectionbox but instead the playersDistance so i should just change that, and i'm done thanks man! \$\endgroup\$ – Baklap4 Jun 26 '14 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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