1
\$\begingroup\$

Currently making a maze game. Maze is drawn, everything is drawn with pygame.draw.rect. I have tried using pygame.coliderect() to check for colisions, but it isn't working. The current error message I keep receiving says that my player rectangle (drawn with a class called Sprite) has no attribute 'colliderect'

The code below shows how I am currently drawing the maze and character, and how I am attempting to call colliderect. Please explain to me what it is I am doing wrong or why this code isn't working.

# Hit variable to tell if the player is touching the wall#
hit = False
#Draw command for moving box set to Sprite#
class Sprite:
    def __init__(self,x,y,width,height):

        self.x=x

        self.y=y

        self.width=15

        self.height=15
#Used to draw the character to the screen
    def render(self):
        pygame.draw.rect(screen,YELLOW,(self.x,self.y,self.width,self.height))
sprite1 = Sprite(30,40,15,15)

moveX,moveY=0,0
#Create the Maze
class Maze: #Maze class to make maze creation and editing easier
    def __init__(self):
       self.W = 20 #Sets the width of the map
       self.H = 10 # Sets the heigth of the map
#Create a series of 1s and 0s to indicate where there is and isn't a wall.
#0 means nothing is there or the space is 0pen (pun intended)
#1 means something is there or no 1 shall pass.
       self.maze = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                     1,0,0,1,0,0,1,1,0,0,0,1,0,0,1,0,0,1,0,1,
                     1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,
                     1,1,0,1,1,1,1,1,1,0,0,1,0,1,0,1,0,0,1,1,
                     1,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,
                     1,0,0,1,0,1,1,1,1,0,0,0,0,1,0,1,0,0,0,1,
                     1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,
                     1,1,1,0,1,1,0,1,1,0,0,0,1,1,1,1,1,1,0,1,
                     1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,
                     0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1]

    def draw(self):
        bx = 0 #Used to loop horizontally through the 1s and 0s as the game draws
        by = 0 #Used to loope vertically through the 1s and 0s as the game draws
        self.surface = screen
        self.color = BLUE
        for i in range(0, self.W*self.H):
            if self.maze[ bx + (by*self.W) ] == 1:
                pygame.draw.rect(self.surface, self.color, ( bx * 25, by * 25, 25, 25))

            bx = bx + 1
            if bx > self.W-1:
                bx = 0 
                by = by + 1
maze = Maze()
## check if the player is still in the maze##
    if sprite1.colliderect(maze):
        hit = True
    else:
        hit = False
##reverse player's movement if they hit the wall##
    if hit == True:
        moveX *= -1
        moveY *= -1

# --- Drawing code should go here
    screen.fill(BLACK)
    # First, clear the screen to black. Don't put other drawing commands
    # above this, or they will be erased with this command.
    maze.draw()
    sprite1.x += moveX
    sprite1.y += moveY
    sprite1.render()
    # --- Go ahead and update the screen with what we've drawn.
    pygame.display.flip()
\$\endgroup\$
  • \$\begingroup\$ The code below shows how I am currently drawing the maze and character, and how I am attempting to call colliderect. Please explain to me what it is I am doing wrong or why this code isn't working. .... maybe the problem that you has not set collider yet , if you already set collider , then the problem is at the code used to set the collider \$\endgroup\$ – user6668201 Jan 23 '17 at 8:46
  • \$\begingroup\$ how does one set collider? I thought that all drawn pygame.Rect objects have the Rect property so they work with the collideRect function. All of the code above shows everything I have for the collisions. The rest is player movement and declaring colors and such. \$\endgroup\$ – N.Huggett Jan 24 '17 at 1:11
  • 1
    \$\begingroup\$ not knowing how to set collider may be the whole issue I'm having. I thought that all .Rect objects just automatically work with pygame.ColldeRect \$\endgroup\$ – N.Huggett Jan 24 '17 at 1:12
  • \$\begingroup\$ Rect is shorten name from Rectangle , mean it used to create rectangle object , in some case it doesn't include collider \$\endgroup\$ – user6668201 Jan 25 '17 at 11:14
  • 1
    \$\begingroup\$ I understand rect is short for rectangle, which is why I am confused. Pygame.draw.rect creates rectangles and pygame.collideRect checks for collisions with rectangular objects. I don't understand why the rectangular objects that I am drawing are not working with the collide rect function \$\endgroup\$ – N.Huggett Jan 26 '17 at 7:22
2
\$\begingroup\$

So I think the main thing that you've confused here is rendering & game logic. Rendering a rectangle to the screen doesn't mean that collision checks will be performed against it. Instead, you need to specify a logic object for that which Pygame can use for collision detection. By default, no external class has the properties that are required for colliderect to work.

So, you want to add a pygame.Rect to your player class and make sure it's up-to-date. One way would be to get rid of the separate X, Y, width and height values and just use a rect instead. Or you could add a method that returns a rectangle representing the player sprite.

def get_rect(self):
    return pygame.Rect(self.x, self.y, self.width, self.height)

Now, you want to either call sprite1.get_rect().colliderect(a_rect) or sprite1.rect.colliderect(a_rect) depending on which approach you take.

This is also an issue with your Maze class. The simple and naive way to do this would be to iterate over all grid positions inside your maze and check collisions against all those tiles.

bx = 0 
by = 0 
for i in range(0, self.W * self.H):
    if self.maze[ bx + (by * self.W) ] == 1:

        rect = pygame.Rect(bx * 25, by * 25, 25, 25)

        if rect.colliderect(sprite1.get_rect()):
            pass  # Collision!

        bx = bx + 1
        if bx > self.W-1:
            bx = 0 
            by = by + 1

You probably want to look into only checking the grid items that the player is overlapping, but that's a different topic.

So, to sum it all up, your issue is that drawing something doesn't make the thing you drew collidable. You need pygame.Rect objects for that.

\$\endgroup\$
  • \$\begingroup\$ @ Tyyppi_77 Is there any way that I can send you all of my code? I understand what you are saying, that a .rect object drawn with draw.rect is not the same as an object that works with .collideRect. I added in the code that you suggested, but now the maze doesn't draw. It used to draw blue squares and now it only draws the movable player. \$\endgroup\$ – N.Huggett Jan 27 '17 at 0:13
  • \$\begingroup\$ Did you remove the drawing code? I don't want your whole code. The collision code above should replace your old collision check, not the draw loop. \$\endgroup\$ – Tyyppi_77 Jan 27 '17 at 5:40
  • \$\begingroup\$ I defined get_rect in the maze class after the draw method. I may need to review the placement of the definition. I then put the rest of the code that you typed up into the method that I already had (copy and pasted over it) I assume that bx = 0 by = 0 are still supposed to be indented into my draw method though. \$\endgroup\$ – N.Huggett Jan 27 '17 at 6:09
  • \$\begingroup\$ Well my code above doesn't touch rendering at all, as I said it should remain the same. Also I don't think you want to add a get_rect to the maze class. You want it for the sprite. In any case, fixing those issues is kinda a separate issue and doesn't have anything to do with your colliderect errors. \$\endgroup\$ – Tyyppi_77 Jan 27 '17 at 10:04
  • 1
    \$\begingroup\$ Right. I put get_rect in the sprite class but the rest of the code that you posted after explaining to call sprite1.get_rect().colliderect(a_rect) or sprite1.rect.colliderect(a_rect) was put into my Maze.draw. I assume that's where it goes because that is the only place in my code that uses bx = 0 and by = 0 \$\endgroup\$ – N.Huggett Jan 28 '17 at 7:13
0
\$\begingroup\$

N.Nugget, you are calling colliderect as sprite1. You will have to put it like this:

if pygame.sprite.collide_rect(sprite1, maze): hit = True else: hit = False

I hope it serves you well.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.