Skip to content
Permalink
Browse files
Improved platform collision
Further improved player/platform collision but it's still a little buggy when jumping against a block on its side while having another one below
  • Loading branch information
dacostag committed Apr 29, 2020
1 parent b52c4db commit 7607ac804ab1778cef2e9a80736112396da3ced2
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 40 deletions.
Binary file not shown.
BIN +42 Bytes (100%) __pycache__/sprites.cpython-38.pyc
Binary file not shown.
66 main.py
@@ -6,6 +6,7 @@ from settings import *
from sprites import *
import os.path


# music: Licensed CC-BY. Attribute to Avgvst.
# https://opengameart.org/content/generic-8-bit-jrpg-soundtrack

@@ -64,31 +65,42 @@ class Game:
def update(self):
# Game loop - Update
self.all_sprites.update()
# check if player hits platform - only if falling
if self.player.vel.y > 0:
hits = pygame.sprite.spritecollide(self.player, self.platforms, False)
if hits:
lowest = hits[0]
for hit in hits:
if hit.rect.bottom > lowest.rect.bottom:
lowest = hit
#if self.player.pos.x < lowest.rect.right +20 and self.player.pos.x > lowest.rect.left + 20:
if self.player.pos.y < lowest.rect.centery:
self.player.pos.y = lowest.rect.top
self.player.vel.y = 0
self.player.jumping = False

# if player reaches 3/4 of width of the screen
if self.player.rect.x >= (width * 0.6):
# check if player hits platform
hits = pygame.sprite.spritecollide(self.player, self.platforms, False)
if hits:
lowest = max(hits, key=lambda x: x.rect.bottom)
highest = min(hits, key=lambda x: x.rect.bottom)
#print("Player pos top:", str(self.player.rect.left), "y", str(self.player.pos.x), "bottom",
#str(self.player.rect.right))
if self.player.pos.y < lowest.rect.centery - 5: # if falling on block - player remains on top of it
self.player.pos.y = lowest.rect.top
self.player.vel.y = 0
self.player.jumping = False
# if player hits block from the side
if self.player.rect.right > highest.rect.left or self.player.rect.left < highest.rect.right:
if self.player.pos.y > highest.rect.centery:
if self.player.rect.right > highest.rect.left:
self.player.pos.x = highest.rect.left - 18 # 18 is 1 pixel more then half the width of the player sprite
if self.player.rect.left < highest.rect.right:
self.player.pos.x = highest.rect.right + 18
self.player.vel.x = 0
self.player.vel.y = 2

if self.player.pos.y > lowest.rect.bottom: # if jumping from below - player hits his head on the platform
self.player.rect.top = lowest.rect.bottom + 5
self.player.vel.y = 0

# if player reaches 3/5 of width of the screen
if self.player.rect.right >= (width * 0.6):
self.player.pos.x -= abs(self.player.vel.x)
for plat in self.platforms:
plat.rect.x -= self.player.vel.x
plat.rect.x -= abs(self.player.vel.x)

# if player reaches 1/5 of the left side of the screen move screen
if self.player.rect.x <= (width * 0.2):
if self.player.rect.left <= (width * 0.2):
self.player.pos.x += abs(self.player.vel.x)
for plat in self.platforms:
plat.rect.x -= self.player.vel.x
plat.rect.x += abs(self.player.vel.x)

# Die, by falling of the screen
if self.player.rect.bottom > height + 60:
@@ -110,7 +122,7 @@ class Game:

def draw(self):
# Game loop - draw/render
self.screen.fill(BG_colour)
self.screen.fill((146, 244, 255))
self.all_sprites.draw(self.screen)
self.screen.blit(self.player.image, self.player.rect)
self.draw_text("Score: " + str(self.score), 26, (255, 255, 255), 40, 15)
@@ -122,10 +134,10 @@ class Game:
# game start screen
pygame.mixer.music.load(os.path.join(self.sound_dir, '01 - Opening.ogg'))
pygame.mixer.music.play(loops=-1)
self.screen.fill(BG_colour)
self.draw_text(title, 48, (255, 255, 255), width / 2, int(height / 4) + 50)
self.draw_text("Arrows to move, Z to shoot", 22, (255, 255, 255), width / 2, int(height / 2))
self.draw_text("Press a key to play", 22, (255, 255, 255), width / 2, int(height / 2) + 40)
self.screen.fill((209, 206, 29))
self.draw_text(title, 48, (255, 255, 255), width // 2, height // 4 + 50)
self.draw_text("Arrows to move, Z to shoot", 22, (255, 255, 255), width // 2, height // 2)
self.draw_text("Press a key to play", 22, (255, 255, 255), width // 2, height // 2 + 40)
pygame.display.flip()
self.wait_for_key()
pygame.mixer.music.fadeout(1000)
@@ -137,9 +149,9 @@ class Game:
if not self.running:
return
self.screen.fill(BG_colour)
self.draw_text("GAME OVER", 48, (255, 255, 255), width / 2, int(height / 4) + 50)
self.draw_text("Final Score: " + str(self.score), 22, (255, 255, 255), width / 2, int(height / 2))
self.draw_text("Press a key to play again", 22, (255, 255, 255), width / 2, int(height / 2) + 40)
self.draw_text("GAME OVER", 48, (255, 255, 255), width // 2, height // 4 + 50)
self.draw_text("Final Score: " + str(self.score), 22, (255, 255, 255), width / 2, height // 2)
self.draw_text("Press a key to play again", 22, (255, 255, 255), width // 2, height // 2 + 40)
pygame.display.flip()
self.wait_for_key()
pygame.mixer.music.fadeout(1000)
@@ -21,12 +21,17 @@ score_font = '8-BIT WONDER.ttf'
player_acc = 0.9
player_friction = -0.12
player_gravity = 1.2
player_jump = 15
player_jump = 17

# Starting platforms

# X Y
platform_list = [(0, 220),(35, 220), (70, 220), (105, 220),
(0, 425), (35, 425), (70, 425), (105, 425),
(800 / 2, 250), (365, 250), (330, 250), (295, 250),
(90, 125)]
platform_list = [(0, 220), (35, 220), (70, 220), (105, 220),
(90, 125)
]

main_floor = []

for i in range(0, 50):
main_floor.append((i * 35, height-35))
main_floor.append((i * 35, height-70))

@@ -64,6 +64,11 @@ class Player(pygame.sprite.Sprite):
self.jump_frame_l = pygame.transform.flip(self.jump_frame_r, True, False)
self.jump_frame_l.set_colorkey((0, 0, 0))

def jump_cut(self):
if self.jumping:
if self.vel.y < -3:
self.vel.y = -3

def jump(self):
# jump only if standing on a platform
self.rect.y += 2
@@ -74,12 +79,6 @@ class Player(pygame.sprite.Sprite):
self.jumping = True
self.vel.y = -player_jump


def jump_cut(self):
if self.jumping:
if self.vel.y < -3:
self.vel.y = -3

def update(self):
self.animate()
self.acc = vec(0, player_gravity)
@@ -97,14 +96,15 @@ class Player(pygame.sprite.Sprite):
self.vel.x = 0
self.pos += self.vel + 0.5 * self.acc

self.rect.midbottom = self.pos
self.rect.midbottom = self.pos # why is it recognized as a typo??

def animate(self):
now = pygame.time.get_ticks()
if self.vel.x != 0:
self.walking = True
else:
self.walking = False
# show walking animation
if self.walking:
if (now - self.last_update) > 100:
self.last_update = now
@@ -116,6 +116,7 @@ class Player(pygame.sprite.Sprite):
self.image = self.walk_frames_l[self.current_frame]
self.rect = self.image.get_rect()
self.rect.bottom = bottom
# show idle animation
if not self.jumping and not self.walking:
if (now - self.last_update) > 400:
self.last_update = now
@@ -128,6 +129,7 @@ class Player(pygame.sprite.Sprite):

class Platform(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites, game.platforms
pygame.sprite.Sprite.__init__(self)
self.game = game
images = [self.game.spritesheet2.get_image(576, 792, 70, 70),

0 comments on commit 7607ac8

Please sign in to comment.