protected override Vector2 OnUpdateSteeringForce(float elapsedTime, Steerable movingEntity) { if (MovesPerMinute < 0f) { MovesPerMinute = 0f; } // Check if we are outside our moving range if (Vector2.Subtract(movingEntity.Position, location).LengthSquared() > PatrolRange * PatrolRange * 1.2F) { timer = (float)(Random.NextDouble() * 60 / (MovesPerMinute + 0.001f)); location = movingEntity.Position; } // Select a random location when the timer expires timer -= (float)elapsedTime; if (timer < 0) { Vector2 target = new Vector2(); float a = (float)(Random.NextDouble() * Math.PI * 2); float r = (float)(Random.NextDouble()); target.X = (float)(Math.Cos(a) * PatrolRange * r); target.Y = (float)(Math.Sin(a) * PatrolRange * r); movingEntity.Target = target + location; timer = (float)(Random.NextDouble() * 60 / (MovesPerMinute + 0.001f)); } return(SteeringHelper.Arrive(elapsedTime, movingEntity)); }
protected override Vector2 OnUpdateSteeringForce(float elapsedTime, Steerable movingEntity) { //if the evader is ahead and facing the agent then we can just seek //for the evader's current position. Vector2 toEvader = Evader.Position - movingEntity.Position; float relativeHeading = Vector2.Dot(movingEntity.Forward, Evader.Forward); if ((Vector2.Dot(toEvader, movingEntity.Forward) > 0) && (relativeHeading < -0.95f)) //acos(0.95)=18 degs { movingEntity.Target = Evader.Position + Offset; return(SteeringHelper.Seek(elapsedTime, movingEntity)); } //Not considered ahead so we predict where the evader will be. //the lookahead time is propotional to the distance between the evader //and the pursuer; and is inversely proportional to the sum of the //agent's velocities float lookAheadTime = toEvader.Length() / (movingEntity.MaxSpeed + Evader.Speed); //now seek to the predicted future position of the evader movingEntity.Target = Evader.Position + Evader.Velocity * lookAheadTime + Offset; return(SteeringHelper.Seek(elapsedTime, movingEntity)); }
/// <summary> /// Calculates the steering force to arrive at the target. /// </summary> public static Vector2 Arrive(float elapsedTime, Steerable movingEntity) { if (!movingEntity.Target.HasValue) { return(Vector2.Zero); } Vector2 toTarget = movingEntity.Target.Value - movingEntity.Position; // Stop when the moving entity has passed target. if (toTarget.Length() <= movingEntity.BoundingRadius + movingEntity.Skin + movingEntity.DecelerationRange) { if (movingEntity.Velocity != Vector2.Zero && Vector2.Dot(toTarget, movingEntity.Velocity) <= 0) { movingEntity.Target = null; return(Vector2.Zero); } } // Stop when the moving entity is close enough. float distance = toTarget.Length(); if (distance <= movingEntity.DecelerationRange) { movingEntity.Target = null; return(Vector2.Zero); } return(SteeringHelper.Seek(elapsedTime, movingEntity)); }
protected override Vector2 OnUpdateSteeringForce(float elapsedTime, Steerable movingEntity) { int count = 0; Vector2 center = Vector2.Zero; var boundingSphere = new BoundingSphere(new Vector3(movingEntity.Position, 0), Range); Neighbors.FindAll(ref boundingSphere, Partners); foreach (var partner in Partners) { if (partner != null && partner != movingEntity) { center += partner.Position; if (++count >= SteeringHelper.MaxAffectingEntities) { break; } } } Partners.Clear(); if (count > 0) { center /= count; movingEntity.Target = center; return(SteeringHelper.Seek(elapsedTime, movingEntity)); } return(Vector2.Zero); }
protected override Vector2 OnUpdateSteeringForce(float elapsedTime, Steerable movingEntity) { // Not necessary to include the check for facing direction this time Vector2 toPursuer = Pursuer.Position - movingEntity.Position; //uncomment the following two lines to have Evade only consider pursuers //within a 'threat range' if (toPursuer.LengthSquared() > ThreatRange * ThreatRange) { return(Vector2.Zero); } //the lookahead time is propotional to the distance between the pursuer //and the pursuer; and is inversely proportional to the sum of the //agents' velocities float LookAheadTime = toPursuer.Length() / (movingEntity.MaxSpeed + Pursuer.Speed); //now flee away from predicted future position of the pursuer return(SteeringHelper.Flee(elapsedTime, movingEntity, Pursuer.Position + Pursuer.Velocity * LookAheadTime)); }
protected override Vector2 OnUpdateSteeringForce(float elapsedTime, Steerable movingEntity) { return(SteeringHelper.Arrive(elapsedTime, movingEntity)); }
/// <summary> /// Updates the internal state of the object based on game time. /// </summary> public void Update(float elapsedTime) { if (elapsedTime <= 0) { return; } // The max acceleration can stops the moving entity from top speed. float MaxAcceleration = MaxSpeed / elapsedTime; if (acceleration >= MaxAcceleration) { currentAcceleration = MaxAcceleration; } force = Vector2.Zero; MaxForce = Acceleration; DecelerationRange = SteeringHelper.GetDecelerateRange(this); TargetedForward = SteeringHelper.GetTargetedForward(this); Skin = MaxSpeed * elapsedTime * 2; // Accumulate force of each behavior for (int i = 0; i < Behaviors.Count; ++i) { Vector2 steeringForce = Behaviors.GetWeightByIndex(i) * Behaviors[i].UpdateSteeringForce(elapsedTime, this); if (BlendMode == SteeringBehaviorBlendMode.WeightedSum) { if (!AccumulateForceWeightedSum(ref force, MaxForce, steeringForce)) { break; } } else if (BlendMode == SteeringBehaviorBlendMode.Solo) { if (!AccumulateForceSolo(ref force, MaxForce, steeringForce)) { break; } } } if (Speed >= 0 && force == Vector2.Zero) { // The moving entity has fully stopped. if (Speed == 0) { return; } // Apply friction when there is no force but the entity is still moving. Vector2 previousVelocity = Velocity; Velocity -= forward * MaxForce * elapsedTime; // When the velocity has changed its direction, that indicates the moving // entity has fully stopped. if (Vector2.Dot(previousVelocity, Velocity) <= 0) { Velocity = Vector2.Zero; Speed = 0; return; } Speed = Velocity.Length(); } else { // We don't multiply elapsedTime here because our force // is calculated based on the subtracting desired speed and current speed. Velocity += force * elapsedTime; Speed = Velocity.Length(); if (Speed <= 0) { return; } // Turncate speed if (Speed > MaxSpeed) { Velocity *= (float)(MaxSpeed / Speed); Speed = MaxSpeed; } } Debug.Assert(Speed > 0); forward = Vector2.Normalize(Velocity); // Update position Vector2 newPosition; IsStucked = DetectCollision(Position, Position + Velocity * elapsedTime, elapsedTime, out newPosition); Position = newPosition; }