/// <summary>
 /// Constructs GameEntity using given position, hitbox and hitpoints.
 /// </summary>
 /// <param name="position">Position of entity</param>
 /// <param name="hitbox">Hitbox.</param>
 /// <param name="hitpoints">Hitpoints.</param>
 public GameEntity(Point position, Polygon hitbox, int hitpoints)
     : base(position)
 {
     _hitbox = hitbox;
     _hitpoints = hitpoints;
     _remove = false;
 }
 /// <summary>
 /// Constructs new entity.
 /// </summary>
 /// <param name="bitmap">Name of bitmap to use.</param>
 /// <param name="hitbox">Definition of hitbox (polygon).</param>
 /// <param name="hitpoints">Number of hitpoints.</param>
 public Entity(string bitmap, Polygon hitbox, int hitpoints)
 {
     _bitmap = bitmap;
     _hitbox = hitbox;
     _hitpoints = hitpoints;
     _tick = 0;
     _remove = false;
 }
        /// <summary>
        /// Constructs Player in default position.
        /// </summary>
        /// <param name="playerType">Type of player.</param>
        public PlayerEntity(PlayerType playerType)
            : base(new Point(270, 430), null, 1)
        {
            _playerType = playerType;
            _grazebox = null;

            _cannonMain = 0;
            _cannonAux = 0;
            _cooldown = 0;
        }
        /// <summary>
        /// Constructs a new player in the defult position.
        /// </summary>
        /// <param name="playerType">Type of player selected.</param>
        public PlayerEntity(PlayerType playerType)
            : base("Player" + playerType.ToString(), InitBounding(new Point(270, 430), playerType), 1)
        {
            _playerType = playerType;
            _grazebox = InitGrazeBox(Hitbox.Centroid, playerType);

            _cannonAux = 0;
            _cannonMain = 0;
            _cooldown = 0;
        }
        /// <summary>
        /// Determines weather the polygons collide in the x-y plane.
        /// </summary>
        /// <param name="polygonA">Polygon a.</param>
        /// <param name="polygonB">Polygon b.</param>
        /// <returns>Boolean.</returns>
        public static bool Collides(Polygon polygonA, Polygon polygonB)
        {
            bool result = true;

            int edgeCountA = polygonA.Edges.Count;
            int edgeCountB = polygonB.Edges.Count;
            Vector edge;

            for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                if (edgeIndex < edgeCountA)
                {
                    edge = polygonA.Edges[edgeIndex];
                }
                else
                {
                    edge = polygonB.Edges[edgeIndex - edgeCountA];
                }

                Vector axis = edge.PerpendicularVector2D();
                axis = axis.Unit;

                double minA = 0;
                double maxA = 0;
                double minB = 0;
                double maxB = 0;

                ProjectPolygon(axis, polygonA, ref minA, ref maxA);
                ProjectPolygon(axis, polygonB, ref minB, ref maxB);

                if (IntervalDisance(minA, maxA, minB, maxB) > 0)
                {
                    result = false;
                }
            }
            return result;
        }
        public static PolygonCollisionResult PolygonCollision(Polygon a, Polygon b, Vector velocity)
        {
            PolygonCollisionResult result = new PolygonCollisionResult();
            result.WillIntersect = true;
            result.Intersect = true;

            int edgeCountA = a.Edges.Count;
            int edgeCountB = b.Edges.Count;
            double minIntervalDistance = double.PositiveInfinity;
            Vector traslationAxis = new Vector();
            Vector edge;

            for(int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                if(edgeIndex < edgeCountA)
                {
                    edge = a.Edges[edgeIndex];
                }
                else
                {
                    edge = b.Edges[edgeIndex - edgeCountA];
                }

                Vector axis = edge.PerpendicularVector2D();
                axis = axis.Unit;

                double minA = 0;
                double maxA = 0;
                double minB = 0;
                double maxB = 0;

                ProjectPolygon(axis, a, ref minA, ref maxA);
                ProjectPolygon(axis, b, ref minB, ref maxB);

                if (IntervalDisance(minA, maxA, minB, maxB) > 0)
                {
                    result.Intersect = false;
                }

                double velosityProjection = axis.DotProduct(velocity);

                if(velosityProjection < 0)
                {
                    minA += velosityProjection;
                }
                else
                {
                    maxA += velosityProjection;
                }

                double intervalDistance = IntervalDisance(minA, maxA, minB, maxB);
                if(intervalDistance > 0)
                {
                    result.WillIntersect = false;
                }

                if(!result.Intersect && !result.WillIntersect)
                {
                    break;
                }

                intervalDistance = Math.Abs(intervalDistance);
                if(intervalDistance < minIntervalDistance)
                {
                    minIntervalDistance = intervalDistance;
                    traslationAxis = axis;

                    Point d = a.Centroid - b.Centroid;
                    if(d.ToVector().DotProduct(traslationAxis) < 0)
                    {
                        traslationAxis = traslationAxis * -1;
                    }
                }
            }

            if(result.WillIntersect)
            {
                result.MinimumTranslationVector = traslationAxis * minIntervalDistance;
            }

            return result;
        }
 public static void ProjectPolygon(Vector axis, Polygon polygon, ref double min, ref double max)
 {
     double dotProduct = axis.DotProduct(polygon.Vertices[0].ToVector());
     min = dotProduct;
     max = dotProduct;
     for(int i = 0; i < polygon.Vertices.Count; i++)
     {
         dotProduct = polygon.Vertices[i].ToVector().DotProduct(axis);
         if(dotProduct < min)
         {
             min = dotProduct;
         }
         else if(dotProduct > max)
         {
             max = dotProduct;
         }
     }
 }
 /// <summary>
 /// Constructs GameEntity using given hitbox.
 /// </summary>
 /// <param name="hitbox"></param>
 public GameEntity(Polygon hitbox)
     : this(hitbox.Middle, hitbox, 1)
 {
 }
        private static Polygon InitBounding(BulletType bulletType, Point position, Vector trajectory)
        {
            Point[] vertices = new Point[]
            {
                new Point(0, 0),
                new Point(15, 0),
                new Point(15, 15),
                new Point(0, 15)
            };

            switch (bulletType)
            {
                case BulletType.Beam:
                    vertices = new Point[]
                    {
                        new Point(0, 0),
                        new Point(15, 0),
                        new Point(15, 15),
                        new Point(0, 15)
                    };
                    break;

                case BulletType.BigStar:
                    vertices = new Point[]
                    {
                        new Point(2, 13),
                        new Point(11, 10),
                        new Point(15, 3),
                        new Point(16, 3),
                        new Point(20, 10),
                        new Point(29, 13),
                        new Point(24, 20),
                        new Point(23, 28),
                        new Point(16, 25),
                        new Point(15, 25),
                        new Point(8, 28),
                        new Point(6, 20)
                    };
                    break;

                case BulletType.Crystal:
                    vertices = new Point[]
                    {
                        new Point(4, 5),
                        new Point(7, 0),
                        new Point(8, 0),
                        new Point(11, 5),
                        new Point(11, 10),
                        new Point(8, 15),
                        new Point(7, 15),
                        new Point(4, 10)
                    };
                    break;

                case BulletType.Dart:
                    vertices = new Point[]
                    {
                        new Point(4, 7),
                        new Point(7, 0),
                        new Point(8, 0),
                        new Point(11, 7),
                        new Point(9, 8),
                        new Point(9, 9),
                        new Point(11, 11),
                        new Point(11, 13),
                        new Point(9, 15),
                        new Point(6, 15),
                        new Point(4, 13),
                        new Point(4, 11),
                        new Point(6, 9),
                        new Point(6, 8)
                    };
                    break;

                case BulletType.HugeSphere:
                    vertices = new Point[]
                    {
                        new Point(7, 27),
                        new Point(10, 19),
                        new Point(14, 14),
                        new Point(19, 10),
                        new Point(27, 7),
                        new Point(36, 7),
                        new Point(44, 10),
                        new Point(49, 14),
                        new Point(53, 19),
                        new Point(56, 27),
                        new Point(56, 36),
                        new Point(53, 44),
                        new Point(49, 49),
                        new Point(44, 53),
                        new Point(36, 56),
                        new Point(27, 56),
                        new Point(19, 53),
                        new Point(14, 49),
                        new Point(10, 44),
                        new Point(7, 36)
                    };
                    break;

                case BulletType.LargeSphere:
                    vertices = new Point[]
                    {
                        new Point(3, 13),
                        new Point(5, 8),
                        new Point(8, 5),
                        new Point(13, 3),
                        new Point(18, 3),
                        new Point(23, 5),
                        new Point(26, 8),
                        new Point(28, 13),
                        new Point(28, 18),
                        new Point(26, 23),
                        new Point(23, 26),
                        new Point(18, 28),
                        new Point(13, 28),
                        new Point(8, 26),
                        new Point(5, 23),
                        new Point(3, 18)
                    };
                    break;

                case BulletType.Palse:
                    vertices = new Point[]
                    {
                        new Point(0, 13),
                        new Point(3, 6),
                        new Point(7, 2),
                        new Point(8, 2),
                        new Point(12, 6),
                        new Point(15, 13),
                        new Point(13, 15),
                        new Point(11, 9),
                        new Point(10, 13),
                        new Point(8, 15),
                        new Point(7, 15),
                        new Point(5, 13),
                        new Point(4, 9),
                        new Point(2, 15)
                    };
                    break;

                case BulletType.Ring:
                    vertices = new Point[]
                    {
                        new Point(0, 6),
                        new Point(2, 2),
                        new Point(6, 0),
                        new Point(9, 0),
                        new Point(13, 2),
                        new Point(15, 6),
                        new Point(15, 9),
                        new Point(13, 13),
                        new Point(9, 15),
                        new Point(6, 15),
                        new Point(2, 13),
                        new Point(0, 9)
                    };
                    break;

                case BulletType.Seed:
                    vertices = new Point[]
                    {
                        new Point(4, 6),
                        new Point(5, 3),
                        new Point(7, 1),
                        new Point(8, 1),
                        new Point(10, 3),
                        new Point(11, 6),
                        new Point(11, 9),
                        new Point(10, 12),
                        new Point(8, 14),
                        new Point(7, 14),
                        new Point(5, 12),
                        new Point(4, 9)
                    };
                    break;

                case BulletType.Shere:
                    vertices = new Point[]
                    {
                        new Point(1, 6),
                        new Point(3, 3),
                        new Point(6, 1),
                        new Point(9, 1),
                        new Point(12, 3),
                        new Point(14, 6),
                        new Point(14, 9),
                        new Point(12, 12),
                        new Point(9, 14),
                        new Point(6, 14),
                        new Point(3, 12),
                        new Point(1, 9)
                    };
                    break;

                case BulletType.SmallRing:
                    vertices = new Point[]
                    {
                        new Point(0, 4),
                        new Point(1, 1),
                        new Point(4, 0),
                        new Point(7, 0),
                        new Point(10, 1),
                        new Point(11, 4),
                        new Point(11, 7),
                        new Point(10, 10),
                        new Point(7, 11),
                        new Point(4, 11),
                        new Point(1, 10),
                        new Point(0, 7)
                    };
                    break;

                case BulletType.SmallSphere:
                    vertices = new Point[]
                    {
                        new Point(1, 4),
                        new Point(4, 1),
                        new Point(7, 1),
                        new Point(10, 4),
                        new Point(10, 7),
                        new Point(7, 10),
                        new Point(4, 10),
                        new Point(1, 7)
                    };
                    break;

                case BulletType.Star:
                    vertices = new Point[]
                    {
                        new Point(1, 6),
                        new Point(5, 5),
                        new Point(7, 2),
                        new Point(8, 2),
                        new Point(10, 5),
                        new Point(14, 6),
                        new Point(11, 10),
                        new Point(11, 14),
                        new Point(8, 12),
                        new Point(7, 12),
                        new Point(4, 14),
                        new Point(4, 10)
                    };
                    break;
            }

            Polygon bounding = new Polygon(vertices, position);

            double angle = 2 * Math.PI - trajectory.Phi - BasicMath.ToRad(90);

            bounding.YawZ(angle, bounding.Middle);

            return bounding;
        }
 /// <summary>
 /// Constructs a polyhedron with the provided faces at the given location
 /// </summary>
 /// <param name="faces">Array of faces (polygon)</param>
 /// <param name="location">Location (point)</param>
 public Polyhedron(Polygon[] faces, Point location)
 {
     _faces = new List<Polygon>(faces);
     Offset(new Vector(location, Center));
 }
 /// <summary>
 /// Constructs a polyhedron with the provided faces.
 /// </summary>
 /// <param name="faces">Array of faces (polygon)</param>
 public Polyhedron(Polygon[] faces)
 {
     _faces = new List<Polygon>(faces);
 }