1
votes

I am attempting to create a working jumping system in Pygame, but I'm having some issues with collision detection. I have a level stored in a list like this:

level = [
"WWWWWWWWWWWWWWWWWWWW",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"W                  W",
"WWWWWWWWWWWWWWWWWWWW",
 ]
x = y = 0
for row in level:
    for col in row:
        if col == "W":
             Wall((x, y))
        x += 32
    y += 32
    x = 0

Where each Wall is appended to a list and given a position based on its location in the grid.

This is the wall class:

class Wall (pygame.sprite.Sprite):
    def __init__(self,pos):
        pygame.sprite.Sprite.__init__(self)
        walls.append(self)
         self.rect = pygame.Rect(pos[0],pos[1],32,32)

I attempt to move the player rect 30 pixels up when the Up key is pressed and collision between the player and one of the tiles is detected:

if event.type == KEYDOWN and event.key == K_UP:
            if player.hitCheck():
                player.move(0,-30)

hitCheck(), a function of the Player class, looks like this:

def hitCheck(self):
    for wall in walls:
        if self.rect.colliderect(wall.rect):
            return True

However, the function never returns True, regardless of any actual collision. I am able to move the player rect without clipping through walls by setting the value of the colliding player-side to the value of the opposite wall-side in question, yet this yields no result.

Why isn't the function returning True on collision?

walls is declared as an empty list initially. It's used in the movement function which is part of the player class as such:

def move_single_axis(self, dx, dy):
    # Move the rect
    self.rect.x += dx
    self.rect.y += dy

    for wall in walls:
        if self.rect.colliderect(wall.rect):
            if dx > 0: # Moving right; Hit the left side of the wall
                self.rect.right = wall.rect.left
            if dx < 0: # Moving left; Hit the right side of the wall
                self.rect.left = wall.rect.right
            if dy > 0: # Moving down; Hit the top side of the wall
                self.rect.bottom = wall.rect.top
            if dy < 0: # Moving up; Hit the bottom side of the wall
                self.rect.top = wall.rect.bottom

This works without issue, which is why I'm having trouble understanding why hitCheck() can't detect collision.

2
In hitCheck, how come there is no return False as last statement? - Michel Keijzers
I removed it for the sake of the question as I'm only interested in figuring out why hitCheck won't return True. - Cowbolt
For the record, have you verified so that your walls actually are added to the wall list and that there isn't some kind of bug in the initialization code? - Dolda2000
Yes, the game renders and has functional movement apart from jumping. - Cowbolt

2 Answers

1
votes

Where are you declaring walls? Is it a global variable? Since walls is also part of the Sprites, you could use spritecollide instead of colliderect:

def hitCheck(self):
    if pygame.sprite.spritecollide(self, self.walls):
        return True
1
votes

Figured out the issue. The movement function automatically prevents collision, which is why it was never detected. Circumvented this by having a var turn True when self.rect.bottom was set to wall.rect.top.