Intereting Posts

# 用C＃中的墙避免障碍

``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); }` `

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

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

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

` `double playerDistance = /* Calculate distance between player and wall */ if (playerDistance < ExpandedRadius)` `