Why won't my collision detection function work inside a class?

Question:

I have a collision detection function that works perfectly, but only if I put it in my game loop (lines 30 to 34). If I put it in a class as an attribute and then call it from within the game loop, it doesn’t work (lines 16 to 20). I’ve also removed the movement code for the player_2 instance of the class, as I don’t think that has anything to do with the problem. Any help is appreciated.

import pygame

pygame.init()

size = (500,500) #size[0] = width, size[1] = height
window = pygame.display.set_mode(size)
clock = pygame.time.Clock()

class Player:
  def __init__(self, x, y, width, height, speed):
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.speed = speed
    self.rect = pygame.Rect(x, y, width, height)

  def collide(self):
    if self.rect.colliderect(player_2.rect):
      print('hello')
    

player_1 = Player(200, 200, 70, 70, 5)
player_2 = Player(60, 60, 70, 70, 5)


loop = True
while loop == True:
  '''
  def collide():
    player_1_rect = pygame.Rect(player_1.x, player_1.y, player_1.width, player_1.height)
    player_2_rect = pygame.Rect(player_2.x, player_2.y, player_2.width, player_2.height)
    if player_1_rect.colliderect(player_2_rect):
      print('hello')
      '''


  def movement():
    keys = pygame.key.get_pressed()
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
        global loop
        loop = False

    if keys[pygame.K_a]:
      player_2.x -= player_2.speed
    if keys[pygame.K_d]:
      player_2.x += player_2.speed
    if keys[pygame.K_w]:
      player_2.y -= player_2.speed
    if keys[pygame.K_s]:
      player_2.y += player_2.speed

      
  window.fill((0, 0, 0))
  clock.tick(60)
  movement()
  pygame.draw.rect(window, (255, 0, 0), (player_1.x, player_1.y, player_1.width, player_1.height))
  pygame.draw.rect(window, (0, 0, 255), (player_2.x, player_2.y, player_2.width, player_2.height))
  player_1.collide()
  pygame.display.update()
Asked By: the popo

||

Answers:

The .rect attributes are used for collision detection. Therefore you have to update the rect attribute after moving the object or before the collision detection:

while loop == True:
    # [...]

    if keys[pygame.K_a]:
      player_2.x -= player_2.speed
    if keys[pygame.K_d]:
      player_2.x += player_2.speed
    if keys[pygame.K_w]:
      player_2.y -= player_2.speed
    if keys[pygame.K_s]:
      player_2.y += player_2.speed
    player_2.rect.topleft = player_2.x, player_2.y

However, you don’t need the x, y, width and height attributes at all. Use the rect attribute instead:

import pygame

pygame.init()
size = (500, 500) #size[0] = width, size[1] = height
window = pygame.display.set_mode(size)
clock = pygame.time.Clock()

class Player:
    def __init__(self, x, y, width, height, speed):
        self.speed = speed
        self.rect = pygame.Rect(x, y, width, height)

    def collide(self, opponent):
        if self.rect.colliderect(opponent.rect):
            print('hello')
    
player_1 = Player(200, 200, 70, 70, 5)
player_2 = Player(60, 60, 70, 70, 5)

def movement():
    keys = pygame.key.get_pressed()
    player_2.rect.x += (keys[pygame.K_d] - keys[pygame.K_a]) * player_2.speed
    player_2.rect.y += (keys[pygame.K_s] - keys[pygame.K_w]) * player_2.speed

loop = True
while loop == True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            loop = False
    
    movement()
    player_1.collide(player_2)
      
    window.fill((0, 0, 0))
    pygame.draw.rect(window, (255, 0, 0), player_1.rect)
    pygame.draw.rect(window, (0, 0, 255), player_2.rect)
    pygame.display.update()
    clock.tick(60)
Answered By: Rabbid76
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.