예제 #1
0
        public AABBProjection(AABB start, SFML.Window.Vector2f movement, SFML.Graphics.Color color)
        {
            Start = start;
            End = new AABB(new SFML.Window.Vector2f(start.Position.X + movement.X, start.Position.Y + movement.Y), start.Extents.X, start.Extents.Y, Start.Color);

            this.color = color;

            InitializeSegments();
        }
예제 #2
0
        public void TestAABBOverlapTrue()
        {
            AABB box1 = new AABB(new SFML.Window.Vector2f(20.0f, 20.0f), 10.0f, 10.0f);
            AABB box2 = new AABB(new SFML.Window.Vector2f(25.0f, 25.0f), 10.0f, 10.0f);

            bool rtn1 = box1.Overlaps(box2);
            bool rtn2 = box2.Overlaps(box1);

            Assert.IsTrue(rtn1 && rtn2);
        }
예제 #3
0
        public CollisionResults()
        {
            Type = CollisionType.enNone;
            CollisionTime = 0.0f;
            Sides = new Dictionary<AABB.AABBSide, AABB.AABBSide>();

            Object1CollisionAABB = new AABB(new SFML.Window.Vector2f(), new SFML.Window.Vector2f());
            Object2CollisionAABB = new AABB(new SFML.Window.Vector2f(), new SFML.Window.Vector2f());

            //Doesn't matter what we feed this, it should be overridden
            Object1Projection = new AABBProjection(Object1CollisionAABB, new SFML.Window.Vector2f());
            Object2Projection = new AABBProjection(Object2CollisionAABB, new SFML.Window.Vector2f());

            Overlap = new Vector2f();
        }
예제 #4
0
        public void TestAABBProjectionDictionary()
        {
            AABB box1 = new AABB(new SFML.Window.Vector2f(50.0f, 100.0f), 10.0f, 10.0f);
            AABB box2 = new AABB(new SFML.Window.Vector2f(50.0f, 50.0f), 10.0f, 10.0f);

            AABBProjection projection1 = new AABBProjection(box1, new SFML.Window.Vector2f(30.0f, -30.0f));
            AABBProjection projection2 = new AABBProjection(box2, new SFML.Window.Vector2f(30.0f, 30.0f));

            Dictionary<AABBProjection.AABBProjectionSegmentEnum,
                    Dictionary<AABBProjection.AABBProjectionSegmentEnum,
                        List<SFML.Window.Vector2f>>> results = null;

            bool collisions = projection1.CollidesWith(projection2, out results);

            Assert.IsTrue(collisions);
        }
예제 #5
0
        public void TestAABBProjectionList()
        {
            AABB box1 = new AABB(new SFML.Window.Vector2f(50.0f, 80.0f), 10.0f, 10.0f);
            AABB box2 = new AABB(new SFML.Window.Vector2f(50.0f, 50.0f), 10.0f, 10.0f);

            AABBProjection projection1 = new AABBProjection(box1, new SFML.Window.Vector2f(30.0f, -30.0f));
            AABBProjection projection2 = new AABBProjection(box2, new SFML.Window.Vector2f(30.0f, 30.0f));

            List<AABBProjection.AABBProjectionCollisionResult> results = null;

            bool collisions = projection1.CollidesWith(projection2, out results);

            List<AABBProjection.AABBProjectionCollisionResult> sorted = results.OrderBy(x => x.Length).ToList();

            Assert.IsTrue(collisions);

            string debug = String.Empty;
        }
예제 #6
0
        public static CollisionResults TestCollisions(CollisionObject object1, CollisionObject object2)
        {
            CollisionResults results = new CollisionResults() { Object1 = object1, Object2 = object2 };

            //Are they already colliding?
            if (object1.BoundingBox.Overlaps(object2.BoundingBox))
            {
                results.Type = CollisionType.enAbsolute;
                return results;
            }

            //If both items are stationary, then there's no reason for projections. Return
            if ((object1.Velocity.X == 0.0f && object1.Velocity.Y == 0.0f) && (object2.Velocity.X == 0.0f && object2.Velocity.Y == 0.0f))
            {
                return results;
            }

            AABBProjection object1Projection = new AABBProjection(object1.BoundingBox, object1.Velocity);
            AABBProjection object2Projection = new AABBProjection(object2.BoundingBox, object2.Velocity);

            results.Object1Projection = object1Projection;
            results.Object2Projection = object2Projection;

            List<AABBProjection.AABBProjectionCollisionResult> projectionResults = null;

            bool collisions = (object1Projection.CollidesWith(object2Projection, out projectionResults) &&
                                ((object1.Velocity.X != 0.0f || object1.Velocity.Y != 0.0f) && (object2.Velocity.X != 0.0f || object2.Velocity.Y != 0.0f)));
            if (collisions)
            {
                List<AABBProjection.AABBProjectionCollisionResult> sorted = projectionResults.OrderBy(x => x.Length).ToList();

                AABBProjection.AABBProjectionCollisionResult shortestResult = sorted[0];

                AABBProjection.AABBProjectionSegmentEnum[] adjacentSegments = AABBProjection.GetAdjacentSegments(shortestResult.LocalSide);

                List<AABBProjection.AABBProjectionCollisionResult> adjacentSegmentResults = sorted.Where(x => x.OtherSide == shortestResult.OtherSide && adjacentSegments.Contains(x.LocalSide)).OrderBy(x => x.Length).ToList();

                if (adjacentSegmentResults.Count > 0)
                {
                    float shortestLength = adjacentSegmentResults[0].Length;
                    //There could be multiples if we hit a corner
                    adjacentSegmentResults = adjacentSegmentResults.Where(x => x.Length == shortestLength).ToList();

                    //Verify collision by projecting the AABB's to this point-in-time in their movement.
                    float totalMovementDistance = Helpers.DistanceBetweenTwoPoints(object1.BoundingBox.Position, object1Projection.End.Position);
                    //This is when the collision *MIGHT* happen for THIS collision object
                    float pointInTime = shortestLength / totalMovementDistance;

                    SFML.Window.Vector2f object1Position = object1.BoundingBox.Position + (object1.Velocity * pointInTime);
                    AABB localCollisionResultProjection = new AABB(object1Position, object1.BoundingBox.Extents, SFML.Graphics.Color.Green);

                    //Now, see where the OTHER collision object will be at this point in time.
                    SFML.Window.Vector2f otherPosition = object2.BoundingBox.Position + (object2.Velocity * pointInTime);
                    AABB otherCollisionResultProjection = new AABB(otherPosition, object2.BoundingBox.Extents, SFML.Graphics.Color.Blue);
                    results.Object1CollisionAABB = localCollisionResultProjection;
                    results.Object2CollisionAABB = otherCollisionResultProjection;
                    results.CollisionTime = pointInTime;
                    //Do they overlap at the projection result?
                    if (!localCollisionResultProjection.Overlaps(otherCollisionResultProjection))
                        return results;

                    foreach (AABBProjection.AABBProjectionCollisionResult collisionResult in adjacentSegmentResults)
                    {
                        AABB.AABBSide collisionSide = AABBProjection.GetSideFromProjectionSegments(shortestResult.LocalSide, collisionResult.LocalSide);
                        AABB.AABBSide otherCollisionSide = AABB.GetOppositeSide(collisionSide);

                        results.Object1CollisionAABB.Sides[(int)collisionSide].SetColor(SFML.Graphics.Color.Red);
                        results.Object2CollisionAABB.Sides[(int)otherCollisionSide].SetColor(SFML.Graphics.Color.Red);
                        results.Sides[collisionSide] = otherCollisionSide;
                    }

                    results.Type = CollisionType.enPrediction;
                }
            }
            else
            {
                List<ProjectionsSideCollisionInfo> collisionInfo = null;
                AABBProjection checkedObjectProjection = null;
                if (object1.Velocity.X != 0.0f || object1.Velocity.Y != 0.0f)
                {
                    //Test projection1 against projection2's End's segments
                    TestProjectionAgainstAABB(object1Projection, object2Projection.End, out collisionInfo);
                    checkedObjectProjection = object1Projection;
                }
                else if (object2.Velocity.X != 0.0f || object2.Velocity.Y != 0.0f)
                {
                    //Test projection2 against projection1's End segments
                    TestProjectionAgainstAABB(object2Projection, object1Projection.End, out collisionInfo);
                    checkedObjectProjection = object2Projection;
                }

                if(collisionInfo != null)
                {
                    if (collisionInfo.Count > 0)
                    {
                        collisionInfo = collisionInfo.OrderBy(x => x.Length).ToList();
                        ProjectionsSideCollisionInfo closestInfo = collisionInfo[0];
                        float shortestLength = closestInfo.Length;
                        //Verify collision by projecting the AABB's to this point-in-time in their movement.
                        float totalMovementDistance = Helpers.DistanceBetweenTwoPoints(checkedObjectProjection.Start.Position, checkedObjectProjection.End.Position);
                        //This is when the collision *MIGHT* happen for THIS collision object
                        float pointInTime = shortestLength / totalMovementDistance;

                        SFML.Window.Vector2f object1Position = object1.BoundingBox.Position + (object1.Velocity * pointInTime);
                        AABB localCollisionResultProjection = new AABB(object1Position, object1.BoundingBox.Extents, SFML.Graphics.Color.Green);

                        //Now, see where the OTHER collision object will be at this point in time.
                        SFML.Window.Vector2f otherPosition = object2.BoundingBox.Position + (object2.Velocity * pointInTime);
                        AABB otherCollisionResultProjection = new AABB(otherPosition, object2.BoundingBox.Extents, SFML.Graphics.Color.Blue);
                        //Do they overlap at the projection result?
                        //if (!localCollisionResultProjection.Overlaps(otherCollisionResultProjection))
                            //return results;

                        results.Object1CollisionAABB = localCollisionResultProjection;
                        results.Object2CollisionAABB = otherCollisionResultProjection;

                        AABB.AABBSide object1Side = AABB.GetOppositeSide(closestInfo.Side);
                        results.Object1CollisionAABB.Sides[(int)object1Side].SetColor(SFML.Graphics.Color.Red);
                        results.Object2CollisionAABB.Sides[(int)closestInfo.Side].SetColor(SFML.Graphics.Color.Red);

                        results.Type = CollisionType.enPrediction;
                        results.Sides[object1Side] = closestInfo.Side;
                        results.CollisionTime = pointInTime;
                    }
                }
            }

            if (results.CollisionTime == (1.0f / 0.0f))
            {
                int i = 0;
            }

            return results;
        }
예제 #7
0
        private static void TestProjectionAgainstAABB(AABBProjection projection, AABB aabb, out List<ProjectionsSideCollisionInfo> collisionInfo )
        {
            collisionInfo = new List<ProjectionsSideCollisionInfo>();
            foreach (AABBProjection.AABBProjectionSegment projectionSegment in projection.PathSegments.Values)
            {
                for (int i = 0; i < 4; i++)
                {
                    AABB.AABBSide currentSide = (AABB.AABBSide)i;
                    LineSegment aabbSegment = aabb.Sides[i];
                    Vector2f[] collisionPoints = null;
                    if (projectionSegment.Path.CollidesWith(aabbSegment, out collisionPoints))
                    {
                        foreach (Vector2f collisionPoint in collisionPoints)
                        {
                            ProjectionsSideCollisionInfo info = new ProjectionsSideCollisionInfo();
                            info.ProjectionSegment = projectionSegment;
                            info.CollisionPoint = collisionPoint;
                            info.Side = currentSide;
                            info.Length = Helpers.DistanceBetweenTwoPoints(projectionSegment.Path.Start, collisionPoint);

                            collisionInfo.Add(info);
                        }
                    }
                }
            }
        }
예제 #8
0
        public void TestAABBOverlapFalse()
        {
            AABB box1 = new AABB(new SFML.Window.Vector2f(20.0f, 20.0f), 10.0f, 10.0f);
            AABB box2 = new AABB(new SFML.Window.Vector2f(40.0f, 40.0f), 10.0f, 10.0f);

            bool rtn1 = box1.Overlaps(box2);
            bool rtn2 = box2.Overlaps(box1);

            window.Draw(box1);
            window.Draw(box2);

            //Assert.IsFalse(rtn1 && rtn2);
        }
예제 #9
0
 public Boolean Overlaps(AABB other)
 {
     return (Math.Abs(Center.X - other.Center.X) * 2 <= (Extents.X + other.Extents.X)) && (Math.Abs(Center.Y - other.Center.Y) * 2 <= (Extents.Y + other.Extents.Y));
 }
예제 #10
0
 public CollisionObject(Vector2f position, Vector2f extents, SFML.Graphics.Color color)
 {
     originalColor = color;
     BoundingBox = new AABB(position, extents, color);
     Configure();
 }