按住 window 时玩家消失
player dissapear when the window is held
我正在尝试进行基于帧的移动。但是我注意到,当 window 被按住时,fps 会暂时增加并且玩家会消失。在我的系统中,dt
的值介于 1.06 和 0.96 之间。一切似乎都正常,除非 window 被按住。
This video shows the problem。第 124 和 125 行解决了问题,但正如评论所说,我不知道这是否是解决问题的正确方法。
该问题似乎只出现在 windows 10 个系统上。
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()
pygame.time.Clock.tick
returns how many milliseconds have passed since the previous call. The problem with your code is that the first time returned is very large. This is the time from the creation of the pygame.time.Clock
object to the first call of tick
。 game = Game()
需要很长时间。
在应用程序循环之前创建 pygame.time.Clock
以解决问题:
game = Game()
fpsClock = pygame.time.Clock()
while True:
dt = fpsClock.tick(fps) / 1000 * fps
# [...]
如果 2 帧之间的时间太长 dt
太大,加速度太大,您的算法就会崩溃。如果只有一个“慢”帧,重力会变得太大,玩家会无处可去。解决这个问题的唯一方法是限制 dt
:
while True:
dt = fpsClock.tick(60) / 1000 * fps
dt = min(dt, 1.5)
# [...]
我正在尝试进行基于帧的移动。但是我注意到,当 window 被按住时,fps 会暂时增加并且玩家会消失。在我的系统中,dt
的值介于 1.06 和 0.96 之间。一切似乎都正常,除非 window 被按住。
This video shows the problem。第 124 和 125 行解决了问题,但正如评论所说,我不知道这是否是解决问题的正确方法。
该问题似乎只出现在 windows 10 个系统上。
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()
pygame.time.Clock.tick
returns how many milliseconds have passed since the previous call. The problem with your code is that the first time returned is very large. This is the time from the creation of the pygame.time.Clock
object to the first call of tick
。 game = Game()
需要很长时间。
在应用程序循环之前创建 pygame.time.Clock
以解决问题:
game = Game()
fpsClock = pygame.time.Clock()
while True:
dt = fpsClock.tick(fps) / 1000 * fps
# [...]
如果 2 帧之间的时间太长 dt
太大,加速度太大,您的算法就会崩溃。如果只有一个“慢”帧,重力会变得太大,玩家会无处可去。解决这个问题的唯一方法是限制 dt
:
while True:
dt = fpsClock.tick(60) / 1000 * fps
dt = min(dt, 1.5)
# [...]