コード例 #1
0
        private void CheckForCollisions(ICollidable collidable, IEnumerable <ICollidable> candidates)
        {
            var vel    = GetEffectiveVelocity(collidable);
            var velX   = new Vector2(vel.X, 0);
            var velY   = new Vector2(0, vel.Y);
            var modelX = new CollisionModel(collidable.Bounds, velX);
            var modelY = new CollisionModel(collidable.Bounds, velY);

            foreach (var other in candidates)
            {
                var otherVel = GetEffectiveVelocity(other);

//                var otherModel = new CollisionModel(other.Bounds, otherVel);
//                var collision = model.GetCollision(otherModel);
//                if (!collision.IsNullCollision())
//                {
//                    collidable.OnCollideWith(other, collision.ReversePolarity(), this);
//                    other.OnCollideWith(collidable, collision, this);
//                    this.Collision?.Invoke(this, new CollisionEventArgs(collidable, other, collision));
//                }

                var otherVelX   = new Vector2(otherVel.X, 0);
                var otherVelY   = new Vector2(0, otherVel.Y);
                var otherModelX = new CollisionModel(other.Bounds, otherVelX);
                var otherModelY = new CollisionModel(other.Bounds, otherVelY);
                var collisionX  = modelX.GetCollision(otherModelX);
                var collisionY  = modelY.GetCollision(otherModelY);
                if (!collisionY.IsNullCollision())
                {
                    collidable.OnCollideWith(other, collisionY.ReversePolarity(), this);
                    other.OnCollideWith(collidable, collisionY, this);
                    this.Collision?.Invoke(this, new CollisionEventArgs(collidable, other, collisionY));
                }

                if (!collisionX.IsNullCollision())
                {
                    collidable.OnCollideWith(other, collisionX.ReversePolarity(), this);
                    other.OnCollideWith(collidable, collisionX, this);
                    this.Collision?.Invoke(this, new CollisionEventArgs(collidable, other, collisionX));
                }
            }

            var bounds = RectangleF.From(this.ContainerBounds);

            if (!modelX.IsInside(bounds) || !modelY.IsInside(bounds))
            {
                var pseg         = new LineSegment(collidable.Position, vel);
                var intersection = bounds.Intersection(pseg);
                collidable.OnContainerExit(intersection, this);
            }
        }
コード例 #2
0
        public RectangleF Intersection(CollisionModel other)
        {
            var rself   = this.R1;
            var rother  = other.R1;
            var overlap = RectangleF.Intersect(rself, rother);

            // return intersection rectangle, or empty rectangle if there is no intersection
            if (overlap != RectangleF.Empty || !this.Intersects(other))
            {
                return(overlap);
            }

            return(RectangleF.Empty);
        }
コード例 #3
0
        public bool Intersects(CollisionModel other)
        {
            if (R0.Intersects(other.R0) || R0.Intersects(other.R1))
            {
                return(true);
            }

            if (R1.Intersects(other.R0) || R1.Intersects(other.R1))
            {
                return(true);
            }

            return(this.moveEdges.Any(e0 => other.moveEdges.Any(e0.Intersects)));
        }
コード例 #4
0
        public CollisionMoment GetCollision(CollisionModel other)
        {
            if (this.DoesNotIntersect(other))
            {
                return(CollisionMoment.NullCollision);
            }

            var overlap = RectangleF.Intersect(this.R1, other.R1);
            var thisDv  = MathUtils.Abs(this.Dv);
            var len     = thisDv.Length();
            var dx      = Math.Min(overlap.Width, thisDv.X);
            var dy      = Math.Min(overlap.Height, thisDv.Y);
            var dvec    = new Vector2(dx, dy);

            var edges = this.DetermineEdges(other);
            var alpha = len > 0 ? (1 - dvec.Length() / thisDv.Length()) : 1;

            return(new CollisionMoment(edges.Item1, edges.Item2, alpha));
        }
コード例 #5
0
 public bool DoesNotIntersect(CollisionModel other)
 {
     return(!this.Intersects(other));
 }
コード例 #6
0
        private Tuple <CollisionEdge, CollisionEdge> DetermineEdges(CollisionModel other)
        {
            var thisEdge  = CollisionEdge.None;
            var otherEdge = CollisionEdge.None;

            if (other.R1.Width <= 0 || other.R1.Height <= 0)
            {
                return(new Tuple <CollisionEdge, CollisionEdge>(thisEdge, otherEdge));
            }

            var otherEdgeMapping = new Dictionary <LineSegment, CollisionEdge>()
            {
                { other.R1.LeftEdge, CollisionEdge.Left },
                { other.R1.RightEdge, CollisionEdge.Right },
                { other.R1.BottomEdge, CollisionEdge.Bottom },
                { other.R1.TopEdge, CollisionEdge.Top }
            };

            var intersections = new List <IntersectionPoint>();

            foreach (var moveEdge in this.moveEdges)
            {
                foreach (var edge in otherEdgeMapping.Keys)
                {
                    var p = moveEdge.Intersection(edge);
                    if (MathUtils.IsVectorNaN(p) || MathUtils.IsVectorInfinite(p))
                    {
                        continue;
                    }

                    var           dist = Vector2.Distance(moveEdge.P0, p);
                    var           otherIntersectionEdge = otherEdgeMapping[edge];
                    CollisionEdge thisIntersectionEdge;
                    if (otherIntersectionEdge.IsBottom() || otherIntersectionEdge.IsTop())
                    {
                        var top    = this.R1.TopEdge;
                        var bottom = this.R1.BottomEdge;
                        thisIntersectionEdge = p.Distance(top) < p.Distance(bottom) ? CollisionEdge.Top : CollisionEdge.Bottom;
                    }
                    else
                    {
                        var left  = this.R1.TopEdge;
                        var right = this.R1.BottomEdge;
                        thisIntersectionEdge = p.Distance(left) < p.Distance(right) ? CollisionEdge.Left : CollisionEdge.Right;
                    }

                    intersections.Add(new IntersectionPoint(dist, thisIntersectionEdge, otherIntersectionEdge));
                }
            }

            intersections = intersections.OrderBy(t => t.Distance).ToList();

            if (intersections.Any())
            {
                var min = intersections.First();
                thisEdge  = min.ThisEdge;
                otherEdge = min.OtherEdge;
                if (thisEdge == CollisionEdge.Bottom && otherEdge == CollisionEdge.Bottom && MathUtils.AreEqual(32, other.R0.Height))
                {
                }
            }

            return(new Tuple <CollisionEdge, CollisionEdge>(thisEdge, otherEdge));
        }