コード例 #1
0
        /// <summary>
        ///  this can be used to vary the accuracy of a player's kick. Just call it
        ///  prior to kicking the ball using the ball's position and the ball target as
        ///  parameters.
        ///
        /// </summary>
        /// <param name="BallPos"></param>
        /// <param name="BallTarget"></param>
        /// <returns></returns>
        public static Vector2D AddNoiseToKick(Vector2D BallPos, Vector2D BallTarget)
        {
            Random random = new Random();

            double displacement = (Pi - Pi * ParameterManager.Instance.PlayerKickingAccuracy) * Utils.Math.RandomClamped(random);

            Vector2D toTarget = BallTarget - BallPos;

            Transformations.Vec2DRotateAroundOrigin(toTarget, displacement);

            return(toTarget + BallPos);
        }
コード例 #2
0
ファイル: Geometry.cs プロジェクト: xnickygx/SimpleSoccer.Net
        /// <summary>
        ///  given a line segment AB and a circle position and radius, this function
        ///  determines if there is an intersection and stores the position of the
        ///  closest intersection in the reference IntersectionPoint
        ///
        ///  returns false if no intersection point is found
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="pos"></param>
        /// <param name="radius"></param>
        /// <param name="IntersectionPoint"></param>
        /// <returns></returns>
        public static bool GetLineSegmentCircleClosestIntersectionPoint(Vector2D A,
                                                                        Vector2D B,
                                                                        Vector2D pos,
                                                                        double radius,
                                                                        ref Vector2D IntersectionPoint)
        {
            Vector2D toBNorm = Vector2D.Vec2DNormalize(B - A);

            //move the circle into the local space defined by the vector B-A with origin
            //at A
            Vector2D LocalPos = Transformations.PointToLocalSpace(pos, toBNorm, toBNorm.Perp, A);

            bool ipFound = false;

            //if the local position + the radius is negative then the circle lays behind
            //point A so there is no intersection possible. If the local x pos minus the
            //radius is greater than length A-B then the circle cannot intersect the
            //line segment
            if ((LocalPos.X + radius >= 0) &&
                ((LocalPos.X - radius) * (LocalPos.X - radius) <= Vector2D.Vec2DDistanceSq(B, A)))
            {
                //if the distance from the x axis to the object's position is less
                //than its radius then there is a potential intersection.
                if (Math.Sqrt(LocalPos.Y) < radius)
                {
                    //now to do a line/circle intersection test. The center of the
                    //circle is represented by A, B. The intersection points are
                    //given by the formulae x = A +/-sqrt(r^2-B^2), y=0. We only
                    //need to look at the smallest positive value of x.
                    double a = LocalPos.X;
                    double b = LocalPos.Y;

                    double ip = a - Math.Sqrt(radius * radius - b * b);

                    if (ip <= 0)
                    {
                        ip = a + Math.Sqrt(radius * radius - b * b);
                    }

                    ipFound = true;

                    IntersectionPoint = A + toBNorm * ip;
                }
            }

            return(ipFound);
        }
コード例 #3
0
        public override void Execute(FieldPlayer player)
        {
            double dot = player.Team.HomeGoal.FacingDirection.GetDotProduct(player.Heading);

            //if the ball is between the player and the home goal, it needs to swivel
            // the ball around by doing multiple small kicks and turns until the player
            //is facing in the correct direction
            if (dot < 0)
            {
                //the player's heading is going to be rotated by a small amount (Pi/4)
                //and then the ball will be kicked in that direction
                Vector2D direction = player.Heading;

                //calculate the sign (+/-) of the angle between the player heading and the
                //facing direction of the goal so that the player rotates around in the
                //correct direction
                double angle = Utils.Math.Constants.QuarterPi * -1 *
                               player.Team.HomeGoal.FacingDirection.Sign(player.Heading);

                Transformations.Vec2DRotateAroundOrigin(direction, angle);

                //this value works well whjen the player is attempting to control the
                //ball and turn at the same time
                const double KickingForce = 0.8;

                player.Ball.Kick(direction, KickingForce);
            }

            //kick the ball down the field
            else
            {
                player.Ball.Kick(player.Team.HomeGoal.FacingDirection,
                                 ParameterManager.Instance.MaxDribbleForce);
            }

            //the player has kicked the ball so he must now change state to follow it
            player.StateMachine.ChangeState(ChaseBallState.Instance);

            return;
        }
コード例 #4
0
        //--------------------------- Render -------------------------------------
        //
        //------------------------------------------------------------------------
        public override void Render(Graphics g)
        {
            //set appropriate team color
            GDI.CurrentPen = (Team.Color == SoccerTeam.SoccerTeamColor.Blue) ? Pens.Blue : Pens.Red;

            // draw the body, translated to it's local coordinate space
            List <Vector2D> vectors = Transformations.WorldTransform(_vecPlayerVB, Position, Heading, Side, Scale);

            GDI.DrawPolygon(g, vectors);

            // draw his head
            GDI.CurrentBrush = new SolidBrush(Color.FromArgb(133, 90, 0));
            if (ParameterManager.Instance.ShowHighlightIfThreatened && (Team.ControllingPlayer == this) && IsThreatened())
            {
                GDI.CurrentBrush = Brushes.Yellow;
            }
            GDI.DrawCircle(g, Position, 6.0f);

            //render the state
            if (ParameterManager.Instance.ShowStates)
            {
                Brush stateBrush = new SolidBrush(Color.FromArgb(0, 170, 0));
                g.DrawString(_stateMachine.CurrentState.ToString(), GDI.TextFont, stateBrush, new PointF((float)Position.X, (float)Position.Y - GDI.TextFont.Height));
            }

            //show IDs
            if (ParameterManager.Instance.ShowIDs)
            {
                g.DrawString(ObjectId.ToString(), GDI.TextFont, textBrush, new PointF((float)Position.X - 20.0f, (float)Position.Y - GDI.TextFont.Height));
            }

            if (ParameterManager.Instance.ShowViewTargets)
            {
                g.FillEllipse(textBrush, new RectangleF((float)SteeringBehaviors.Target.X, (float)SteeringBehaviors.Target.Y, 3.0f, 3.0f));
                g.DrawString(ObjectId.ToString(), GDI.TextFont, Brushes.Red, new PointF((float)SteeringBehaviors.Target.X, (float)SteeringBehaviors.Target.Y));
            }
        }
コード例 #5
0
        /// <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);
        }
コード例 #6
0
        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());
            }
        }