I am continuing to work on collision detection. It appears for the most part, everything I have implemented is working. When the game starts, the character is on the left side of the screen (plus a few pixels). If I hold down the left key so he is pushed against the wall, he doesn't go anywhere like is supposed to happen.
However, when I move the character to the right up to the first ledge something weird happens:
At first, he doesn't go through the ledge like he's supposed to:
But then, after holding down the right key for a while, he starts to creep into the ledge:
If I hold down the right key long enough, he ends up inside the ledge completely:
(can't post another pic, because I don't have enough rep)
There is no rhyme or reason as to how long it takes for him to creep forward. It seems to happen at random intervals.
Any clues as to what is happening? The weirdest thing to me is that it only happens when he is colliding with the left side of a "wall" and not the right side. I held down the left key on the left side of the map (the beginning) for quite a while and nothing happened, again like is supposed to happen.
Relevant code:
def col_ground(self, sprite, wall):
return self.walls[wall].collidepoint(sprite.feet.midbottom)
def col_left(self, sprite, wall):
return self.walls[wall].collidepoint(sprite.feet.midleft)
def col_right(self, sprite, wall):
return self.walls[wall].collidepoint(sprite.feet.midright)
def update(self, dt):
""" Tasks that occur over time should be handled here
"""
self.group.update(dt)
# sprite must have a rect called feet, and move_back method,
# otherwise this will fail
# TODO: this could probably be modified to handle anytime
# the sprite is just on the ground or hitting a corner instead
# of having seprate instances of where the sprite hits the right
# or left side of a wall
for sprite in self.group.sprites():
wall_collide = sprite.feet.collidelist(self.walls)
walls = sprite.feet.collidelistall(self.walls)
if wall_collide > -1:
# if the sprite hits the ground
if self.col_ground(sprite, wall_collide):
self.hero.jumping = False
sprite.move_back_y(dt)
# if the sprite's right side hits a wall
if self.col_left(sprite, wall_collide):
sprite.move_back_x(dt)
# if the sprite's left side hits a wall
if self.col_right(sprite, wall_collide):
sprite.move_back_x(dt)
# if the sprite is in a corner
if len(walls) == 2:
# if in a corner, keep him from going up or down (x, y)
if not self.walls[walls[1]].collidepoint(sprite.feet.topleft) and \
not self.walls[walls[0]].collidepoint(sprite.feet.topleft):
sprite.move_back_x(dt)
if not self.walls[walls[0]].collidepoint(sprite.feet.topright) and \
not self.walls[walls[1]].collidepoint(sprite.feet.topright):
sprite.move_back(dt)
If you need any more code snippets or explanation, please let me know.
Edit (movement functions):
def move_back_x(self, dt):
""" If called after an update, the sprite can move back
in the x
"""
self._position[0] = self._old_position[0]
self.rect.topleft = self._position
self.feet.midbottom = self.rect.midbottom
def move_back_y(self, dt):
""" If called after an update, the sprite can move back
in the y direction
"""
self._position[1] = self._old_position[1]
self.rect.topleft = self._position
self.feet.midbottom = self.rect.midbottom
def move_back(self, dt):
""" If called after an update, the sprite can move back
"""
self._position = self._old_position
self.rect.topleft = self._position
self.feet.midbottom = self.rect.midbottom