public FieldPlayer(SoccerTeam homeTeam, int homeRegionIndex, State<FieldPlayer> startState, Vector2D heading, Vector2D velocity, double mass, double maxForce, double maxSpeed, double maxTurnRate, double scale, PlayerBase.PlayerRoles role) : base(homeTeam, homeRegionIndex, heading, velocity, mass, maxForce, maxSpeed, maxTurnRate, scale, role) { _stateMachine = new StateMachine<FieldPlayer>(this); if (startState != null) { _stateMachine.CurrentState = _stateMachine.PreviousState = startState; _stateMachine.GlobalState = GlobalPlayerState.Instance; _stateMachine.CurrentState.Enter(this); } _steeringBehaviors.Seperation = true; //set up the kick regulator _kickRegulator = new Regulator(ParameterManager.Instance.PlayerKickFrequency); }
public SoccerTeam(SoccerGoal homeGoal, SoccerGoal opponentsGoal, SoccerPitch pitch, SoccerTeamColor color) { _homeGoal = homeGoal; _opponentsGoal = opponentsGoal; _pitch = pitch; _color = color; _opposingTeam = null; _distSqToBallOfClosestPlayer = 0.0; _supportingPlayer = null; _controllingPlayer = null; _playerClosestToBall = null; _stateMachine = new StateMachine<SoccerTeam>(this); _stateMachine.CurrentState = DefendingState.Instance; _stateMachine.PreviousState = DefendingState.Instance; _stateMachine.GlobalState = null; //create the players and goalkeeper CreatePlayers(); //set default steering behaviors foreach (PlayerBase player in _players) { player.SteeringBehaviors.Seperation = true; } _supportSpotCalculator = new SupportSpotCalculator(ParameterManager.Instance.NumSupportSpotsX, ParameterManager.Instance.NumSupportSpotsY, this); }
public SteeringBehaviors(PlayerBase player, SoccerBall ball) { _player = player; _ball = ball; _separationMultiple = ParameterManager.Instance.SeparationCoefficient; _viewDistance = ParameterManager.Instance.ViewDistance; _tagged = false; _interposeDist = 0.0; _behaviorFlags = (int)BehaviorFlags.None; _dribbleFeelers = new List<Vector2D>(5); for (int i = 0; i < _dribbleFeelers.Count; i++) { _dribbleFeelers[i] = new Vector2D(); } }
public bool SortByReversedDistanceToOpponentsGoal(PlayerBase p1, PlayerBase p2) { return (p1.DistanceToOpposingGoal > p2.DistanceToOpposingGoal); }
/// <summary> /// Tests a pass from position 'from' to position 'target' against each member /// of the opposing team. Returns true if the pass can be made without /// getting intercepted /// /// </summary> /// <param name="from"></param> /// <param name="target"></param> /// <param name="receiver"></param> /// <param name="PassingForce"></param> /// <returns></returns> public bool IsPassSafeFromAllOpponents(Vector2D from, Vector2D target, PlayerBase receiver, double PassingForce) { foreach (PlayerBase opponent in OpposingTeam.Players) { if (!IsPassSafeFromOpponent(from, target, receiver, opponent, PassingForce)) { return false; } } return true; }
/// <summary> /// Three potential passes are calculated. One directly toward the receiver's /// current position and two that are the tangents from the ball position /// to the circle of radius 'range' from the receiver. /// These passes are then tested to see if they can be intercepted by an /// opponent and to make sure they terminate within the playing area. If /// all the passes are invalidated the function returns false. Otherwise /// the function returns the pass that takes the ball closest to the /// opponent's goal area. /// /// </summary> /// <param name="passer"></param> /// <param name="receiver"></param> /// <param name="PassTarget"></param> /// <param name="power"></param> /// <returns></returns> public bool GetBestPassToReceiver(PlayerBase passer, PlayerBase receiver, ref Vector2D PassTarget, double power) { //first, calculate how much time it will take for the ball to reach //this receiver, if the receiver was to remain motionless double time = Pitch.Ball.CalucateTimeToCoverDistance(Pitch.Ball.Position, receiver.Position, power); //return false if ball cannot reach the receiver after having been //kicked with the given power if (time < 0) return false; //the maximum distance the receiver can cover in this time double InterceptRange = time * receiver.MaxSpeed; //Scale the intercept range const double ScalingFactor = 0.3; InterceptRange *= ScalingFactor; //now calculate the pass targets which are positioned at the intercepts //of the tangents from the ball to the receiver's range circle. Vector2D ip1 = new Vector2D(), ip2 = new Vector2D(); Geometry.GetTangentPoints(receiver.Position, InterceptRange, Pitch.Ball.Position, ip1, ip2); const int NumPassesToTry = 3; Vector2D[] Passes = new Vector2D[NumPassesToTry] { ip1, receiver.Position, ip2 }; // this pass is the best found so far if it is: // // 1. Further upfield than the closest valid pass for this receiver // found so far // 2. Within the playing area // 3. Cannot be intercepted by any opponents double ClosestSoFar = double.MaxValue; bool bResult = false; for (int pass = 0; pass < NumPassesToTry; ++pass) { double dist = Math.Abs(Passes[pass].X - OpponentsGoal.GoalLineCenter.X); if ((dist < ClosestSoFar) && Pitch.PlayingArea.IsPositionInside(Passes[pass]) && IsPassSafeFromAllOpponents(Pitch.Ball.Position, Passes[pass], receiver, power)) { ClosestSoFar = dist; PassTarget = Passes[pass]; bResult = true; } } return bResult; }
/// <summary> /// test if a pass from 'from' to 'to' can be intercepted by an opposing player /// /// </summary> /// <param name="from"></param> /// <param name="target"></param> /// <param name="receiver"></param> /// <param name="opp"></param> /// <param name="PassingForce"></param> /// <returns></returns> public bool IsPassSafeFromOpponent(Vector2D from, Vector2D target, PlayerBase receiver, PlayerBase opp, double PassingForce) { //move the opponent into local space. Vector2D ToTarget = target - from; Vector2D ToTargetNormalized = Vector2D.Vec2DNormalize(ToTarget); Vector2D LocalPosOpp = Transformations.PointToLocalSpace(opp.Position, ToTargetNormalized, ToTargetNormalized.Perp, from); //if opponent is behind the kicker then pass is considered okay(this is //based on the assumption that the ball is going to be kicked with a //velocity greater than the opponent's max velocity) if (LocalPosOpp.X < 0) { return true; } //if the opponent is further away than the target we need to consider if //the opponent can reach the position before the receiver. if (Vector2D.Vec2DDistanceSq(from, target) < Vector2D.Vec2DDistanceSq(opp.Position, from)) { if (receiver != null) { if (Vector2D.Vec2DDistanceSq(target, opp.Position) > Vector2D.Vec2DDistanceSq(target, receiver.Position)) { return true; } else { return false; } } else { return true; } } //calculate how long it takes the ball to cover the distance to the //position orthogonal to the opponents position double TimeForBall = Pitch.Ball.CalucateTimeToCoverDistance(new Vector2D(0, 0), new Vector2D(LocalPosOpp.X, 0), PassingForce); //now calculate how far the opponent can run in this time double reach = opp.MaxSpeed * TimeForBall + Pitch.Ball.BoundingRadius + opp.BoundingRadius; //if the distance to the opponent's y position is less than his running //range plus the radius of the ball and the opponents radius then the //ball can be intercepted if (Math.Abs(LocalPosOpp.Y) < reach) { return false; } return true; }
/// <summary> /// The best pass is considered to be the pass that cannot be intercepted /// by an opponent and that is as far forward of the receiver as possible /// /// </summary> /// <param name="passer"></param> /// <param name="receiver"></param> /// <param name="PassTarget"></param> /// <param name="power"></param> /// <param name="MinPassingDistance"></param> /// <returns></returns> public bool FindPass(PlayerBase passer, out PlayerBase receiver, out Vector2D PassTarget, double power, double MinPassingDistance) { receiver = null; PassTarget = null; double ClosestToGoalSoFar = double.MaxValue; Vector2D Target = new Vector2D(); //iterate through all this player's team members and calculate which //one is in a position to be passed the ball foreach (PlayerBase currentPlayer in _players) { //make sure the potential receiver being examined is not this player //and that it is further away than the minimum pass distance if ((currentPlayer != passer) && (Vector2D.Vec2DDistanceSq(passer.Position, currentPlayer.Position) > MinPassingDistance * MinPassingDistance)) { if (GetBestPassToReceiver(passer, currentPlayer, ref Target, power)) { //if the pass target is the closest to the opponent's goal line found // so far, keep a record of it double Dist2Goal = Math.Abs(Target.X - OpponentsGoal.GoalLineCenter.X); if (Dist2Goal < ClosestToGoalSoFar) { ClosestToGoalSoFar = Dist2Goal; //keep a record of this player receiver = currentPlayer; //and the target PassTarget = Target; } } } }//next team member if (receiver != null) return true; else return false; }
/// <summary> /// sets _playerClosestToBall to the player closest to the ball /// </summary> public void CalculateClosestPlayerToBall() { double ClosestSoFar = double.MaxValue; for (int playerIndex = 0; playerIndex < _players.Count; playerIndex++) { //calculate the dist. Use the squared value to avoid sqrt double dist = Vector2D.Vec2DDistanceSq(_players[playerIndex].Position, Pitch.Ball.Position); //keep a record of this value for each player _players[playerIndex].DistanceToBallSquared = dist; if (dist < ClosestSoFar) { ClosestSoFar = dist; _playerClosestToBall = _players[playerIndex]; } } _distSqToBallOfClosestPlayer = ClosestSoFar; }
/// <summary> /// Calculates the closest opponent to this teams goal /// </summary> public void CalculateClosestOpponentToGoal() { double ClosestSoFar = double.MaxValue; for (int memberIndex = 0; memberIndex < _opposingTeam.Players.Count; memberIndex++) { //calculate the dist. to home goal, remember the opponents home goal // is our target if (_opposingTeam.Players[memberIndex].PlayerRole != PlayerBase.PlayerRoles.GoalKeeper) { double dist = _opposingTeam.Players[memberIndex].DistanceToHomeGoal; if (dist < ClosestSoFar) { ClosestSoFar = dist; _opponentClosestToGoal = _opposingTeam.Players[memberIndex]; } } } }
private void LostControl() { _controllingPlayer = null; }
public bool SortByReversedDistanceToOpponentsGoal(PlayerBase p1, PlayerBase p2) { return(p1.DistanceToOpposingGoal > p2.DistanceToOpposingGoal); }