Search code examples
pythonpygamecollision-detectioncollision

Collision Detection Not Working - PyGame


I'm working in a game, and in this game an object falls from the top of the game screen and the player at the bottom of the screen has to hit the object falling. When the player hits the falling object, the player's width and height needs to increase. When I tested the code, the collision worked when the player hit the falling object from the side, but the collision didn't work when the player hit the falling object in the middle. Can someone help me?

PYTHON

# IMPORTS
import pygame, random

# GLOBALS
global screen, displayW, displayH
global clock, FPS
global end, food, player

# SETGLOBALVALUES
def setGlobalValues():
    global screen, displayW, displayH
    global clock, FPS
    global end, food, player

    displayW = 800
    displayH = 600
    screen = pygame.display.set_mode((displayW, displayH))

    clock = pygame.time.Clock()
    FPS = 60

    end = False
    food = Food()
    player = Player()

# MAIN
def main():
    pygame.init()

    setGlobalValues()
    setup()
    gameLoop()
    quitGame()

# GAMELOOP
def gameLoop():
    global end, player

    while not end:
        for event in pygame.event.get():
            # ONCLICK QUIT
            if event.type == pygame.QUIT:
                end = True;

            # KEYDOWN
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    player.velX -= 10
                if event.key == pygame.K_RIGHT:
                    player.velX += 10

            # KEYUP
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT:
                    player.velX = 0
                if event.key == pygame.K_RIGHT:
                    player.velX = 0

        draw()
        animate()
        collision()
        setFPS()


# DRAW
def draw():
    global screen, food, player

    # fill background
    screen.fill((255, 255, 255))

    player.draw()
    food.draw()

    # update
    pygame.display.update()

# ANIMATE
def animate():
    global food, player

    food.animate()
    player.animate()

# COLLISION
def collision():
    global player, food;

    player.collision()
    food.collision();

# SETFPS
def setFPS():
    global clock, FPS

    clock.tick(FPS);

# CLASSES
class Food():
    def __init__(self, img="", x=0, h=0, w=0, velY=0, color=()):
        global displayW

        self.img = pygame.image.load("assets/img/rsz_burger.png")
        self.w = 30
        self.h = 30
        self.x = random.randrange(0, displayW - self.w)
        self.y = -100
        self.velY = 3
        self.color = (255, 0, 0)

    def draw(self):
        global screen

        screen.blit(self.img, (self.x, self.y))

    def animate(self):
        self.y += self.velY

        if self.y >= displayW:
            self.reset()

    def collision(self):
        global displayW, displayH

        # collision with player
        if self.y >= player.y and self.y <= player.y + player.h and self.x >= player.x and self.x <= player.x + player.w:
            player.w += player.increase
            player.h += player.increase
            player.y - player.increase

            print(player.w)
            self.reset()

    def reset(self):
        self.y = -100
        self.x = random.randrange(0, displayW - self.w)
        self.velY += 1
        screen.blit(self.img, (self.x, self.y))

class Player():
    def __init__(self, x=0, y=0, velX=0, velY=0, w=0, h=0, increase=0, color=()):
        global displayW, displayH

        self.w = 20
        self.h = 20
        self.x = displayW / 2 - self.w / 2
        self.y = displayH - 100
        self.velX = 0
        self.velY = 0
        self.increase = 2
        self.color = (0, 0, 0)

    def draw(self):
        global screen

        pygame.draw.ellipse(screen, self.color, (self.x, self.y, self.w, self.h))

    def animate(self):
        self.x += self.velX
        self.y += self.velY

    def collision(self):
        global displayW

        # collision to walls
        if self.x <= 0:
            self.velX = 0
        elif self.x  + self.h >= displayW:
            self.velX = 0


# SETUP
def setup():
    pygame.display.set_caption("Food Catcher")

# QUIT GAME
def quitGame():
    pygame.quit()
    quit()

# CALL MAIN
if __name__ == "__main__":
    main()

Solution

  • The problem was that had to minus the player's width

    Before:

    if self.y >= player.y and self.y <= player.y + player.h and self.x >= player.x and self.x <= player.x + player.w:
                player.w += player.increase
                player.h += player.increase
                player.y - player.increase
    

    After:

    if self.y >= player.y - player.h and self.y <= player.y + player.h and self.x >= player.x - player.w and self.x <= player.x + player.w:
                player.w += player.increase
                player.h += player.increase
                player.y - player.increase
    

    I forgot that the objects x and y start at the top left.