public void ProcessCollisions() { // if here is in transactional state - get out if (!hero.CanCollide) { heroPrevBounds.Clear(); return; } colliders.Clear(); // tunneling prevention if (!heroPrevBounds.IsZero()) { // horizontal move { var d = hero.Bounds.X - heroPrevBounds.X; if (d != 0) { float n = (int)Math.Abs(d / MaxSingleMoveX); if (n > 1.0f) { var inc = MaxSingleMoveX * d / Math.Abs(d); for (int i = 0; i < n && colliders.Count == 0; i++) { heroPrevBounds.X += inc; FindCollisions(ref heroPrevBounds); } } } } // vertical move { var d = hero.Bounds.Y - heroPrevBounds.Y; if (d != 0) { float n = (int)Math.Abs(d / MaxSingleMoveY); if (n > 1.0f) { var inc = MaxSingleMoveY * d / Math.Abs(d); for (int i = 0; i < n && colliders.Count == 0; i++) { heroPrevBounds.Y += inc; FindCollisions(ref heroPrevBounds); } } } } } // find objects we collided with if (colliders.Count == 0) { FindCollisions(ref hero.Bounds); } heroPrevBounds = hero.Bounds; if (colliders.Count == 0) { return; } // sort them by the amounth of intersection (descending) colliders.Sort((t1, t2) => t2.Item3.CompareTo(t1.Item3)); for (int i = 0; i < colliders.Count; i++) { // process collision with the object if (colliders[i].Item1.ProcessCollision(this, colliders[i].Item2)) { // quit if collision was processed or go to the next object break; } } }