Пример #1
0
        // Check if polygon A is going to collide with polygon B for the given velocity
        public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector velocity)
        {
            // TODO - Do stuff with polygonC and polygonD - they're meant to be the bow and stern and take less damage
            // Get Nick to explain the for loop

            PolygonCollisionResult result = new PolygonCollisionResult();

            result.Intersect     = true;
            result.WillIntersect = true;

            int    edgeCountA          = polygonA.Edges.Count;
            int    edgeCountB          = polygonB.Edges.Count;
            float  minIntervalDistance = float.PositiveInfinity;
            Vector translationAxis     = new Vector();
            Vector edge;

            // Loop through all the edges of both polygons
            for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                if (edgeIndex < edgeCountA)
                {
                    edge = polygonA.Edges[edgeIndex];
                }
                else
                {
                    edge = polygonB.Edges[edgeIndex - edgeCountA];
                }

                // ===== 1. Find if the polygons are currently intersecting =====

                // Find the axis perpendicular to the current edge
                Vector axis = new Vector(-edge.Y, edge.X);
                axis.Normalize();

                // Find the projection of the polygon on the current axis
                float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
                ProjectPolygon(axis, polygonA, ref minA, ref maxA);
                ProjectPolygon(axis, polygonB, ref minB, ref maxB);

                // Check if the polygon projections are currentlty intersecting
                if (IntervalDistance(minA, maxA, minB, maxB) > 0)
                {
                    result.Intersect = false;
                }

                // ===== 2. Now find if the polygons *will* intersect =====

                // Project the velocity on the current axis
                float velocityProjection = axis.DotProduct(velocity);

                // Get the projection of polygon A during the movement
                if (velocityProjection < 0)
                {
                    minA += velocityProjection;
                }
                else
                {
                    maxA += velocityProjection;
                }

                // Do the same test as above for the new projection
                float intervalDistance   = IntervalDistance(minA, maxA, minB, maxB);
                if (intervalDistance > 0)
                {
                    result.WillIntersect = false;
                }

                // If the polygons are not intersecting and won't intersect, exit the loop
                if (!result.Intersect && !result.WillIntersect)
                {
                    break;
                }

                // Check if the current interval distance is the minimum one. If so store
                // the interval distance and the current distance.
                // This will be used to calculate the minimum translation vector
                intervalDistance = Math.Abs(intervalDistance);
                if (intervalDistance < minIntervalDistance)
                {
                    minIntervalDistance = intervalDistance;
                    translationAxis     = axis;

                    Vector d = polygonA.Center - polygonB.Center;
                    if (d.DotProduct(translationAxis) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }
            }

            // The minimum translation vector can be used to push the polygons appart.
            // First moves the polygons by their velocity
            // then move polygonA by MinimumTranslationVector.
            if (result.WillIntersect)
            {
                result.MinimumTranslationVector = translationAxis * minIntervalDistance;
            }

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Performed before drawing to move all animations onto the next timestep.
        /// </summary>
        /// <param name="elapsedMilliseconds">Time elapsed.</param>
        private void PerformAnimationStep(double elapsedMilliseconds)
        {
            if (_aPressed)
            {
                _data.Ships[2].Angle -= (float)(elapsedMilliseconds / 1000) * _data.Settings.TurnSpeed;

                if (_data.Ships[2].Angle < 0)
                {
                    _data.Ships[2].Angle += 360;
                }
            }

            if (_dPressed)
            {
                _data.Ships[2].Angle += (float)(elapsedMilliseconds / 1000) * _data.Settings.TurnSpeed;

                if (_data.Ships[2].Angle > 360)
                {
                    _data.Ships[2].Angle -= 360;
                }
            }

            if (_wPressed)
            {
                _data.Ships[2].Speed += (float)(elapsedMilliseconds / 1000) * _data.Settings.Acceleration;

                if (_data.Ships[2].Speed > _data.Settings.MaxSpeed)
                {
                    _data.Ships[2].Speed = _data.Settings.MaxSpeed;
                }
            }

            if (_sPressed)
            {
                _data.Ships[2].Speed -= (float)(elapsedMilliseconds / 1000) * _data.Settings.Deceleration;

                if (_data.Ships[2].Speed < -_data.Settings.MaxReverseSpeed)
                {
                    _data.Ships[2].Speed = -_data.Settings.MaxReverseSpeed;
                }
            }
            if (_qPressed)
            {
                if (_data.Ships[2].Reload <= 0)
                {
                    _data.Cannonballs.Add(_data.Ships[2].FireCannonball(_data.Settings, _data.Ships[2].Angle - 90));
                }
            }
            if (_ePressed)
            {
                if (_data.Ships[2].Reload <= 0)
                {
                    _data.Cannonballs.Add(_data.Ships[2].FireCannonball(_data.Settings, _data.Ships[2].Angle + 90));
                }
            }

            if (_data.Ships[2].Reload > 0)
            {
                _data.Ships[2].Reload -= (float)elapsedMilliseconds / 1000F;
            }

            foreach (var ship in _data.Ships)
            {
                var originalLocation = new PointF(ship.X, ship.Y);

                ship.MoveShip((float)elapsedMilliseconds / 1000F);

                var newLocation = new PointF(ship.X, ship.Y);

                var velocity = new Vector(newLocation.X - originalLocation.X, newLocation.Y - originalLocation.Y);

                var shipPolygon_hull = new Polygon();
                shipPolygon_hull.Points.Add(new Vector(-20, -20));
                shipPolygon_hull.Points.Add(new Vector(20, -20));
                shipPolygon_hull.Points.Add(new Vector(20, 20));
                shipPolygon_hull.Points.Add(new Vector(-20, 20));
                shipPolygon_hull.Rotate(ship.Angle);
                shipPolygon_hull.Offset(ship.X, ship.Y);
                shipPolygon_hull.BuildEdges();

                var shipPolygon_bow = new Polygon();
                shipPolygon_bow.Points.Add(new Vector(20, 20));
                shipPolygon_bow.Points.Add(new Vector(0, 60));
                shipPolygon_bow.Points.Add(new Vector(0, 60));
                shipPolygon_bow.Points.Add(new Vector(-20, 20));
                shipPolygon_bow.Rotate(ship.Angle);
                shipPolygon_bow.Offset(ship.X, ship.Y);
                shipPolygon_bow.BuildEdges();

                var shipPolygon_stern = new Polygon();
                shipPolygon_stern.Points.Add(new Vector(-20, -20));
                shipPolygon_stern.Points.Add(new Vector(0, -50));
                shipPolygon_stern.Points.Add(new Vector(0, -50));
                shipPolygon_stern.Points.Add(new Vector(20, -20));
                shipPolygon_stern.Rotate(ship.Angle);
                shipPolygon_stern.Offset(ship.X, ship.Y);
                shipPolygon_stern.BuildEdges();

                // Check for collisions with other ships

                foreach (var otherShip in _data.Ships)
                {
                    if (otherShip == ship)
                    {
                        continue;
                    }

                    var otherShipPolygon_hull = new Polygon();
                    otherShipPolygon_hull.Points.Add(new Vector(-20, -20));
                    otherShipPolygon_hull.Points.Add(new Vector(20, -20));
                    otherShipPolygon_hull.Points.Add(new Vector(20, 20));
                    otherShipPolygon_hull.Points.Add(new Vector(-20, 20));
                    otherShipPolygon_hull.Rotate(otherShip.Angle);
                    otherShipPolygon_hull.Offset(otherShip.X, otherShip.Y);
                    otherShipPolygon_hull.BuildEdges();

                    // Point(20, 20), new Point(0, 50), new Point(0, 50), new Point(-20, 20)

                    var otherShipPolygon_bow = new Polygon();
                    otherShipPolygon_bow.Points.Add(new Vector(20, 20));
                    otherShipPolygon_bow.Points.Add(new Vector(0, 60));
                    otherShipPolygon_bow.Points.Add(new Vector(0, 60));
                    otherShipPolygon_bow.Points.Add(new Vector(-20, 20));
                    otherShipPolygon_bow.Rotate(otherShip.Angle);
                    otherShipPolygon_bow.Offset(otherShip.X, otherShip.Y);
                    otherShipPolygon_bow.BuildEdges();

                    var otherShipPolygon_stern = new Polygon();
                    otherShipPolygon_stern.Points.Add(new Vector(-20, -20));
                    otherShipPolygon_stern.Points.Add(new Vector(0, -50));
                    otherShipPolygon_stern.Points.Add(new Vector(0, -50));
                    otherShipPolygon_stern.Points.Add(new Vector(20, -20));
                    otherShipPolygon_stern.Rotate(otherShip.Angle);
                    otherShipPolygon_stern.Offset(otherShip.X, otherShip.Y);
                    otherShipPolygon_stern.BuildEdges();

                    // TODO - Make an "anypart" polygon instead of having polygons for each
                    // TODO - reduce damage taken by otherShip's bow and stern

                    PolygonCollisionResult h_hull  = Collisions.PolygonCollision(shipPolygon_hull, otherShipPolygon_hull, velocity);
                    PolygonCollisionResult h_bow   = Collisions.PolygonCollision(shipPolygon_hull, otherShipPolygon_bow, velocity);
                    PolygonCollisionResult h_stern = Collisions.PolygonCollision(shipPolygon_hull, otherShipPolygon_stern, velocity);

                    PolygonCollisionResult b_hull  = Collisions.PolygonCollision(shipPolygon_bow, otherShipPolygon_hull, velocity);
                    PolygonCollisionResult b_bow   = Collisions.PolygonCollision(shipPolygon_bow, otherShipPolygon_bow, velocity);
                    PolygonCollisionResult b_stern = Collisions.PolygonCollision(shipPolygon_bow, otherShipPolygon_stern, velocity);

                    PolygonCollisionResult s_hull  = Collisions.PolygonCollision(shipPolygon_stern, otherShipPolygon_hull, velocity);
                    PolygonCollisionResult s_bow   = Collisions.PolygonCollision(shipPolygon_stern, otherShipPolygon_bow, velocity);
                    PolygonCollisionResult s_stern = Collisions.PolygonCollision(shipPolygon_stern, otherShipPolygon_stern, velocity);

                    if (h_hull.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + h_hull.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + h_hull.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= h_hull.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= h_hull.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down since it's hit it.

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (h_bow.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + h_bow.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + h_bow.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= h_bow.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= h_bow.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (h_stern.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + h_stern.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + h_stern.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= h_stern.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= h_stern.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }

                    /* shopPolygon_bow */

                    if (b_hull.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + b_hull.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + b_hull.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= b_hull.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= b_hull.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down since it's hit it.

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (b_bow.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + b_bow.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + b_bow.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= b_bow.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= b_bow.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (b_stern.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + b_stern.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + b_stern.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= b_stern.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= b_stern.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }

                    /* shipPolygon_stern */

                    if (s_hull.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + s_hull.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + s_hull.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= s_hull.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= s_hull.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down since it's hit it.

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (s_bow.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + s_bow.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + s_bow.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= s_bow.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= s_bow.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                    if (s_stern.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;

                        ship.X += velocity.X + s_stern.MinimumTranslationVector.X / 2.0F;
                        ship.Y += velocity.Y + s_stern.MinimumTranslationVector.Y / 2.0F;

                        otherShip.X -= s_stern.MinimumTranslationVector.X / 2.0F;
                        otherShip.Y -= s_stern.MinimumTranslationVector.Y / 2.0F;

                        // Slow the ship down

                        if (ship.Speed > 0)
                        {
                            if (ship.Speed > _data.Settings.MaxSpeed / 2)
                            {
                                otherShip.Health -= (ship.Speed - (_data.Settings.MaxSpeed / 2)) * (float)(1000.0 * (elapsedMilliseconds / 100000));
                            }

                            ship.Speed -= (float)(1000.0 * (elapsedMilliseconds / 1000));

                            if (ship.Speed < 0)
                            {
                                ship.Speed = 0;
                            }
                        }

                        break;
                    }
                }
            }

            // Check for otherShip collision with cannonballs

            for (var i = 0; i < _data.Cannonballs.Count; i++)
            {
                // TODO: Update required for old location

                var shell = _data.Cannonballs[i];

                var velocity = shell.GetMovementVector((float)elapsedMilliseconds / 1000F);

                // Find out if this overlaps any tank except its owner

                foreach (var ship in _data.Ships)
                {
                    if (ship == shell.Ship)
                    {
                        continue;
                    }

                    var shipPolygon_hull = new Polygon();
                    shipPolygon_hull.Points.Add(new Vector(-20, -20));
                    shipPolygon_hull.Points.Add(new Vector(20, -20));
                    shipPolygon_hull.Points.Add(new Vector(20, 20));
                    shipPolygon_hull.Points.Add(new Vector(-20, 20));
                    shipPolygon_hull.Rotate(ship.Angle);
                    shipPolygon_hull.Offset(ship.X, ship.Y);
                    shipPolygon_hull.BuildEdges();

                    var shipPolygon_bow = new Polygon();
                    shipPolygon_bow.Points.Add(new Vector(20, 20));
                    shipPolygon_bow.Points.Add(new Vector(0, 60));
                    shipPolygon_bow.Points.Add(new Vector(0, 60));
                    shipPolygon_bow.Points.Add(new Vector(-20, 20));
                    shipPolygon_bow.Rotate(ship.Angle);
                    shipPolygon_bow.Offset(ship.X, ship.Y);
                    shipPolygon_bow.BuildEdges();

                    var shipPolygon_stern = new Polygon();
                    shipPolygon_stern.Points.Add(new Vector(-20, -20));
                    shipPolygon_stern.Points.Add(new Vector(0, -50));
                    shipPolygon_stern.Points.Add(new Vector(0, -50));
                    shipPolygon_stern.Points.Add(new Vector(20, -20));
                    shipPolygon_stern.Rotate(ship.Angle);
                    shipPolygon_stern.Offset(ship.X, ship.Y);
                    shipPolygon_stern.BuildEdges();

                    // TODO - Add shipPolygon_bow, shipPolygon_stern, to a Polygon collision detection

                    PolygonCollisionResult r       = Collisions.PolygonCollision(shell.cannonballPolygon, shipPolygon_hull, velocity);
                    PolygonCollisionResult r_bow   = Collisions.PolygonCollision(shell.cannonballPolygon, shipPolygon_bow, velocity);
                    PolygonCollisionResult r_stern = Collisions.PolygonCollision(shell.cannonballPolygon, shipPolygon_stern, velocity);

                    if (r.WillIntersect)
                    {
                        //playerTranslation = velocity + r.MinimumTranslationVector;
                        // No need to do a translation, this is a hit!
                        ship.cannonballX = shell.X - 15;
                        ship.cannonballY = shell.Y;
                        ship.Health     -= _data.Settings.HitDamage;
                        if (ship.Health <= 0)
                        {
                            ship.Dead = true;
                        }
                        shell.Life = 0;
                        _bang      = true;
                        ship.Hurt  = true;
                        break;
                    }
                    if (r_bow.WillIntersect)
                    {
                        ship.cannonballX = shell.X - 15;
                        ship.cannonballY = shell.Y;
                        ship.Health     -= _data.Settings.HitDamage / 10;
                        if (ship.Health <= 0)
                        {
                            ship.Dead = true;
                        }
                        shell.Life = 0;
                        _bang      = true;
                        ship.Hurt  = true;
                        break;
                    }
                    if (r_stern.WillIntersect)
                    {
                        ship.cannonballX = shell.X - 15;
                        ship.cannonballY = shell.Y;
                        ship.Health     -= _data.Settings.HitDamage / 10;
                        if (ship.Health <= 0)
                        {
                            ship.Dead = true;
                        }
                        shell.Life = 0;
                        _bang      = true;
                        ship.Hurt  = true;
                        break;
                    }
                }

                shell.MoveCannonball(velocity);

                shell.Life -= (float)elapsedMilliseconds / 1000F;

                if (shell.Life <= 0)
                {
                    _data.Cannonballs.RemoveAt(i);
                    i--;
                }

                // TODO: Update required for new location
            }

            UpdateRequired();
        }