예제 #1
0
        // per frame simulation update
        public void Update(float currentTime, float elapsedTime)
        {
            // apply steering force to our momentum
            ApplySteeringForce(DetermineCombinedSteering(elapsedTime), elapsedTime);

            // reverse direction when we reach an endpoint
            if (Globals.UseDirectedPathFollowing)
            {
                if (Vector3.Distance(Position, Globals.Endpoint0) < _path.Radius)
                {
                    _pathDirection = true;
                    annotation.CircleXZ(_path.Radius, Globals.Endpoint0, Color.DarkRed.ToVector3().FromXna(), 20);
                }
                if (Vector3.Distance(Position, Globals.Endpoint1) < _path.Radius)
                {
                    _pathDirection = false;
                    annotation.CircleXZ(_path.Radius, Globals.Endpoint1, Color.DarkRed.ToVector3().FromXna(), 20);
                }
            }

            // annotation
            annotation.VelocityAcceleration(this, 5, 0);
            _trail.Record(currentTime, Position);

            // notify proximity database that our position has changed
            _proximityToken.UpdateForNewPosition(Position);
        }
예제 #2
0
        public Vector3 SteerToEvadeAllDefenders()
        {
            Vector3 evade        = Vector3.Zero;
            float   goalDistance = Vector3.Distance(Globals.HomeBaseCenter, Position);

            // sum up weighted evasion
            foreach (CtfEnemy e in Plugin.CtfEnemies)
            {
                Vector3 eOffset   = e.Position - Position;
                float   eDistance = eOffset.Length();

                float eForwardDistance = Vector3.Dot(Forward, eOffset);
                float behindThreshold  = Radius * 2;
                bool  behind           = eForwardDistance < behindThreshold;
                if ((!behind) || (eDistance < 5))
                {
                    if (eDistance < (goalDistance * 1.2))             //xxx
                    {
                        // const float timeEstimate = 0.5f * eDistance / e.speed;//xxx
                        float   timeEstimate = 0.15f * eDistance / e.Speed;          //xxx
                        Vector3 future       = e.PredictFuturePosition(timeEstimate);

                        annotation.CircleXZ(e.Radius, future, Globals.EvadeColor.ToVector3().FromXna(), 20); // xxx

                        Vector3 offset  = future - Position;
                        Vector3 lateral = Vector3Helpers.PerpendicularComponent(offset, Forward);
                        float   d       = lateral.Length();
                        float   weight  = -1000 / (d * d);
                        evade += (lateral / d) * weight;
                    }
                }
            }
            return(evade);
        }
예제 #3
0
        private void UpdateState(float currentTime)
        {
            // if we reach the goal before being tagged, switch to atGoal state
            if (State == SeekerState.Running)
            {
                float baseDistance = Vector3.Distance(Position, Globals.HomeBaseCenter);
                if (baseDistance < (Radius + Plugin.BaseRadius))
                {
                    State = SeekerState.AtGoal;
                }
            }

            // update lastRunningTime (holds off reset time)
            if (State == SeekerState.Running)
            {
                _lastRunningTime = currentTime;
            }
            else
            {
                const float RESET_DELAY = 4;
                float       resetTime   = _lastRunningTime + RESET_DELAY;
                if (currentTime > resetTime)
                {
                    // xxx a royal hack (should do this internal to CTF):
                    Demo.QueueDelayedResetPlugInXXX();
                }
            }
        }
예제 #4
0
        static float TestOneObstacleOverlap(float minClearance, float r, float radius, Vector3 c, Vector3 center)
        {
            float d         = Vector3.Distance(c, center);
            float clearance = d - (r + radius);

            if (minClearance > clearance)
            {
                minClearance = clearance;
            }
            return(minClearance);
        }
예제 #5
0
        // per frame simulation update
        public void Update(float elapsedTime)
        {
            // if I hit the ball, kick it.
            float distToBall = Vector3.Distance(Position, _ball.Position);
            float sumOfRadii = Radius + _ball.Radius;

            if (distToBall < sumOfRadii)
            {
                _ball.Kick((_ball.Position - Position) * 50);
            }

            // otherwise consider avoiding collisions with others
            Vector3 collisionAvoidance = SteerToAvoidNeighbors(1, _allPlayers);

            if (collisionAvoidance != Vector3.Zero)
            {
                ApplySteeringForce(collisionAvoidance, elapsedTime);
            }
            else
            {
                float distHomeToBall = Vector3.Distance(_home, _ball.Position);
                if (distHomeToBall < 12)
                {
                    // go for ball if I'm on the 'right' side of the ball
                    if (_imTeamA ? Position.X > _ball.Position.X : Position.X < _ball.Position.X)
                    {
                        Vector3 seekTarget = SteerForSeek(_ball.Position);
                        ApplySteeringForce(seekTarget, elapsedTime);
                    }
                    else
                    {
                        if (distHomeToBall < 12)
                        {
                            float   z               = _ball.Position.Z - Position.Z > 0 ? -1.0f : 1.0f;
                            Vector3 behindBall      = _ball.Position + (_imTeamA ? new Vector3(2, 0, z) : new Vector3(-2, 0, z));
                            Vector3 behindBallForce = SteerForSeek(behindBall);
                            annotation.Line(Position, behindBall, Color.Green.ToVector3().FromXna());
                            Vector3 evadeTarget = SteerForFlee(_ball.Position);
                            ApplySteeringForce(behindBallForce * 10 + evadeTarget, elapsedTime);
                        }
                    }
                }
                else                    // Go home
                {
                    Vector3 seekTarget = SteerForSeek(_home);
                    Vector3 seekHome   = SteerForSeek(_home);
                    ApplySteeringForce(seekTarget + seekHome, elapsedTime);
                }
            }
        }
예제 #6
0
        // per frame simulation update
        public void Update(float currentTime, float elapsedTime)
        {
            // determine upper bound for pursuit prediction time
            float seekerToGoalDist  = Vector3.Distance(Globals.HomeBaseCenter, Globals.Seeker.Position);
            float adjustedDistance  = seekerToGoalDist - Radius - Plugin.BaseRadius;
            float seekerToGoalTime  = ((adjustedDistance < 0) ? 0 : (adjustedDistance / Globals.Seeker.Speed));
            float maxPredictionTime = seekerToGoalTime * 0.9f;

            // determine steering (pursuit, obstacle avoidance, or braking)
            Vector3 steer = Vector3.Zero;

            if (Globals.Seeker.State == SeekerState.Running)
            {
                Vector3 avoidance = SteerToAvoidObstacles(Globals.AVOIDANCE_PREDICT_TIME_MIN, AllObstacles);

                // saved for annotation
                Avoiding = (avoidance == Vector3.Zero);

                steer = Avoiding ? SteerForPursuit(Globals.Seeker, maxPredictionTime) : avoidance;
            }
            else
            {
                ApplyBrakingForce(Globals.BRAKING_RATE, elapsedTime);
            }
            ApplySteeringForce(steer, elapsedTime);

            // annotation
            annotation.VelocityAcceleration(this);
            Trail.Record(currentTime, Position);

            // detect and record interceptions ("tags") of seeker
            float seekerToMeDist = Vector3.Distance(Position, Globals.Seeker.Position);
            float sumOfRadii     = Radius + Globals.Seeker.Radius;

            if (seekerToMeDist < sumOfRadii)
            {
                if (Globals.Seeker.State == SeekerState.Running)
                {
                    Globals.Seeker.State = SeekerState.Tagged;
                }

                // annotation:
                if (Globals.Seeker.State == SeekerState.Tagged)
                {
                    Color color = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 0.5f), (byte)(255.0f * 0.5f));
                    annotation.DiskXZ(sumOfRadii, (Position + Globals.Seeker.Position) / 2, color.ToVector3().FromXna(), 20);
                }
            }
        }
예제 #7
0
        /**
         * Gets the face area
         *
         * @return face area
         */
        public double getArea()
        {
            //area = (a * c * sen(B))/2
            Point3d  p1 = v1.getPosition();
            Point3d  p2 = v2.getPosition();
            Point3d  p3 = v3.getPosition();
            Vector3d xy = new Vector3d(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
            Vector3d xz = new Vector3d(p3.X - p1.X, p3.Y - p1.Y, p3.Z - p1.Z);

            double a = Vector3d.Distance(p1, p2);
            double c = Vector3d.Distance(p1, p3);
            double B = xy.Angle(xz);

            return((a * c * Math.Sin(B)) / 2d);
        }
예제 #8
0
        //--------------------------------OTHERS----------------------------------------//

        /**
         * Computes the distance from the line point to another point
         *
         * @param otherPoint the point to compute the distance from the line point. The point
         * is supposed to be on the same line.
         * @return points distance. If the point submitted is behind the direction, the
         * distance is negative
         */
        public double computePointToPointDistance(Point3d otherPoint)
        {
            //float distance = otherPoint.distance(point);
            float distance = Vector3d.Distance(otherPoint, point);

            Vector3d vec = Vector3d.Normalize(new Vector3d(otherPoint.X - point.X, otherPoint.Y - point.Y, otherPoint.Z - point.Z));

            if (Vector3d.Dot(vec, direction) < 0)
            {
                return(-distance);
            }
            else
            {
                return(distance);
            }
        }
예제 #9
0
 private void AdjustObstacleAvoidanceLookAhead(bool clearPath)
 {
     if (clearPath)
     {
         _evading = false;
         float goalDistance      = Vector3.Distance(Globals.HomeBaseCenter, Position);
         bool  headingTowardGoal = this.IsAhead(Globals.HomeBaseCenter, 0.98f);
         bool  isNear            = (goalDistance / Speed) < Globals.AVOIDANCE_PREDICT_TIME_MAX;
         bool  useMax            = headingTowardGoal && !isNear;
         Globals.AvoidancePredictTime = (useMax ? Globals.AVOIDANCE_PREDICT_TIME_MAX : Globals.AVOIDANCE_PREDICT_TIME_MIN);
     }
     else
     {
         _evading = true;
         Globals.AvoidancePredictTime = Globals.AVOIDANCE_PREDICT_TIME_MIN;
     }
 }
예제 #10
0
        // one simulation step
        public void Update(float currentTime, float elapsedTime)
        {
            // when pursuer touches quarry ("wanderer"), reset its position
            float d = Vector3.Distance(Position, _wanderer.Position);
            float r = Radius + _wanderer.Radius;

            if (d < r)
            {
                Reset();
            }

            const float MAX_TIME = 20;             // xxx hard-to-justify value

            ApplySteeringForce(SteerForPursuit(_wanderer, MAX_TIME), elapsedTime);

            // for annotation
            Trail.Record(currentTime, Position);
        }
예제 #11
0
 private void SerialNumberAnnotationUtility(ILocalSpaceBasis selected)
 {
     // display a Pedestrian's serial number as a text label near its
     // screen position when it is near the selected vehicle or mouse.
     if (selected != null)            //FIXME: && IsAnnotationEnabled)
     {
         foreach (IVehicle vehicle in _crowd)
         {
             const float NEAR_DISTANCE = 6;
             Vector3     vp            = vehicle.Position;
             //Vector3 np = nearMouse.Position;
             if ((Vector3.Distance(vp, selected.Position) < NEAR_DISTANCE) /* ||
                                                                            * (nearMouse != null && (Vector3.Distance(vp, np) < nearDistance))*/)
             {
                 String  sn         = String.Format("#{0}", vehicle.GetHashCode());
                 Color   textColor  = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 1), (byte)(255.0f * 0.8f));
                 Vector3 textOffset = new Vector3(0, 0.25f, 0);
                 Vector3 textPos    = vehicle.Position + textOffset;
                 Drawing.Draw2dTextAt3dLocation(sn, textPos, textColor);
             }
         }
     }
 }
        public void ScanRun()
        {
            if (_scanQueue.Count == 0)
            {
                return;
            }
            DestructionRequest request = _scanQueue.First();

            int objectsFound = 0;

            foreach (BarricadeRegion region in BarricadeManager.regions)
            {
                foreach (BarricadeData data in region.barricades)
                {
                    if (Vector3.Distance(request.Position, data.point.ToSystemVector()) > request.Radius)
                    {
                        continue;
                    }

                    if (_destroyQueue.ContainsKey(data.GetHashCode()))
                    {
                        continue;
                    }

                    if (request.SteamID != 0)
                    {
                        if (data.owner != request.SteamID)
                        {
                            continue;
                        }
                        if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.barricade", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                        {
                            continue;
                        }
                    }

                    if (request.ItemID != 0)
                    {
                        if (data.barricade.id != request.ItemID)
                        {
                            continue;
                        }
                    }

                    if (request.Filters != null)
                    {
                        if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == data.barricade.id || request.Filters.Contains('*')))
                        {
                            continue;
                        }
                    }

                    if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.barricade", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                    {
                        continue;
                    }

                    objectsFound++;
                    if (request.WreckType == WreckType.Scan)
                    {
                        continue;
                    }
                    _destroyQueue.Add(data.GetHashCode(), data);
                }
            }

            foreach (StructureRegion region in StructureManager.regions)
            {
                foreach (StructureData data in region.structures)
                {
                    if (Vector3.Distance(request.Position, data.point.ToSystemVector()) > request.Radius)
                    {
                        continue;
                    }

                    if (_destroyQueue.ContainsKey(data.GetHashCode()))
                    {
                        continue;
                    }

                    if (request.SteamID != 0)
                    {
                        if (data.owner != request.SteamID)
                        {
                            continue;
                        }
                        if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.structure", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                        {
                            continue;
                        }
                    }

                    if (request.ItemID != 0)
                    {
                        if (data.structure.id != request.ItemID)
                        {
                            continue;
                        }
                    }

                    if (request.Filters != null)
                    {
                        if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == data.structure.id || request.Filters.Contains('*')))
                        {
                            continue;
                        }
                    }

                    if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.structure", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                    {
                        continue;
                    }

                    objectsFound++;
                    if (request.WreckType == WreckType.Scan)
                    {
                        continue;
                    }
                    _destroyQueue.Add(data.GetHashCode(), data);
                }
            }

            foreach (InteractableVehicle vehicle in VehicleManager.vehicles)
            {
                if (Vector3.Distance(request.Position, vehicle.transform.position.ToSystemVector()) > request.Radius)
                {
                    continue;
                }

                if (_destroyQueue.ContainsKey(vehicle.GetHashCode()))
                {
                    continue;
                }

                if (request.SteamID != 0)
                {
                    if (vehicle.lockedOwner.m_SteamID != request.SteamID)
                    {
                        continue;
                    }
                    if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(_wreckPlugin.Container.Resolve <IPlayerManager> ().GetPlayer(request.SteamID.ToString()), "wreckingball.skip.vehicle", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                    {
                        continue;
                    }
                }

                if (request.ItemID != 0)
                {
                    if (vehicle.id != request.ItemID)
                    {
                        continue;
                    }
                }

                if (request.Filters != null)
                {
                    if (!_wreckPlugin.ConfigurationInstance.Elements.Any(c => request.Filters.Contains(c.CategoryId) && c.Id == vehicle.id || request.Filters.Contains('*')))
                    {
                        continue;
                    }
                }

                if (request.WreckType != WreckType.Scan && _permissionProvider.CheckHasAnyPermission(request.User, "wreckingball.skip.vehicle", "wreckingball.skip.*", "wreckingball.*") == PermissionResult.Grant)
                {
                    continue;
                }

                objectsFound++;
                if (request.WreckType == WreckType.Scan)
                {
                    continue;
                }
                _destroyQueue.Add(vehicle.GetHashCode(), vehicle);
            }

            if (request.Filters.Contains('A'))
            {
                foreach (Animal animal in AnimalManager.animals)
                {
                    if (Vector3.Distance(request.Position, animal.transform.position.ToSystemVector()) > request.Radius)
                    {
                        continue;
                    }

                    if (_destroyQueue.ContainsKey(animal.GetHashCode()))
                    {
                        continue;
                    }

                    if (request.ItemID != 0)
                    {
                        if (animal.id != request.ItemID)
                        {
                            continue;
                        }
                    }

                    objectsFound++;
                    if (request.WreckType == WreckType.Scan)
                    {
                        continue;
                    }
                    _destroyQueue.Add(animal.GetHashCode(), animal);
                }
            }
            if (request.Filters.Contains('Z'))
            {
                foreach (ZombieRegion region in ZombieManager.regions)
                {
                    foreach (Zombie zombie in region.zombies)
                    {
                        if (Vector3.Distance(request.Position, zombie.transform.position.ToSystemVector()) > request.Radius)
                        {
                            continue;
                        }

                        if (_destroyQueue.ContainsKey(zombie.GetHashCode()))
                        {
                            continue;
                        }

                        if (request.ItemID != 0)
                        {
                            if (zombie.id != request.ItemID)
                            {
                                continue;
                            }
                        }

                        objectsFound++;
                        if (request.WreckType == WreckType.Scan)
                        {
                            continue;
                        }
                        _destroyQueue.Add(zombie.GetHashCode(), zombie);
                    }
                }
            }

            request.User.SendLocalizedMessage(_wreckPlugin.Translations, "wreckingball_scan", objectsFound);
            _scanQueue.Remove(request);
            if (request.WreckType == WreckType.Scan)
            {
                return;
            }
            request.User.SendLocalizedMessage(_wreckPlugin.Translations, "wreckingball_added_destruction", FormattedTimeUntilDestroyed());
        }
예제 #13
0
        private void Update(EvaluationContext context)
        {
            if (!(SourcePoints.GetValue(context) is StructuredList <Point> sourcePoints))
            {
                return;
            }

            if (sourcePoints.NumElements == 0)
            {
                sourcePoints.SetLength(0);
                ResultList.Value = sourcePoints;
                return;
            }

            var spread     = Spread.GetValue(context);
            var spreadMode = (SpreadModes)SpreadMode.GetValue(context);

            var indexWithinSegment = 0;
            var lineSegmentLength  = 0f;
            var totalLength        = 0f;
            var maxLength          = float.NegativeInfinity;

            var randomizeStart    = RandomizeStart.GetValue(context);
            var randomizeDuration = RandomizeDuration.GetValue(context);

            // Measure...
            segments.Clear();
            for (var pointIndex = 0; pointIndex < sourcePoints.NumElements; pointIndex++)
            {
                if (float.IsNaN(sourcePoints.TypedElements[pointIndex].W))
                {
                    var hasAtLeastTwoPoints = indexWithinSegment > 1;
                    if (hasAtLeastTwoPoints)
                    {
                        if (lineSegmentLength > maxLength)
                        {
                            maxLength = lineSegmentLength;
                        }

                        totalLength += lineSegmentLength;
                        segments.Add(new Segment
                        {
                            PointIndex        = pointIndex - indexWithinSegment,
                            PointCount        = indexWithinSegment,
                            AccumulatedLength = totalLength,
                            SegmentLength     = lineSegmentLength
                        });
                    }

                    lineSegmentLength  = 0;
                    indexWithinSegment = 0;
                }
                else
                {
                    if (indexWithinSegment > 0)
                    {
                        lineSegmentLength += Vector3.Distance(sourcePoints.TypedElements[pointIndex - 1].Position,
                                                              sourcePoints.TypedElements[pointIndex].Position);
                    }

                    indexWithinSegment++;
                }
            }

            if (totalLength < 0.0001f || segments.Count < 2)
            {
                Log.Warning("Stroke animation requires at least two segments with of some length");
                return;
            }

            // Write offsets...
            float dist = maxLength / (segments.Count - 1);

            _random = new Random(42);

            for (var segmentIndex = 0; segmentIndex < segments.Count; segmentIndex++)
            {
                var segmentOffset = ComputeOverlappingProgress(0, segmentIndex, segments.Count, spread);
                var lengthProgressWithingSegment = 0f;
                var segment = segments[segmentIndex];

                // see https://www.figma.com/file/V5k13NMMIsnAnbWH651clI/Untitled?node-id=205%3A96
                var stackedRange = TimeRange.FromStartAndDuration(segment.AccumulatedLength - segment.SegmentLength, segment.SegmentLength) * (1 / totalLength);

                var anchor      = segmentIndex * segment.SegmentLength / (segments.Count - 1);
                var pGrid       = segmentIndex * dist;
                var packedRange = TimeRange.FromStartAndDuration(pGrid - anchor, segment.SegmentLength) * (1 / maxLength);
                var range       = TimeRange.Lerp(packedRange, stackedRange, spread);

                if (Math.Abs(randomizeStart) > 0.0001f)
                {
                    var randomStart = (float)_random.NextDouble() * (1 - range.Duration);
                    range.Start = MathUtils.Lerp(range.Start, randomStart, randomizeStart);
                }

                if (Math.Abs(randomizeDuration) > 0.0001f)
                {
                    var randomDuration = (float)_random.NextDouble() * (1 - range.Start);
                    range.Duration = MathUtils.Lerp(range.Duration, randomDuration, randomizeDuration);
                }

                for (var pointIndexInSegment = 0; pointIndexInSegment < segment.PointCount; pointIndexInSegment++)
                {
                    var pi = segment.PointIndex + pointIndexInSegment;
                    if (pointIndexInSegment > 0)
                    {
                        lengthProgressWithingSegment += Vector3.Distance(sourcePoints.TypedElements[pi - 1].Position,
                                                                         sourcePoints.TypedElements[pi].Position);
                    }

                    var   normalizedSegmentPosition = pointIndexInSegment / (segment.PointCount - 1);
                    float w = 0;
                    switch (spreadMode)
                    {
                    case SpreadModes.IgnoreStrokeLengths:
                        var f = lengthProgressWithingSegment / segment.SegmentLength.Clamp(0.001f, 999999f);
                        w = (f - segmentOffset) / (segments.Count + 1);
                        break;

                    case SpreadModes.UseStrokeLength:
                        w = MathUtils.Lerp(range.Start, range.End, normalizedSegmentPosition);
                        break;

                    case SpreadModes.Weird:
                        w = segmentOffset * 0.2f + pointIndexInSegment / segment.PointCount / 2;
                        break;
                    }

                    sourcePoints.TypedElements[pi].W = w;
                }
            }

            StrokeCount.Value = segments.Count;
            ResultList.Value  = sourcePoints;
            StrokeCount.DirtyFlag.Clear();
            ResultList.DirtyFlag.Clear();
        }
예제 #14
0
        public override void Redraw(float currentTime, float elapsedTime)
        {
            // selected Pedestrian (user can mouse click to select another)
            IVehicle selected = Demo.SelectedVehicle;

            // Pedestrian nearest mouse (to be highlighted)
            IVehicle nearMouse = Demo.VehicleNearestToMouse();

            // update camera
            Demo.UpdateCamera(elapsedTime, selected);

            // draw "ground plane"
            if (Demo.SelectedVehicle != null)
            {
                _gridCenter = selected.Position;
            }
            Demo.GridUtility(_gridCenter);

            // draw and annotate each Pedestrian
            foreach (Pedestrian pedestrian in _crowd)
            {
                pedestrian.Draw();
            }

            // draw the path they follow and obstacles they avoid
            DrawPathAndObstacles();

            // highlight Pedestrian nearest mouse
            Demo.HighlightVehicleUtility(nearMouse);

            // textual annotation (at the vehicle's screen position)
            SerialNumberAnnotationUtility(selected);

            // textual annotation for selected Pedestrian
            if (Demo.SelectedVehicle != null)            //FIXME: && annotation.IsEnabled)
            {
                Color   color        = new Color((byte)(255.0f * 0.8f), (byte)(255.0f * 0.8f), (byte)(255.0f * 1.0f));
                Vector3 textOffset   = new Vector3(0, 0.25f, 0);
                Vector3 textPosition = selected.Position + textOffset;
                Vector3 camPosition  = Demo.Camera.Position;
                float   camDistance  = Vector3.Distance(selected.Position, camPosition);

                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("1: speed: {0:0.00}\n", selected.Speed);
                sb.AppendFormat("2: cam dist: {0:0.0}\n", camDistance);
                Drawing.Draw2dTextAt3dLocation(sb.ToString(), textPosition, color);
            }

            // display status in the upper left corner of the window
            StringBuilder status = new StringBuilder();

            status.AppendFormat("[F1/F2] Crowd size: {0}\n", _population);
            status.Append("[F3] PD type: ");
            switch (_cyclePD)
            {
            case 0: status.Append("LQ bin lattice"); break;

            case 1: status.Append("brute force"); break;
            }
            status.Append("\n[F4] ");
            status.Append(Globals.UseDirectedPathFollowing ? "Directed path following." : "Stay on the path.");
            status.Append("\n[F5] Wander: ");
            status.Append(Globals.WanderSwitch ? "yes" : "no");
            status.Append("\n");
            Vector3 screenLocation = new Vector3(15, 50, 0);

            Drawing.Draw2dTextAt2dLocation(status.ToString(), screenLocation, Color.LightGray);
        }
예제 #15
0
        // is there a clear path to the goal?
        private bool IsPathToGoalClear()
        {
            float sideThreshold   = Radius * 8.0f;
            float behindThreshold = Radius * 2.0f;

            Vector3 goalOffset    = Globals.HomeBaseCenter - Position;
            float   goalDistance  = goalOffset.Length();
            Vector3 goalDirection = goalOffset / goalDistance;

            bool goalIsAside = this.IsAside(Globals.HomeBaseCenter, 0.5f);

            // for annotation: loop over all and save result, instead of early return
            bool xxxReturn = true;

            // loop over enemies
            foreach (CtfEnemy e in Plugin.CtfEnemies)
            {
                float   eDistance        = Vector3.Distance(Position, e.Position);
                float   timeEstimate     = 0.3f * eDistance / e.Speed;       //xxx
                Vector3 eFuture          = e.PredictFuturePosition(timeEstimate);
                Vector3 eOffset          = eFuture - Position;
                float   alongCorridor    = Vector3.Dot(goalDirection, eOffset);
                bool    inCorridor       = ((alongCorridor > -behindThreshold) && (alongCorridor < goalDistance));
                float   eForwardDistance = Vector3.Dot(Forward, eOffset);

                // xxx temp move this up before the conditionals
                annotation.CircleXZ(e.Radius, eFuture, Globals.ClearPathColor.ToVector3().FromXna(), 20);             //xxx

                // consider as potential blocker if within the corridor
                if (inCorridor)
                {
                    Vector3 perp           = eOffset - (goalDirection * alongCorridor);
                    float   acrossCorridor = perp.Length();
                    if (acrossCorridor < sideThreshold)
                    {
                        // not a blocker if behind us and we are perp to corridor
                        float eFront = eForwardDistance + e.Radius;

                        //annotation.annotationLine (position, forward*eFront, gGreen); // xxx
                        //annotation.annotationLine (e.position, forward*eFront, gGreen); // xxx

                        // xxx
                        // std::ostringstream message;
                        // message << "eFront = " << std::setprecision(2)
                        //         << std::setiosflags(std::ios::fixed) << eFront << std::ends;
                        // draw2dTextAt3dLocation (*message.str(), eFuture, gWhite);

                        bool eIsBehind             = eFront < -behindThreshold;
                        bool eIsWayBehind          = eFront < (-2 * behindThreshold);
                        bool safeToTurnTowardsGoal = ((eIsBehind && goalIsAside) || eIsWayBehind);

                        if (!safeToTurnTowardsGoal)
                        {
                            // this enemy blocks the path to the goal, so return false
                            annotation.Line(Position, e.Position, Globals.ClearPathColor.ToVector3().FromXna());
                            // return false;
                            xxxReturn = false;
                        }
                    }
                }
            }

            // no enemies found along path, return true to indicate path is clear
            // clearPathAnnotation (sideThreshold, behindThreshold, goalDirection);
            // return true;
            //if (xxxReturn)
            ClearPathAnnotation(sideThreshold, behindThreshold, goalDirection);
            return(xxxReturn);
        }