0
\$\begingroup\$

I have a hero character with jumping physics that I am trying to figure out the collision detection for. Right now, the problem that I am running into is as soon as the character hits the floor (while I'm pressing left on the left side of the screen) the rect that it recognizes that it is colliding with is the ground. Which is to be expected.

However, based on the checks that I have,

for sprite in self.group.sprites():
        wall_collide = sprite.feet.collidelist(self.walls)
        if wall_collide > -1:
            print wall_collide
            if self.col_ground(sprite, wall_collide):
                self.hero.jumping = False
                sprite.move_back_y(dt)
            if self.col_left(sprite, wall_collide):
                sprite.move_back_x(dt)
            if self.col_right(sprite, wall_collide):
                sprite.move_back_x(dt)
            print ""

since the character is colliding with the ground, the check to see if the character's rect is inside the colliding rect fails for 2 reasons:

1: The current collision rect is the ground which the character is above, so the test fails

2: Because of #1, the character will keep moving left until it realizes it's colliding with the left side, at which point it will have already gone too far into the wall.

What's the best collision solution?

Note: the character starts to the right of the left wall, on the ground but isn't colliding with the ground since the start position is right above it. Also, I realize that my code is a bit jumbled and I'm not taking care of every sprite in the group. I'll fix that once I have this fixed.

I can provide more code/pictures if necessary

Edit:

More code

def col_ground(self, sprite, wall):
    if self.walls[wall].collidepoint(sprite.feet.midbottom):
        return True
    return False

def col_left(self, sprite, wall):
    if self.walls[wall].collidepoint(sprite.feet.midleft):
        return True
    return False
def col_right(self, sprite, wall): 
    if self.walls[wall].collidepoint(sprite.feet.midright):
    return True
return False
\$\endgroup\$
1
\$\begingroup\$

The collidelist() method returns an index of the first collision.

You could use the collidelistall() method which returns a list of indices that collide with the Rect. In that case, you could use the indices for your collision code instead of using 'self.col_*' since you already know they are colliding.

To solve your collision issue with going into the wall: in your move code, check if the next position will be inside the wall. You can do this by using the collidepoint() method. If it returns true, do not move the sprite in that direction and if returns false, you can continue moving.

EDIT: Upon seeing your collision code edit, I would recommend checking collisions with the whole sprite rather than cuts of it. Rather than

if self.walls[wall].collidepoint(sprite.feet.midleft):

you would do

if self.walls[wall].colliderect(sprite):
\$\endgroup\$
  • \$\begingroup\$ I ended up just using exactly what I already have, but adding a case where sprite.collidelistall(self.walls) returns a list of 2 (the sprite is colliding with two rects - the ground and a wall). And instead of just moving back the x or y positions, I moved back both. I would upvote your answer, but I don't have enough rep. Thanks for your help \$\endgroup\$ – David Sep 3 '16 at 12:38

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.