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); } }
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); }
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))); }
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)); }
public bool DoesNotIntersect(CollisionModel other) { return(!this.Intersects(other)); }
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)); }