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()
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)
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()
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)