/// <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); }
/// <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; }
/// <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); }