I'm trying to do frame based movement. However I noticed when the window is held the fps increase momentarily and the player dissapeares. The value of dt, in my system, is between 1.06 and 0.96. Everything seems to work fine except when the window is held.
This video shows the problem. Lines 124 and 125 solves the problem, but as the commentary says i don't know if this is the correct way to fix it.
The problem seems to appear only on windows 10 systems.
import sys
import pygame
from pygame.locals import *
vec = pygame.math.Vector2
pygame.init()
fps = 60
fpsClock = pygame.time.Clock()
width, height = 1024, 768
TILESIZE = 32
screen = pygame.display.set_mode((width, height))
class Player(pygame.sprite.Sprite):
def __init__(self,x,y):
super().__init__()
self.image = pygame.Surface((TILESIZE, TILESIZE))
self.image.fill('green')
self.rect = self.image.get_rect(topleft=(x,y))
self.pos = vec(self.rect.topleft)
self.speed = .8
self.direction = vec(0,0)
self.gravity = .8
self.jump_height = -15
self.friction = -.12
self.velocity = vec(0,0)
self.acceleration = vec(0,self.gravity)
def update(self):
keys = pygame.key.get_pressed()
self.acceleration.x = 0
if keys[K_RIGHT]:
self.acceleration.x = self.speed
elif keys[K_LEFT]:
self.acceleration.x = -self.speed
if keys[K_UP]:
self.velocity.y = self.jump_height
class Obstacle(pygame.sprite.Sprite):
def __init__(self,pos,width,height,color):
super().__init__()
self.image = pygame.Surface((width,height))
self.image.fill(color)
self.rect = self.image.get_rect(topleft=pos)
tiles_map = [
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................",
"..P.............................",
"................................",
"................................",
"11111111111111111111111111111111",
"11111111111111111111111111111111"
]
class Game:
def __init__(self):
self.player_sprite = pygame.sprite.GroupSingle()
self.obstacles = pygame.sprite.Group()
for row,line in enumerate(tiles_map):
for col, char in enumerate(line):
if char == "1":
self.obstacles.add(Obstacle((col*TILESIZE,row*TILESIZE),TILESIZE,TILESIZE,'red'))
elif char == "P":
self.player_sprite.add(Player(col*TILESIZE,row*TILESIZE))
def horizontal_movement(self, dt):
player = self.player_sprite.sprite
# equations of motion
player.acceleration.x += player.velocity.x * player.friction
player.velocity.x += player.acceleration.x * dt
player.pos.x += player.velocity.x * dt + 0.5 * player.acceleration.x * dt **2
player.rect.x = round(player.pos.x)
def vertical_movement(self, dt):
player = self.player_sprite.sprite
# equations of motion
player.velocity.y += player.acceleration.y * dt
player.pos.y += player.velocity.y * dt + (player.acceleration.y * .5) * dt**2
player.rect.y = round(player.pos.y)
for obstacle in self.obstacles.sprites():
if obstacle.rect.colliderect(player.rect):
if player.velocity.y > 0: # falling
player.rect.bottom = obstacle.rect.top
player.pos.y = player.rect.y
player.velocity.y = 0
def update(self, dt):
self.player_sprite.update()
self.player_sprite.draw(screen)
self.obstacles.draw(screen)
self.horizontal_movement(dt)
self.vertical_movement(dt)
game = Game()
while True:
dt = fpsClock.tick(60) /1000 * fps # normalize
print(dt)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# if dt > 1.2: # it solves the problem but i don't know if this is the correct way to fix it
# dt = 1.2
screen.fill('white')
game.update(dt)
pygame.display.update()