/// <summary>
        /// This calculates a force repelling from the other neighbors
        /// </summary>
        /// <returns></returns>
        protected Vector2D calculateSeparationVector()
        {
            //iterate through all the neighbors and calculate the vector from the
            Vector2D steeringForce = new Vector2D();

            List <PlayerBase> allPlayers = AutoList <PlayerBase> .GetAllMembers();

            for (int playerIndex = 0; playerIndex < allPlayers.Count; playerIndex++)
            {
                //make sure this agent isn't included in the calculations and that
                //the agent is close enough
                if (allPlayers[playerIndex] != _player && allPlayers[playerIndex].SteeringBehaviors.Tagged)
                {
                    Vector2D toAgent = _player.Position - allPlayers[playerIndex].Position;

                    //scale the force inversely proportional to the agents distance
                    //from its neighbor.
                    if (Math.Abs(toAgent.Length) > double.Epsilon)
                    {
                        steeringForce += Vector2D.Vec2DNormalize(toAgent) / toAgent.Length;
                    }
                }
            }

            return(steeringForce);
        }
        /// <summary>
        /// Tags any vehicles within a predefined radius
        /// </summary>
        protected void findNeighbours()
        {
            List <PlayerBase> allPlayers = AutoList <PlayerBase> .GetAllMembers();

            for (int playerIndex = 0; playerIndex < allPlayers.Count; playerIndex++)
            {
                //first clear any current tag
                allPlayers[playerIndex].SteeringBehaviors.Tagged = false;

                //work in distance squared to avoid sqrts
                Vector2D to = allPlayers[playerIndex].Position - _player.Position;

                if (to.LengthSquared < (_viewDistance * _viewDistance))
                {
                    allPlayers[playerIndex].SteeringBehaviors.Tagged = true;
                }
            }//next
        }
        public PlayerBase(SoccerTeam homeTeam, int homeRegionIndex, Vector2D heading, Vector2D velocity,
                          double mass, double maxForce, double maxSpeed, double maxTurnRate, double scale, PlayerRoles role)
            : base(homeTeam.Pitch.GetRegion(homeRegionIndex).VectorCenter, scale * 10.0, velocity, maxSpeed, heading, mass, new Vector2D(scale, scale), maxTurnRate, maxForce)
        {
            _playerRole            = role;
            _team                  = homeTeam;
            _distanceToBallSquared = double.MaxValue;
            _homeRegionIndex       = homeRegionIndex;
            _kickoffRegionIndex    = homeRegionIndex;

            Vector2D[] player = new Vector2D[4] {
                new Vector2D(-3, 8), new Vector2D(3, 10), new Vector2D(3, -10), new Vector2D(-3, -8)
            };

            for (int vertexIndex = 0; vertexIndex < 4; vertexIndex++)
            {
                _vecPlayerVB.Add(player[vertexIndex]);

                //set the bounding radius to the length of the
                //greatest extent
                if (Math.Abs(player[vertexIndex].X) > BoundingRadius)
                {
                    BoundingRadius = Math.Abs(player[vertexIndex].X);
                }

                if (Math.Abs(player[vertexIndex].Y) > BoundingRadius)
                {
                    BoundingRadius = Math.Abs(player[vertexIndex].Y);
                }
            }

            //set up the steering behavior class
            _steeringBehaviors = new SteeringBehaviors(this, Ball);

            //a player's start target is its start position (because it's just waiting)
            _steeringBehaviors.Target = _team.Pitch.GetRegion(_homeRegionIndex).VectorCenter;

            AutoList <PlayerBase> .GetAllMembers().Add(this);

            _defaultHomeRegionIndex = _homeRegionIndex;
        }
        public override void Update()
        {
            //run the logic for the current state
            _stateMachine.Update();

            //calculate the combined force from each steering behavior
            Vector2D SteeringForce = _steeringBehaviors.CalculateSteeringForce();

            //Acceleration = Force/Mass
            Vector2D Acceleration = SteeringForce / Mass;

            //update velocity
            Velocity += Acceleration;

            //make sure player does not exceed maximum velocity
            Velocity.Truncate(MaxSpeed);

            //update the position
            Position += Velocity;

            //enforce a non-penetration constraint if desired
            if (ParameterManager.Instance.NonPenetrationConstraint)
            {
                EntityManager.EnforceNonPenetrationContraint <PlayerBase>(this, AutoList <PlayerBase> .GetAllMembers());
            }

            //update the heading if the player has a non zero velocity
            if (!Velocity.IsZero)
            {
                Heading = Vector2D.Vec2DNormalize(Velocity);

                Side = Heading.Perp;
            }

            //look-at vector always points toward the ball
            if (!Team.Pitch.GoalKeeperHasBall)
            {
                _lookAt = Vector2D.Vec2DNormalize(Ball.Position - Position);
            }
        }
        public override void Update()
        {
            //run the logic for the current state
            _stateMachine.Update();

            //calculate the combined steering force
            _steeringBehaviors.CalculateSteeringForce();

            //if no steering force is produced decelerate the player by applying a
            //braking force
            if (_steeringBehaviors.SteeringForce.IsZero)
            {
                double brakingRate = 0.8;

                Velocity = Velocity * brakingRate;
            }

            //the steering force's side component is a force that rotates the
            //player about its axis. We must limit the rotation so that a player
            //can only turn by PlayerMaxTurnRate rads per update.
            double TurningForce = _steeringBehaviors.SideComponent;

            if (TurningForce < -ParameterManager.Instance.PlayerMaxTurnRate)
            {
                TurningForce = -ParameterManager.Instance.PlayerMaxTurnRate;
            }

            if (TurningForce > ParameterManager.Instance.PlayerMaxTurnRate)
            {
                TurningForce = ParameterManager.Instance.PlayerMaxTurnRate;
            }

            //rotate the heading vector
            Transformations.Vec2DRotateAroundOrigin(Heading, TurningForce);

            //make sure the velocity vector points in the same direction as
            //the heading vector
            Velocity = Heading * Velocity.Length;

            //and recreate m_vSide
            Side = Heading.Perp;


            //now to calculate the acceleration due to the force exerted by
            //the forward component of the steering force in the direction
            //of the player's heading
            Vector2D accel = Heading * _steeringBehaviors.ForwardComponent / Mass;

            Velocity += accel;

            //make sure player does not exceed maximum velocity
            Velocity.Truncate(MaxSpeed);

            //update the position
            Position += Velocity;


            //enforce a non-penetration constraint if desired
            if (ParameterManager.Instance.NonPenetrationConstraint)
            {
                EntityManager.EnforceNonPenetrationContraint(this, AutoList <PlayerBase> .GetAllMembers());
            }
        }
 public void Dispose()
 {
     AutoList <PlayerBase> .GetAllMembers().Remove(this);
 }