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)] slide = [pygame.image.load(os.path.join('images', 'S1.png')),pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')),pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S2.png')), pygame.image.load(os.path.join('images', 'S3.png')), pygame.image.load(os.path.join('images', 'S4.png')), pygame.image.load(os.path.join('images', 'S5.png'))] fall = pygame.image.load(os.path.join('images','0.png')) # NEW 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