public override List <Tuple <Vector, double> > GetPoints()
        {
            List <Tuple <PCar, PTire> > hitInforamtions = hitInformation();

            if (null == hitInforamtions || 0 == hitInforamtions.Count)
            {
                return(null);
            }

            List <Tuple <Vector, double> > result = new List <Tuple <Vector, double> >();

            foreach (Tuple <PCar, PTire> hitInfo in hitInforamtions)
            {
                PCar  self = hitInfo.Item1;
                PTire tire = hitInfo.Item2;

                Vector selfPos = new Vector(self.Car.X, self.Car.Y);
                Vector tirePos = new Vector(tire.Tire.X, tire.Tire.Y);

                double angle = self.Car.Angle.AngleDeviation((tirePos - selfPos).Angle);
                double sign  = Math.Sign(angle);

                Vector center = selfPos + (tire.Pos - selfPos) * 0.5;
                Vector dir    = new Vector(path[0].DirOut.X, path[0].DirOut.Y);
                Vector endPos = center + dir.PerpendicularRight() * sign * car.Height;

                result.Add(new Tuple <Vector, double>(endPos, car.Height));
            }

            return(result);
        }
        private List <Tuple <PCar, PTire> > hitInformation()
        {
            List <Tuple <PCar, PTire> > result = new List <Tuple <PCar, PTire> >();

            foreach (Projectile iter in world.Projectiles)
            {
                if (iter.Type == ProjectileType.Tire)
                {
                    PCar  self = new PCar(car, game);
                    PTire tire = new PTire(iter, game);
                    if (checkHit(self, tire))
                    {
                        result.Add(new Tuple <PCar, PTire>(self, tire));
                    }
                }
            }

            return(result);
        }
        private bool checkHit(PCar self, PTire tire)
        {
            double selfRadius  = 0.5 * Math.Sqrt(game.CarWidth * game.CarWidth + game.CarHeight * game.CarHeight);
            double checkRadius = selfRadius + game.TireRadius;

            self.setEnginePower(1);
            MoveToAngleFunction mover = new MoveToAngleFunction(new Vector(path[0].DirOut.X, path[0].DirOut.Y).Angle);

            for (int i = 0; i < MaxCheckTicks; i++)
            {
                Vector lastDistance = tire.LastPos - self.LastPos;
                Vector distance     = tire.Pos - self.Pos;

                if (lastDistance.Length > checkRadius && distance.Length < checkRadius)
                {
                    return(true);
                }

                tire.Iteration(1);
                mover.Iteration(self, 1);
            }

            return(false);
        }
        private bool isRunTire(PCar self, PCar[] their, PCar[] enemies)
        {
            Logger.instance.Assert(null != self, "Self car is null.");

            PCar ignored = self;

            PTire tire = new PTire(self.Pos, self.Dir * game.TireInitialSpeed, game);

            int tireRebound = maxTireRebound;

            for (int i = 0; i < tireCalculateTicks; i++)
            {
                tire.Iteration(1);

                foreach (PCar physicCar in their)
                {
                    physicCar.Iteration(1);

                    Vector collisionNormal = null;
                    if (tireCollisionWithCar(tire.Pos, physicCar, out collisionNormal, 2))
                    {
                        if (ignored == physicCar)
                        {
                            continue;
                        }

                        return(false);
                    }
                }

                foreach (PCar physicCar in enemies)
                {
                    physicCar.Iteration(1);

                    Vector collisionNormal = null;
                    if (tireCollisionWithCar(tire.Pos, physicCar, out collisionNormal, 0.25))
                    {
                        if (null == collisionNormal)
                        {
                            return(false);
                        }

                        double angleDot         = Math.Abs(tire.Speed.Normalize().Dot(collisionNormal));
                        double angleCross       = Math.Abs(tire.Speed.Normalize().Cross(collisionNormal));
                        bool   correctFireAngle = (Math.Abs(tire.Speed.Dot(physicCar.Speed)) > 70 && angleDot > 0.5) ||
                                                  (Math.Abs(tire.Speed.Cross(physicCar.Speed)) > 70 && angleCross > 0.5);
                        return(correctFireAngle && physicCar.Car.Durability > 1.0e-9 && !physicCar.Car.IsFinishedTrack);
                    }
                }

                Vector collisionNormalWithMap = tireCollisionWithMap(tire.Pos, tire.LastPos);
                if (null != collisionNormalWithMap)
                {
                    ignored = null;
                    tire.HitTireWitMap(collisionNormalWithMap);
                    tireRebound--;
                }

                if (!tire.Valid() || tireRebound < 0)
                {
                    return(false);
                }
            }

            return(false);
        }