0

I am creating a game where the player moves around a grid and dodges rocks, but my code for detecting collision doesn't seem to work.

import pygame from pygame.locals import * import random pygame.init() xSize = 500 ySize = 500 win = pygame.display.set_mode((xSize, ySize), RESIZABLE) pygame.display.set_caption('Grid Game: Featuring Sad Blue Circle') grid = pygame.image.load('gr.png').convert() clock = pygame.time.Clock() rockWait = 1000 rock_spawn_ev = pygame.USEREVENT class player(object): def __init__(self): self.right = [pygame.image.load('right_%s.png' % frame) for frame in range(1, 9)] self.x = 109 self.y = 109 self.frameCount = 0 self.rect = pygame.Rect(self.x, self.y, 32, 32) #rect for collision def draw(self, win): if self.frameCount + 1 >= 40: self.frameCount = 0 win.blit(self.right[self.frameCount//5], (self.x, self.y)) self.frameCount +=1 self.rect = pygame.Rect(self.x, self.y, 32, 32) #update rect position class rock(object): def __init__(self, vel): self.rock = pygame.image.load('rock.png') self.vel = vel self.ran = random.randint(0, 3) self.ran2 = random.randint(1, 10) * 50 - 41 if self.ran > 1: self.x = 550 self.y = 550 else: self.x = -50 self.y = -50 rocks.append(self) self.rect = pygame.Rect(self.x, self.y, 32, 32) #rect for collision def draw(self, win): if self.ran == 0: #top to bottom self.y += self.vel win.blit(self.rock, (self.ran2, self.y)) if self.ran == 2: #bottom to top self.y -= self.vel win.blit(self.rock, (self.ran2, self.y)) if self.ran == 1: #left to right self.x += self.vel win.blit(self.rock, (self.x, self.ran2)) if self.ran == 3: #right to left self.x -= self.vel win.blit(self.rock, (self.x, self.ran2)) self.rect = pygame.Rect(self.x, self.y, 32, 32) #update rect position def rgw(): win.blit (grid, (0,0)) player.draw(win) for rock in rocks: rock.draw(win) colliding = player.rect.colliderect(rock.rect) if colliding: print('collide') #nothing happens, even when touching rock pygame.display.update() pygame.time.set_timer(rock_spawn_ev, rockWait) player = player() rocks = [] run = True while run: clock.tick(60) events = pygame.event.get() for event in events: if event.type == pygame.QUIT: run = False if event.type == rock_spawn_ev: rock(6) if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP and player.y > 9: player.y -= 50 elif event.key == pygame.K_DOWN and player.y < ySize - 41: player.y += 50 elif event.key == pygame.K_LEFT and player.x > 9: player.x -= 50 elif event.key == pygame.K_RIGHT and player.x < xSize - 41: player.x += 50 rgw() pygame.quit() 

I think that colliding = player.rect.colliderect(rock.rect) should return True when touching a rock, but "collide" never gets printed, in this for loop:

for rock in rocks: rock.draw(win) colliding = player.rect.colliderect(rock.rect) if colliding: print('collide') #nothing happens, even when touching rock 

I know that the for loop itself works, because the rocks are being drawn

class player(object): def __init__(self): self.x = 109 self.y = 109 self.rect = pygame.Rect(self.x, self.y, 32, 32) #rect for collision def draw(self, win): self.rect = pygame.Rect(self.x, self.y, 32, 32) #update rect position class rock(object): def __init__(self): rocks.append(self) self.rect = pygame.Rect(self.x, self.y, 32, 32) #rect for collision def draw(self, win): self.rect = pygame.Rect(self.x, self.y, 32, 32) #update rect position player = player() rocks = [] def rgw(): win.blit (grid, (0,0)) player.draw(win) for rock in rocks: rock.draw(win) colliding = player.rect.colliderect(rock.rect) if colliding: print('collide') #nothing happens, even when touching rock pygame.display.update() 
4
  • Sorry if this is a silly question. I'm new to pygame. Commented Jun 18, 2020 at 22:34
  • 1
    It will help if you can make a minimal reproducible example. Commented Jun 18, 2020 at 22:36
  • @khelwood Ok, I made one Commented Jun 18, 2020 at 23:57
  • 1
    Your player image is 32x32 pixels right? Normally you set the rect off the image: self.rect = self.image.get_rect(). If the rect has an incorrect size, this could cause your issue. Maybe try drawing the collision rects too themselves (just the outline) when you paint the sprites. Commented Jun 19, 2020 at 2:33

1 Answer 1

2

First of all, there is no rock drawn at the position (self.x, self.y), but there are rocks drawn at the positions (self.ran2, self.y) and (self.x, self.ran2)


I recommend to create the rectangles which surround the objects from the corresponding pygame.Surface objects. Use get_rect() to generate a pygame.Rect object with the size of the image and set the position by keyword arguments (self.rect = self.rock.get_rect(topleft = (self.x, self.ran2))) or use the rectangle which is returned by pygame.Surface.blit. For instance:

class player(object): # [...] def draw(self, win): # [...] self.rect = win.blit(self.right[self.frameCount//5], (self.x, self.y)) 
class rock(object): # [...] def draw(self, win): # [...] self.rect = win.blit(self.rock, (self.x, self.ran2)) 

Since in the class rock are drawn 2 rocks at the positions (self.ran2, self.y) and (self.x, self.ran2), you have to set 2 different rectangle objects:

class rock(object): # [...] def draw(self, win): # [...] self.rect_1 = win.blit(self.rock, (self.ran2, self.y)) # [...] self.rect_2 = win.blit(self.rock, (self.x, self.ran2)) 

And you have to do 2 collision tests:

def rgw(): win.blit (grid, (0,0)) player.draw(win) for rock in rocks: rock.draw(win) colliding = player.rect.colliderect(rock_1.rect) or player.rect.colliderect(rock_2.rect) if colliding: print('collide') #nothing happens, even when touching rock pygame.display.update() 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.