I'm trying to detect the collision between two moving Rects in pygame

Question:

So I keep trying to detect two different moving rects in pygame colliding but its just constantly registering a collision. As in the console constantly print lose, but the enemy isn’t even touching the ball. The effect I want is just a simple game where the ball has to avoid the tack so that the ball doesn’t pop.

import pygame
import sys
import math
import random
pygame.init()



size = width, height = 800, 600
white = 255, 255, 255
red = 255, 0, 0
clock = pygame.time.Clock()

screen = pygame.display.set_mode(size)

character = pygame.image.load("intro_ball.gif")
charrect = character.get_rect()
x = 340
y = 480
enemy = pygame.image.load("ho.png")
enrect = enemy.get_rect()
ex = random.randint(0, 690)
ey = 0
lose = False




while 1:
     clock.tick(60)
     for event in pygame.event.get():
          if event.type == pygame.QUIT: sys.exit()


     if ey >= 600 and lose != True:
          ey = 0
          ex = random.randint(0, 690)

     collide = pygame.Rect.colliderect(charrect, enrect)


     if event.type == pygame.KEYDOWN:
          if event.key == pygame.K_RIGHT and x < 690:
          x += 4
     if event.key == pygame.K_LEFT and x > 0:
        x -= 4

     if collide:
        lose = True
     else: lose = False

     if lose == True: print("lose")




    ey += 2        
    screen.fill(white)
    screen.blit(enemy, (ex, ey))
    screen.blit(character, (x, y))
    pygame.display.update()
Asked By: FireFlower

||

Answers:

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 lelft of the rectangle can be specified with the keyword argument topleft. These keyword argument are applied to the attributes of the pygame.Rect before it is returned (see pygame.Rect for a full list of the keyword arguments):

while 1:
    # [...]

    charrect = character.get_rect(topleft = (x, y))
    enrect = enemy.get_rect(topleft = (ex, ey))
    collide = pygame.Rect.colliderect(charrect, enrect)

    # [...]

On the other hand you do not need the variables x, y, ex, ey at all. Use the features of the pygame.Rect objects.
Additionally read How can I make a sprite move when key is held down

Minimal example:

import pygame, sys, math, random
pygame.init()

size = width, height = 800, 600
white = 255, 255, 255
red = 255, 0, 0
clock = pygame.time.Clock()
screen = pygame.display.set_mode(size)

#character = pygame.image.load("intro_ball.gif")
character = pygame.Surface((20, 20))
character.fill((0, 255, 0))
charrect = character.get_rect(topleft = (340, 480))
#enemy = pygame.image.load("ho.png")
enemy = pygame.Surface((20, 20))
enemy.fill((255, 0, 0))
enrect = enemy.get_rect(topleft = (random.randint(0, 690), 0))
lose = False

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    
    keys = pygame.key.get_pressed()
    charrect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 4
    charrect.clamp_ip(screen.get_rect())

    enrect.y += 2     
    if enrect.y >= 600 and lose != True:
        enrect.y = 0
        enrect.x = random.randint(0, 690)

    collide = pygame.Rect.colliderect(charrect, enrect)
    if collide:
        lose = True
    else: 
        lose = False
    if lose == True: 
        print("lose")
   
    screen.fill(white)
    screen.blit(enemy, enrect)
    screen.blit(character, charrect)
    pygame.display.update()

pygame.quit()
exit()
Answered By: Rabbid76