For some reason, my collision is not working as intended. If I stand still my character will fall all the way down the world, but if I start running my character will jerk himself back up somehow. I'm not sure why this is happening because my collision code under def update(self): in main doesn't include the x velocity in any way.
import pygame as pg
from settings import *
from sprites import *
class Game:
def __init__(self):
# initialize game window, etc
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode(SCREEN)
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.spritesheet = Spritesheet(Mario)
self.running = True
def new(self):
# start a new game
self.all_sprites = pg.sprite.LayeredUpdates()
self.player = pg.sprite.Group()
self.platforms = pg.sprite.Group()
self.player = Player(self)
self.level()
self.run()
def run(self):
# Game Loop
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
# COLLISION CODE
def update(self):
# Game Loop - Update
self.all_sprites.update()
hits = pg.sprite.spritecollide(self.player, self.platforms, False)
if hits:
lowest = hits[0]
if self.player.pos.x < lowest.rect.right and self.player.pos.x > lowest.rect.left:
self.player.pos.y = lowest.rect.top
self.player.vel.y = 0
self.player.jumping = False
self.player.rect.midbottom = self.player.pos
# make left impossible to go to
if self.player.pos.x < 0 + self.player.rect.width / 2:
self.player.pos.x = 0 + self.player.rect.width / 2
# move screen
if self.player.pos.x > WIDTH / 2:
for platform in self.platforms:
platform.rect.x -= self.player.vel.x
if self.player.pos.x > WIDTH / 2:
self.player.pos.x -= self.player.vel.x
def events(self):
# Game Loop - events
for event in pg.event.get():
# check for closing window
if event.type == pg.QUIT:
self.playing = False
self.running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
self.player.jump()
if event.type == pg.KEYUP:
if event.key == pg.K_SPACE:
self.player.jump_cut()
def level(self):
self.levelsss = level
y=0
for row in self.levelsss:
x = 0
for col in row:
if col == "1":
block(self, x, y)
x += 1
y+= 1
def draw(self):
# Game Loop - draw
self.screen.fill(DEEP_SKY_BLUE)
self.all_sprites.draw(self.screen)
# *after* drawing everything, flip the display
pg.display.flip()
def show_start_screen(self):
# game splasrh/start screen
pass
def show_go_screen(self):
# game over/continue
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
This is my sprites.py
import pygame as pg
import random
from settings import *
vec = pg.math.Vector2
class Spritesheet:
# utility class for loading and parsing spritesheets
def __init__(self, filename):
self.spritesheet = pg.image.load(filename).convert_alpha()
def get_image(self, x, y, width, height):
image = pg.Surface((width, height))
image.blit(self.spritesheet, (0, 0), (x, y, width, height))
image = pg.transform.scale(image, (width * 3, height * 3))
return image
class Player(pg.sprite.Sprite):
def __init__(self, game):
self._layer = PLAYER_LAYER
self.groups = game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.jumping = False
self.walking = False
self.last_update = 0
self.frame_count = 0
self.load_images()
self.image = self.stationary_r[0]
self.stationary = 0
self.right = False
self.left = False
self.cImage = 0
self.fImage = 0
self.update_time = 125
self.rect = self.image.get_rect()
self.rect.center = (40, HEIGHT - 100)
self.pos = vec(70, HEIGHT - 64)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def update(self):
self.animates()
self.acc = vec(0, PLAYER_GRAVITY)
keys = pg.key.get_pressed()
if keys[pg.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_d]:
self.acc.x = PLAYER_ACC
# apply friction
self.acc.x += self.vel.x * PLAYER_FRICTION
# equations of motion
self.vel += self.acc
if abs(self.vel.x) < 0.11:
self.vel.x = 0
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
def load_images(self):
self.stationary_r = [self.game.spritesheet.get_image(211, 0, 14, 16)]
for frame in self.stationary_r:
frame.set_colorkey(BLACK)
self.stationary_l = []
for frame in self.stationary_r:
frame.set_colorkey(BLACK)
self.stationary_l.append(pg.transform.flip(frame, True, False))
self.running_r = [self.game.spritesheet.get_image(241, 0, 14, 16), self.game.spritesheet.get_image(272, 0, 14, 16), self.game.spritesheet.get_image(300, 0, 14, 16)]
for frame in self.running_r:
frame.set_colorkey(BLACK)
self.running_l = []
for frame in self.running_r:
frame.set_colorkey(BLACK)
self.running_l.append(pg.transform.flip(frame, True, False))
self.turn_r = [self.game.spritesheet.get_image(331, 0, 14, 16)]
for frame in self.turn_r:
frame.set_colorkey(BLACK)
self.turn_l = []
for frame in self.turn_r:
self.turn_l.append(pg.transform.flip(frame, True, False))
def animates(self):
now = pg.time.get_ticks()
if self.vel.x != 0.0:
self.walking = True
else:
self.walking = False
if self.walking:
if now - self.last_update > 150:
if now - self.last_update > self.update_time:
self.last_update = now
bottom = self.rect.bottom
self.frame_count += 1
if self.frame_count >= 3:
self.frame_count = 0
self.rect = self.image.get_rect()
# running left and right animations
if self.vel.x >= 0.1:
self.image = self.running_r[self.frame_count]
else:
self.image = self.running_l[self.frame_count]
# stationary animations
if self.vel.x <= 0.4 and self.vel.x >= 0:
self.image = self.stationary_r[0]
if self.vel.x <= 0 and self.vel.x >= -0.4:
self.image = self.stationary_l[0]
self.rect.bottom = bottom
def jump_cut(self):
if self.jumping:
if self.vel.y < 0:
self.vel.y *= 0.5
def jump(self):
# jump only if standing on a platform
self.rect.y += 5
hits = pg.sprite.spritecollide(self, self.game.platforms, False) # LOOK AT
self.rect.y -= 5
if hits and not self.jumping:
self.jumping = True
self.vel.y = -20
class block(pg.sprite.Sprite):
def __init__(self, game, x, y):
self._layer = PLATFORM_LAYER
self.groups = game.platforms, game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.image = pg.image.load("block.png").convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x*32
self.rect.y = y*32