I'm tearing my hair out trying to work out how to handle my collision resolution at the corners of the rectangles that I'm colliding with.
The code that I'm working with is:
class Player(object):
def move(self):
# Calculate velocity based on gravity, etc
# ...
# Check collisions
for obj in self.controller.collidable():
sides = self.get_intersect(obj)
if sides & TOP:
self.mover.vy = 0
self.mover.y = obj.coord.y + obj.size.y
elif sides & BOTTOM:
self.mover.vy = 0
self.mover.y = obj.coord.y - self.size.y
elif sides & LEFT:
self.mover.vx = 0
self.mover.x = obj.coord.x - self.size.x
elif sides & RIGHT:
self.mover.vx = 0
self.mover.x = obj.coord.x + obj.size.x
self.coord.x = self.mover.x
self.coord.y = self.mover.y
self.velocity.x = self.mover.vx
self.velocity.y = self.mover.vy
def is_intersecting(self, other):
return (
(
self.coord.x + self.size.x > other.coord.x
and
self.coord.x < other.coord.x + other.size.x
)
and
(
self.coord.y + self.size.y > other.coord.y
and
self.coord.y < other.coord.y + other.size.y
)
)
def get_intersect(self, other):
if not self.is_intersecting(other):
return 0
pos = 0
# Are we overlapping the bottom edge?
if self.coord.y < other.coord.y < (self.coord.y + self.size.y) > other.coord.y:
pos |= BOTTOM
# Are we overlapping the top edge?
if self.coord.y < (other.coord.y + other.size.y) < (self.coord.y + self.size.y):
pos |= TOP
# Are we overlapping the left edge?
if self.coord.x < other.coord.x < (self.coord.x + self.size.x):
pos |= LEFT
# Are we overlapping the right edge?
if self.coord.x < (other.coord.x + other.size.x) < (self.coord.x + self.size.x):
pos |= RIGHT
if pos == 0:
pos = INSIDE
return pos
The problem I'm experiencing is during vertical movement. If you push into a wall and jump, as you reach the top corner, it will push you vertically. This is due to the sides & TOP
being the first check. Moving the horizontal checks first fixes this when jumping up, but then falling onto a corner moves the player horizontally.
I've tried doing checking based on what the horizontal/vertical velocities are, but this falls apart, since the vertical velocity is always non-zero due to gravity (and is corrected by this check if standing on a platform). Any other answers I've found fail to take this into account.