Collision

Subscribe to Tech With Tim!

Player Hit-box

In the last tutorials we created a hit-box for our saw and our spike. However, we have yet to create one for our player. Since our player jumps and slides this will make things a bit more difficult.

We will need to modify the player draw() method to add hit-boxes:

```class player():
...
def draw(self, win):
if self.jumping:
self.y -= self.jumpList[self.jumpCount] * 1.3
win.blit(self.jump[self.jumpCount//18], (self.x,self.y))
self.jumpCount += 1
if self.jumpCount > 108:
self.jumpCount = 0
self.jumping = False
self.runCount = 0
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) # NEW
elif self.sliding or self.slideUp:
if self.slideCount < 20:
self.y += 1
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) # NEW
elif self.slideCount == 80:
self.y -= 19
self.sliding = False
self.slideUp = True
# NEW ELIF STATEMENT
elif self.slideCount > 20 and self.slideCount < 80: # NEW
self.hitbox = (self.x,self.y+3,self.width-8,self.height-35) # NEW

if self.slideCount >= 110:
self.slideCount = 0
self.runCount = 0
self.slideUp = False
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10) # NEW
win.blit(self.slide[self.slideCount//10], (self.x,self.y))
self.slideCount += 1

else:
if self.runCount > 42:
self.runCount = 0
win.blit(self.run[self.runCount//6], (self.x,self.y))
self.runCount += 1
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-13) # NEW

pygame.draw.rect(win, (255,0,0),self.hitbox, 2) # NEW - Draws hitbox
```

Player Falling

When the player collides with an object we want it to appear as though they are falling. To do this we need to again modify the player class. We will add a falling attribute and add a check in our draw method so that we can draw a different image if the player is falling.

```class player(object):
run = [pygame.image.load(os.path.join('images', str(x) + '.png')) for x in range(8,16)]
jump = [pygame.image.load(os.path.join('images', str(x) + '.png')) for x in range(1,8)]
jumpList = [1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4]
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
self.jumping = False
self.sliding = False
self.falling = False # NEW
self.slideCount = 0
self.jumpCount = 0
self.runCount = 0
self.slideUp = False

def draw(self, win):
if self.falling: # NEW
win.blit(self.fall, (self.x, self.y + 30)) # NEW

elif self.jumping:
self.y -= self.jumpList[self.jumpCount] * 1.3
win.blit(self.jump[self.jumpCount//18], (self.x,self.y))
self.jumpCount += 1
if self.jumpCount > 108:
self.jumpCount = 0
self.jumping = False
self.runCount = 0
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10)
elif self.sliding or self.slideUp:
if self.slideCount < 20:
self.y += 1
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10)
elif self.slideCount == 80:
self.y -= 19
self.sliding = False
self.slideUp = True
elif self.slideCount > 20 and self.slideCount < 80:
self.hitbox = (self.x,self.y+3,self.width-8,self.height-35)

if self.slideCount >= 110:
self.slideCount = 0
self.runCount = 0
self.slideUp = False
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-10)
win.blit(self.slide[self.slideCount//10], (self.x,self.y))
self.slideCount += 1

else:
if self.runCount > 42:
self.runCount = 0
win.blit(self.run[self.runCount//6], (self.x,self.y))
self.runCount += 1
self.hitbox = (self.x+ 4,self.y,self.width-24,self.height-13)

#pygame.draw.rect(win, (255,0,0),self.hitbox, 2)
```

Collision

Now that we have all of our hit-boxes setup we need to determine if objects have collided with one another. The first step to doing this is to add a method to both our saw and spike class called collide().

```class saw:
...
def collide(self, rect):
if rect[0] + rect[2] > self.hitbox[0] and rect[0] < self.hitbox[0] + self.hitbox[2]:
if rect[1] + rect[3] > self.hitbox[1]:
return True
return False
```

```class spike(saw):
...
def collide(self, rect):
if rect[0] + rect[2] > self.hitbox[0] and rect[0] < self.hitbox[0] + self.hitbox[2]:
if rect[1] < self.hitbox[3]:
return True
return False
```

Now that we have our collide methods completed we need to use them to check for collision with the player. We will do this from the game loop. Since we already have a for loop that moves each of our objects we will also check for collision in that loop.

```if obstacle.collide(runner.hitbox):
runner.falling = True

# This should go inside of the "for obstacle in obstacles" loop
```