Search code examples
pythonpygamespritecollision-detectionmask

Pygame mask for pixel perfect collision between player sprite and platform sprites


I am successfully detecting collisions between my player sprite and platform sprites using masks in pygame, but my issue is stopping the player from falling through a platform when jumping to it.

I tried solving the issue with mask.overlap(). Using this, I'm able to identify the point on my player sprite that has come into contact with the platform during a collision. When the bottom of the player sprite (her shoes) is colliding with a platform, she should stop falling. I can get this point from mask.overlap() and I hard-coded the y-coordinate of this point (which is a point on the sprite itself, not the screen) y = 155 in the program:

hits = pygame.sprite.spritecollide(player, platform_group, False)
if hits:
    hits = pygame.sprite.spritecollide(player, platform_group, False, pygame.sprite.collide_mask)
    for platform in hits:
        offset = (platform.rect.x - player.rect.x), (platform.rect.y - player.rect.y)
        if player.mask.overlap(platform.mask, offset):
            x = player.mask.overlap(platform.mask, offset)[0]
            y = player.mask.overlap(platform.mask, offset)[1]
            pygame.draw.circle(display, s.RED, (x + player.rect.x, y + player.rect.y), 2)
            print('Sprite pixel coll y: ' + str(y), 'Platform rect y top: ' + str(platform.rect.top))

        if y == 155:
            player.v_y = 0
            player.rect.y = platform.rect.y - y

The red dot is the point at which collision on the player sprite has been detected.

The problem with the current code (apart from it being a very ugly solution) is that it doesn't work for all cases. When the player falls too fast, the detected collision point will not be her feet (i.e. not when y = 155´) and she will fall through the platform since the if-condition will not be fulfilled. I could try a limit like if y >= 145 and y <= 160: but that still doesn't cover all cases and can cause her to "bounce" up when landing.

I'm currently stuck and wondering if anyone has any suggestions. I know I can use sprite Rects and go with colliderect but that will not give me the desired effect.

Thanks alot


Solution

  • you could check to see if the character is touching the platform ( using the mask.overlap method) and then set the velocity to 0 and gradually increase the y value until they are no longer colliding then continue with the rest of the game loop. (this is how I checked for collision but I used images instead of sprites) hope this helps.