Search code examples
pythonimagepygamecollision-detectionpygame-surface

Collisions using masks between two images only working at a certain point


I am trying to check a collision between one static, and one moving image. The static image is a balloon and the moving image is a gun. I've tried to create a function that gets the rect of the gun (using get_rect), checks if one of the (7) balloons (stored in a list) has the same x coordinate (x coordinate is randomly generated), and prints out which balloon it collided with. But it doesn't always seem to work, and only works in a certain position. Also, it prints out something like collision with [<Surface(444x250x32 SW)> when it should print the name (variable name) of which one of the balloons it hit.

Edit: Using Rabbid's suggestions, I've made a mask around both the balloon and the gun and tried checking those for the collision. They still don't work, but I feel like I am getting closer. I also made a repl, so you can run the code yourself. Here it is: Repl

enter image description here (When the gun is in the same position as the balloon, it should print out which balloon it hit.)

How can I check the collisions between these images properly, and print out which balloon was hit?


Solution

  • pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top left of the rectangle can be specified with the keyword argument topleft. e.g.:

    gun_rect = gun.get_rect(topleft = (x, y))
    

    Read How do I detect collision in pygame? and use pygame.Rect.collidepoint to detect the collision of the gun tip (gun_rect.topleft) with the enclosing rectangle of a balloon (ballon_rect):

    def check_collisions(x, y):
        for i in range(num_balloons):
            gun_rect = gun.get_rect(topleft = (x,y))
            ballon_rect = colors[i].get_rect(topleft = (balloon_list[i] - 100, y-90))
            if ballon_rect.collidepoint(gun_rect.topleft):
                print(f'collision with {colors[i]}')
    
    while running: # Game loop #
        # [...]
    
        check_collisions(x, y)
    
        # [...]
    

    Note, that the position of the balloon is (balloon_list[i] - 100, y-90), since you are drawing it at that position:

    def draw_balloons(y):
       for i in range(num_balloons):
           screen.blit(colors[i], (balloon_list[i] - 100, y-90))