Пример #1
0
        /// <summary>
        /// Verifica se os limites do ator 1 está intersectando os limites do ator 2,
        /// e retorna um objeto CollisionResult para verificação do resultado.
        /// </summary>
        public static CollisionResult ActorCollision(Actor actor1, Actor actor2)
        {
            CollisionResult result = new CollisionResult
            {
                Type        = CollisionType.None,
                HasCollided = false
            };

            //Fazemos o cálculo simples de intersecção entre retângulos se não há rotação nos atores.
            if (actor1.Transform.Rotation == 0 && actor2.Transform.Rotation == 0)
            {
                //Verifica se  há colisão.
                if (BoundsCollision(actor1.Bounds, actor2.Bounds))
                {
                    //Cria o resultado da colisão entre retângulos.
                    RectangleCollisionResult rcr = new RectangleCollisionResult
                    {
                        Intersection = Rectangle.Intersect(actor1.Bounds, actor2.Bounds)
                    };

                    var ab = actor1.Bounds;
                    var ob = actor2.Bounds;

                    //O vetor de subtração a ser completado e adicionado.
                    rcr.Subtract = Subtract(ab, ob);

                    result.HasCollided     = true;
                    result.Type            = CollisionType.Rectangle;
                    result.RectangleResult = rcr;
                }
            }
            //se as entidades estão rotacionadas.
            else
            {
                PolygonCollisionResult pcr = PolygonCollision(actor1.BoundsR, actor2.BoundsR, actor1.Transform.Velocity);

                if (pcr.Intersect)
                {
                    result.HasCollided   = true;
                    result.Type          = CollisionType.Polygon;
                    result.PolygonResult = pcr;
                }
            }

            return(result);
        }
Пример #2
0
 /// <summary>
 /// Cria um objeto de CollisionResult.
 /// </summary>
 /// <param name="result">True caso houve uma colisão.</param>
 /// <param name="type">True caso a colisão foi entre retângulos não rotacionados.</param>
 /// <param name="intersection">A intersecção da colisão entre retângulos não rotacionados.</param>
 /// <param name="polyResult">O resultado de uma colisão entre polígonos (caso os retângulos estejam rotacionados).</param>
 public CollisionResult(bool result, CollisionType type, RectangleCollisionResult rectangleResult, PolygonCollisionResult polyResult)
 {
     HasCollided     = result;
     Type            = type;
     RectangleResult = rectangleResult;
     PolygonResult   = polyResult;
 }
Пример #3
0
        /// <summary>
        /// Verifica se um polígono colidiu outro polígono.
        /// </summary>
        /// <param name="polygonA">O primeiro polígono.</param>
        /// <param name="polygonB">O segundo polígono.</param>
        /// <param name="velocity">A velocidade do primeiro polígono.</param>
        public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector2 velocity)
        {
            PolygonCollisionResult result = new PolygonCollisionResult();

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

            int     edgeCountA          = polygonA.Edges.Count;
            int     edgeCountB          = polygonB.Edges.Count;
            float   minIntervalDistance = float.PositiveInfinity;
            Vector2 translationAxis     = new Vector2();
            Vector2 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
                Vector2 axis = new Vector2(-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 = Vector2.Dot(axis, 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;

                    Vector2 d = polygonA.Center - polygonB.Center;
                    if (Vector2.Dot(d, 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.Subtract = translationAxis * minIntervalDistance;
            }

            return(result);
        }