Ok let's take a shot here.

Two implementations. One naive and one complicated.

The following are methods of our Player class.

Naive implementation:

- Code: Select all
`def get_collision_direction_naive(self,other_sprite):`

"""A naive implementation to find direction of collision."""

check_dict = {"left" : other_sprite.rect.midleft,

"right" : other_sprite.rect.midright,

"top" : other_sprite.rect.midtop,

"bottom" : other_sprite.rect.midbottom}

for direction,test in check_dict.items():

if self.rect.collidepoint(test):

return direction

return False

This just tests if the middle edge points of the other sprite we are colliding with are contained within our sprite's rect. Limited, but could serve your needs depending on what those might be.

Finite difference of mask collisions implementation:

- Code: Select all
`def get_collision_direction(self,other_sprite):`

"""Find what side of an object the player is running into."""

dx = self.get_finite_difference(other_sprite,0,self.speed)

dy = self.get_finite_difference(other_sprite,1,self.speed)

if abs(dx) > abs(dy):

if dx > 0:

return "right"

else:

return "left"

else:

if dy > 0:

return "bottom"

else:

return "top"

def get_finite_difference(self,other_sprite,index,delta=1):

"""Find the finite difference in area of mask collision with the

rects position incremented and decremented in axis index."""

base_offset = [other_sprite.rect.x-self.rect.x,

other_sprite.rect.y-self.rect.y]

offset_high = base_offset[:]

offset_low = base_offset[:]

offset_high[index] += delta

offset_low[index] -= delta

first_term = self.mask.overlap_area(other_sprite.mask,offset_high)

second_term = self.mask.overlap_area(other_sprite.mask,offset_low)

return first_term - second_term

This is a little harder to explain. We check the collisions between our mask and the mask we collide with, incrementing and decrementing our position by delta. We do this separately for the X-axis and the Y-axis. Comparing the relative results from these calculations can tell us the direction of collision (it can actually tell us the exact angle of collision if we are not restricted to orthogonal movement).

I have added examples of each to the four_dir_movement section of my example repo:

Naive implementationFinite difference of mask collisions implementationGood luck.

-Mek

Edit:

Oh, another possibly easier (and potentially more accurate) naive implementation. On collision calculate the angle of the vector between the center of your rect and the center of the other rect. If it is between certain ranges (say -45 to 45 degrees) you can make assumptions about the angle between the sprites. I'll write one up later.