this is my first question in stackoverflow. I started learning python 3 months ago, and I'm building a platformer game using sprites. I had to isolate the problem, so I'm only posting the part where the issue is.
Whenever the square is landing on any platform, there is a detection of collision but the square actually goes through the platform approximately 10 pixels down (DURING the collision) and then it goes back up and it stabilizes on top of the platform.
You can SEE the effect better if you adjust the FPS to 2. How can I fix this? I remember building a previous game BUT without using acceleration in "x" axis (friction) and "y" axis (gravity), just fast&stop movements of the square (left/right/up/down) detecting collision and the square never went through the platfom...
Here is the isolated problem:
import pygame as pg
import random
WIDTH = 900
HEIGHT = 600
NAME = "square"
FPS = 60
green = (0, 150, 0)
white = (255, 255, 255)
black = (0, 0, 0)
class Platform(pg.sprite.Sprite):
def __init__(self, x, y, width, height, color):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((40, 40))
self.image.fill(black)
self.rect = self.image.get_rect()
self.rect.center = (WIDTH / 2, HEIGHT / 2)
self.posx = WIDTH / 2
self.posy = HEIGHT * 0.10
self.velx = 0
self.vely = 0
self.accx = 0
self.accy = 0
self.jumping = False
self.jump_go = False
def jump(self):
if self.jumping == False:
self.jumping = True
self.vely = -25
def update(self):
self.accx = 0 #FRICTION
self.accy = 1 #GRAVITY
keys = pg.key.get_pressed()
if keys[pg.K_RIGHT]:
self.accx = 1
if keys[pg.K_LEFT]:
self.accx = -1
if self.vely != 0:
self.jump_go = False
#MOVEMENT IN X:
self.accx = self.accx + (self.velx * (-0.10))
self.velx = self.velx + self.accx
self.posx = self.posx + self.velx
self.rect.x = self.posx
if abs(self.velx) < 0.5:
self.velx = 0
#MOVEMENT IN Y:
self.accy = self.accy + (self.vely * (-0.05))
self.vely = self.vely + self.accy
self.posy = self.posy + self.vely
self.rect.y = self.posy
#IF PLAYER FALLS TO EDGE OF SCREEN:
if self.posy > HEIGHT:
self.posy = 0
if self.posx < 0:
self.posx = WIDTH
if self.posx > WIDTH:
self.posx = 0
class Game:
def __init__(self):
pg.init()
pg.mixer.init()
pg.font.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
self.clock = pg.time.Clock()
self.running = True
def new(self):
self.all_sprites = pg.sprite.Group()
self.all_platforms = pg.sprite.Group()
for i in range(3):
self.platform = Platform(random.randint(0, WIDTH), random.randint(HEIGHT * .15,
HEIGHT - 25), random.randint(100, 300), 50, green)
self.all_platforms.add(self.platform)
self.all_sprites.add(self.platform)
self.player = Player()
self.all_sprites.add(self.player)
self.run()
def run(self):
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.eventos()
self.update()
self.draw()
def eventos(self):
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
if event.type == pg.KEYDOWN:
if self.player.jump_go:
if event.key == pg.K_a:
self.player.jump()
def update(self):
self.all_sprites.update()
# Check if player hit platfom:
if self.player.vely > 0:
hits = pg.sprite.spritecollide(self.player, self.all_platforms, False)
if hits:
for hit in hits:
if self.player.rect.top < hit.rect.top:
self.player.posy = hit.rect.top - self.player.rect.height
self.player.vely = 0
self.player.jumping = False
self.player.jump_go = True
def draw(self):
self.screen.fill(white)
self.all_sprites.draw(self.screen)
pg.display.flip()
g = Game()
while g.running:
g.new()
pg.quit()