Пример #1
0
        /// <summary>
        ///     Estimates the future position of target.
        /// </summary>
        /// <param name="player">The player on which the future position estimate is to be performed.</param>
        /// <param name="target">The target position of the player.</param>
        /// <param name="max">The maximum estimated time.</param>
        /// <returns>The future position of the player.</returns>
        public static Vector2 FuturePosition(IPointMass player, IPointMass target, float max)
        {
            Contract.Requires<ArgumentException>(player != null);
            Contract.Requires<ArgumentException>(target != null);
            Contract.Requires<ArgumentException>(max >= 0);

            var estimatedTime = max;
            var invSpeed = 1/player.Velocity.Length();

            if (!float.IsNaN(invSpeed))
            {
                int p, f;

                var offset = target.Position - player.Position;
                var parallelness = Vector2.Dot(Vector2.Normalize(player.Velocity), Vector2.Normalize(target.Velocity));
                if (float.IsNaN(parallelness)) p = 1;
                else p = parallelness < -0.707f ? 2 : (parallelness > 0.707f ? 0 : 1);
                var forwardness = Vector2.Dot(Vector2.Normalize(player.Velocity), Vector2.Normalize(offset));
                if (float.IsNaN(forwardness)) f = 3;
                else f = forwardness < -0.707f ? 6 : (forwardness > 0.707f ? 0 : 3);

                estimatedTime = Math.Min(offset.Length()*invSpeed*TimeFactorTable[p + f], max);
            }

            return target.Position + target.Velocity*estimatedTime;
        }
Пример #2
0
        /// <summary>
        ///     Move toward a specified position.
        /// </summary>
        /// <param name="player">The player that should seek the specified position.</param>
        /// <param name="target">The target position.</param>
        /// <param name="desiredSpeed">The desired speed at which the player should move towards the target.</param>
        /// <returns>The force vector that should be applied to the player.</returns>
        public static Vector2 Seek(IPointMass player, Vector2 target, float desiredSpeed)
        {
            Contract.Requires<ArgumentException>(player != null);
            Contract.Requires<ArgumentException>(desiredSpeed >= 0);

            return Vector2.Normalize(target - player.Position)*desiredSpeed - player.Velocity;
        }
Пример #3
0
 public Spring(IPointMass end1, IPointMass end2, float stiffness, float damping) : base()
 {
     End1         = end1;
     End2         = end2;
     Stiffness    = stiffness;
     Damping      = damping;
     TargetLength = Vector3.Distance(end1.Position, end2.Position) * 0.95f;
 }
Пример #4
0
        /// <summary>
        /// </summary>
        /// <param name="player"></param>
        /// <param name="target"></param>
        /// <param name="otherPlayers"></param>
        /// <param name="passingLaneWidth"></param>
        /// <returns></returns>
        public static bool IsPlayerOpenForPass(
            IPointMass player,
            IPointMass target,
            IEnumerable<IPointMass> otherPlayers,
            float passingLaneWidth)
        {
            var angle = Math.PI/2 -
                        Math.Atan2(target.Position.Y - player.Position.Y, target.Position.X - player.Position.X);
            var v = passingLaneWidth/2*new Vector2((float) Math.Cos(angle), (float) Math.Sin(angle));

            return
                otherPlayers.All(
                    p => !PointInTriangle(p.Position, player.Position, v + target.Position, target.Position - v));
        }
        private static void DrawPointMass(IPointMass pointMass, Pen pen, Brush brush, Graphics g)
        {
            var triangle = new[] { new PointF(1, 0), new PointF(-0.7f, 0.7f), new PointF(-0.7f, -0.7f) };

            using (var m = new Matrix())
            {
                m.Translate(pointMass.Position.X, pointMass.Position.Y);
                m.Rotate((float)(Math.Atan2(pointMass.Velocity.Y, pointMass.Velocity.X) * 180 / Math.PI));
                m.Scale(pointMass.Radius*0.9f, pointMass.Radius*0.9f);
                m.TransformPoints(triangle);
            }

            g.FillPolygon(brush, triangle);
            g.DrawCircle(pen, pointMass.Position, pointMass.Radius);
        }
Пример #6
0
        /// <summary>
        ///     Move to and stop at a specified position.
        /// </summary>
        /// <param name="player">The player that should arrive at the specified position.</param>
        /// <param name="target">The target position.</param>
        /// <param name="maxSpeed">The maximum speed at which the player should move towards the target position.</param>
        /// <param name="slowingRadius">The radius in which the player should begin to slow down.</param>
        /// <returns>The force vector that should be applied to the player.</returns>
        public static Vector2 Arrive(IPointMass player, Vector2 target, float maxSpeed, float slowingRadius)
        {
            Contract.Requires<ArgumentException>(player != null);
            Contract.Requires<ArgumentException>(maxSpeed >= 0);
            Contract.Requires<ArgumentException>(slowingRadius >= 0);

            var targetOffset = target - player.Position;
            var distance = targetOffset.Length();
            var rampedSpeed = maxSpeed*(distance/slowingRadius);
            var clippedSpeed = Math.Min(rampedSpeed, player.MaxSpeed);
            var direction = targetOffset/distance;
            var desiredVelocity = clippedSpeed*direction;

            return desiredVelocity - player.Velocity;
        }
Пример #7
0
        /// <summary>
        /// </summary>
        /// <param name="player"></param>
        /// <param name="target"></param>
        /// <param name="ball"></param>
        /// <returns></returns>
        // TODO: Finish this
        public static Kick PassToPlayer(IPointMass player, IPointMass target, IPointMass ball)
        {
            var desiredDirection = target.Position - player.Position;

            if (ball.Velocity.LengthSquared() < 0.1)
            {
                return new Kick(player, desiredDirection * 100000);
            }
            else
            {
                var projection = ball.Velocity.Projection(desiredDirection);
                var rejection = ball.Velocity.Rejection(desiredDirection);
                var difference = ball.Velocity - desiredDirection;
                var force = desiredDirection - projection - rejection;

                //var angle = Math.Atan2(difference.Y, difference.X);
                //var force = ball.Velocity - rejection * 2;

                //if (Math.Abs(angle) > Math.PI / 2)
                //    force -= projection * 2;

                return new Kick(player, force * 100000);
            }
        }
 private static void DrawDebugInfo(IPointMass pointMass, Brush brush, Font font, Graphics g)
 {
 }
Пример #9
0
 private static IPointMass ClosestPlayerToPoint(IEnumerable<IPointMass> players, IPointMass target, float max, Vector2 goalMiddle)
 {
     return players.OrderBy(p => (p.Position - SteeringStrategies.FuturePosition(p, target, max)).LengthSquared() + DistanceBetween(p.Position, goalMiddle)).First();
 }
Пример #10
0
 /// <summary>
 ///     Creates a new instance of the <see cref="Kick" /> class with the specified player and force.
 /// </summary>
 /// <param name="player">The player to kick the ball.</param>
 /// <param name="force">The desired force on the ball to be exerted by the player.</param>
 public Kick(IPointMass player, Vector2 force)
 {
     Contract.Requires<ArgumentNullException>(player != null);
     Player = player;
     Force = force;
 }
Пример #11
0
 /// <summary>
 /// </summary>
 /// <param name="players"></param>
 /// <param name="target"></param>
 /// <param name="max"></param>
 /// <returns></returns>
 public static IPointMass ClosestPlayerToPoint(IEnumerable<IPointMass> players, IPointMass target, float max)
     => players.OrderBy(p => (p.Position - SteeringStrategies.FuturePosition(p, target, max)).LengthSquared()).First();
Пример #12
0
 private bool IsKickValid(IPointMass player, ISimulation simulation) =>
     Players.Any(p => p == player) &&
     (player.Position - simulation.Ball.Position).Length() < player.Radius + simulation.Ball.Radius;
Пример #13
0
 /// <summary>
 /// </summary>
 /// <param name="player"></param>
 /// <returns></returns>
 public static float GetSlowingRadius(IPointMass player)
 {
     Contract.Requires<ArgumentException>(player != null);
     return player.MaxSpeed*player.MaxSpeed/(2*player.MaxForce/player.Mass);
 }
Пример #14
0
 /// <summary>
 ///     Move toward a target's future position. This method assumes the player will move at their maximum speed.  It also
 ///     ignores friction on the target.
 /// </summary>
 /// <param name="player">The player that should pursue the specified location.</param>
 /// <param name="target">The target position that the player should pursue.</param>
 /// <param name="maxEstimatedTime">The maximum estimated time.</param>
 /// <returns>The force vector that shoud be applied to the player.</returns>
 public static Vector2 Pursue(IPointMass player, IPointMass target, float maxEstimatedTime)
     => Seek(player, FuturePosition(player, target, maxEstimatedTime), player.MaxSpeed);