# Bounding box collision handling makes player glitch to the other side of the wall

The way I handle simple collision detection causes a really frequent and easy to reproduce glitch, which affects gameplay severely. Here's my code (Python 3.5):

 def move(self, _map):
self.col = False
for y in _map.actors:
for actor in y:
if actor[1]:
if not (((self.y + self.h) < (actor[1].y - self.cam.y)) or (self.y > ((actor[1].y - self.cam.y) + actor[1].h)) or (self.x > ((actor[1].x - self.cam.x) + actor[1].w)) or ((self.x + self.w) < (actor[1].x - self.cam.x))):
print(self.col)
self.col = True
if not self.col:
if self.directions[0]:
self.cam.y -= self.speed
if self.directions[1]:
self.cam.y += self.speed
if self.directions[2]:
self.cam.x -= self.speed
if self.directions[3]:
self.cam.x += self.speed
else:
if self.directions[0]:
self.cam.y += self.speed
if self.directions[1]:
self.cam.y -= self.speed
if self.directions[2]:
self.cam.x += self.speed
if self.directions[3]:
self.cam.x -= self.speed
if self.running:
self.speed = system.RUNNING_PLAYER_SPEED
else:
self.speed = system.NORMAL_PLAYER_SPEED
self.x = ((self.cam.w / 2) - (self.w / 2))
self.y = ((self.cam.h / 2) - (self.h / 2))


As you can see, I'm detecting collision against walls and whatever (Any actor in the map) in the player's "move" method. The logic is pretty straightforward, a basic bounding box collision test (I consider the position of the player relative to the camera, since the player is always in the center (It's the camera that moves)). If I just stop the player if there's a collision, the player gets stuck inside the wall, thus creating the necessity of "teleporting" the player to its former position, as you can see in this other question. The problem with that solution is that it leads to this glitch, which I need to illustrate in order to make myself clear.

In this first example, I'm going up (pressing W) towards the wall.

The collision works fine just pressing W, it gets teleported in the opposite direction at each collision. The problem is when I start pressing S (Down) at the same time. The player goes to the opposite direction, glitching up towards the other side of the wall, since the collision test always returns true when the player is "inside" the wall, just like this:

This would severely compromise the gameplay, since players would be able to play outside the boundaries of the map in multiplayer. How can I avoid this using bounding box collision or other method?

I've finally realized how to solve the problem perfectly. I came to the conclusion that it's not a matter of detecting the collision in the present, but rather a matter of foreseeing the collision in the future. It's a matter of time! Either you record the positions of the player and then teleport him to his past in the event of a collision instead of moving him in the opposite direction in the present, or you check for a possible collision in the future. It works perfectly! The player can't get stuck inside the wall, or glitch through it, because the player never gets there! So that's the answer, future viewers: Accurate collision detection is all about time! (Not considering pixel-perfect detection, of course. That's not always necessary).

def move(self, _map):
def check_collision(future_pos):
for y in _map.actors:
for actor in y:
if actor[1]:
if not (((self.y + self.h) < (actor[1].y - future_pos[1])) or (self.y > ((actor[1].y - future_pos[1]) + actor[1].h)) or (self.x > ((actor[1].x - future_pos[0]) + actor[1].w)) or ((self.x + self.w) < (actor[1].x - future_pos[0]))):
return True
return False
if self.directions[0] and not check_collision((self.cam.x, self.cam.y - self.speed)):
self.cam.y -= self.speed
if self.directions[1] and not check_collision((self.cam.x, self.cam.y + self.speed)):
self.cam.y += self.speed
if self.directions[2] and not check_collision((self.cam.x - self.speed, self.cam.y)):
self.cam.x -= self.speed
if self.directions[3] and not check_collision((self.cam.x + self.speed, self.cam.y)):
self.cam.x += self.speed
if self.running:
self.speed = system.RUNNING_PLAYER_SPEED
else:
self.speed = system.NORMAL_PLAYER_SPEED
self.x = ((self.cam.w / 2) - (self.w / 2))
self.y = ((self.cam.h / 2) - (self.h / 2))