gpt4 book ai didi

Python pygame如何设置FPS

转载 作者:太空宇宙 更新时间:2023-11-04 01:45:11 26 4
gpt4 key购买 nike

我正在制作 python 游戏,但我不知道应该将 FPS 设置为多少。我的游戏卡住了,不流畅。我怎么知道 FPS 应该是多少?

这是我的代码:

http://bin.shortbin.eu:8080/x87bSUKUiN

最佳答案

运行您的代码后,我还注意到帧速率下降,这会影响游戏的流畅度。

这里有两个不同的问题:

<强>1。 FPS 下降

FPS 下降的原因可能是您无法控制的,例如垃圾收集器的工作。即使您无法控制此类问题,您通常也可以提高游戏的性能。请参阅以下游戏分析器运行的屏幕截图: Profiler results

可以看到大部分时间花在了blit上。然而,很大一部分时间也花在了 get_y_list 上。 get_y_list 方法还使用大型列表,这会为垃圾收集器稍后收集产生大量垃圾,从而进一步影响性能。

据我了解,get_y_list 方法是您用于碰撞检测的一种非常粗略的方法的一部分,该方法基本上需要二次方时间。您的算法似乎将每个对象划分为大量的二维单元格,然后测试每对单元格之间的碰撞。相反,您可以只测试框与框的交集。如果您希望对象具有复杂的碰撞形状,您可以使用其他算法,互联网上有很多这样的算法。例如:https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

使用其他算法进行碰撞检测将大大提高您的性能。

<强>2。当 FPS 下降时,游戏变得不流畅。

对象的 xy 位置正在更新,例如:player.x -= player.vx。物理上正确的方法是:player.x -= player.vx * DELTA_T。其中 DELTA_T 是自上一帧以来耗时。如果您不使用自上一帧以来耗时,则角色的运动速度将取决于 FPS。这正是我们所看到的。

您可能会问,我从哪里得到 DELTA_T。你在调用 tick 时直接执行:

def main():
global DELTA_T

finish = False
background_x = 0
background_y = 0
background = pygame.image.load(BACKGROUND_IAMGE)

while not finish:
DELTA_T = clock.tick(REFRESH_RATE)

我尝试用 DELTA_T 进行乘法运算,但游戏变得不稳定,因为您假设对象在每一帧中精确地前进 vx 个“单元格”以检测碰撞和地板穿透.请参阅下面的尝试:

import pygame

pygame.init()
WINDOW_WIDTH = 700
WINDOW_HEIGHT = 500
SIZE = (WINDOW_WIDTH, WINDOW_HEIGHT)
SCREEN = pygame.display.set_mode(SIZE)
pygame.display.set_caption("Python Game")
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PINK = (255, 0, 255)
BACKGROUND_IAMGE = 'back.png'
clock = pygame.time.Clock()
REFRESH_RATE = 30
FRAMES_DELAY = 3

PLAYER_HEIGHT = 72
PLAYER_WIDTH = 40

MUSHROOM_HEIGHT = 31
MUSHROOM_WIDTH = 40

BLOCK_HEIGHT = 30
BLOCK_WIDTH = 30

FLOOR_Y = 435

DELTA_T = 0

class Player:
def __init__(self, x, y):
self.__images = [pygame.image.load('mario1.png'), pygame.image.load('mario2.png'),
pygame.image.load('mario3.png'), pygame.image.load('mario4.png'),
pygame.image.load('mario5.png'), pygame.image.load('mario6.png')]
self.__current_image = self.__images[0]
self.x = x
self.y = y
self.vx = 5/33.
self.vy = 10/33.
self.__is_mid_air = False
self.__direction = "right"
self.__is_jumping = False
self.__MAX_JUMP = 20
self.__is_walking = False
self.__counter = 0
self.__jump_counter = 0

def reset_jump_counter(self):
self.__jump_counter = 0

def get_bottom_y(self):
return int(self.y + PLAYER_HEIGHT)

def set_walk(self, bol):
self.__is_walking = bol

def set_is_mid_air(self, bol):
self.__is_mid_air = bol

def is_mid_air(self):
return self.__is_mid_air

def get_image(self):
if self.__is_mid_air and self.__direction == "right":
self.__current_image = self.__images[4]
return self.__current_image

if self.__is_mid_air and self.__direction == "left":
self.__current_image = self.__images[5]
return self.__current_image

self.__counter += 1
if self.__counter > FRAMES_DELAY:
self.__counter = 0

if self.__counter == FRAMES_DELAY and self.__direction == "right":
if self.__is_walking and self.__current_image == self.__images[0]:
self.__current_image = self.__images[1]
else:
self.__current_image = self.__images[0]

if self.__counter == FRAMES_DELAY and self.__direction == "left":
if self.__is_walking and self.__current_image == self.__images[2]:
self.__current_image = self.__images[3]
else:
self.__current_image = self.__images[2]

return self.__current_image

def stand_still(self):
if self.__direction == "right":
self.__current_image = self.__images[0]
if self.__direction == "left":
self.__current_image = self.__images[2]

def set_jump(self, bol):
self.__is_jumping = bol
if not bol:
self.reset_jump_counter()

def check_jump(self):
if self.__jump_counter != self.__MAX_JUMP and self.__is_jumping:
self.y -= self.vy * DELTA_T
self.__jump_counter += 1
if self.__jump_counter >= self.__MAX_JUMP:
self.__is_jumping = False
self.__jump_counter = 0

def is_jumping(self):
return self.__is_jumping

def fall(self):
if not self.__is_jumping:
self.y += self.vy * DELTA_T

def get_direction(self):
return self.__direction

def turn_around(self):
if self.__direction == "right":
self.__direction = "left"
elif self.__direction == "left":
self.__direction = "right"

def get_x_list(self):
result = []
for i in range(PLAYER_WIDTH + 1):
result.append(self.x + i)
return result

def get_y_list(self):
result = []
for i in range(PLAYER_HEIGHT + 1):
result.append(self.y + i)
return result

def get_right_x(self):
return self.x + PLAYER_WIDTH

def is_crash(self, obj):
is_x_equals = False
for i in range(int(self.vx * DELTA_T+0.5)):
if self.x + PLAYER_WIDTH + i in obj.get_x_list():
is_x_equals = True
if self.x - i in obj.get_x_list():
is_x_equals = True

is_y_equals = False
for i in range(int(self.vy*DELTA_T+0.5)):
if self.y + PLAYER_HEIGHT + i in obj.get_y_list():
is_y_equals = True
if self.y - i in obj.get_y_list():
is_y_equals = True

return is_x_equals and is_y_equals

class Monster:
def __init__(self, x, y, vx, vy, monster_type):
self.__images = [pygame.image.load(monster_type + '1.png').convert(),
pygame.image.load(monster_type + '2.png').convert()]
if monster_type == "mushroom":
self.__width = MUSHROOM_WIDTH
self.__height = MUSHROOM_HEIGHT

self.__current_image = self.__images[0]
self.__FIRST_X = x
self.__FIRST_Y = y
self.__x = x
self.__y = y
self.__vx = vx
self.__vy = vy
self.__direction = "left"
self.__monster_type = monster_type
self.__counter = 0

def get_image(self):
self.__counter += 1
if self.__counter > FRAMES_DELAY:
self.__counter = 0

if self.__monster_type == "mushroom" and self.__counter == FRAMES_DELAY:
if self.__current_image == self.__images[1]:
self.__current_image = self.__images[0]
self.__current_image.set_colorkey(PINK)
else:
self.__current_image = self.__images[1]
self.__current_image.set_colorkey(PINK)
return self.__current_image
elif self.__monster_type == "mushroom" and self.__counter != FRAMES_DELAY:
self.__current_image.set_colorkey(PINK)
return self.__current_image

def get_x(self):
return self.__x

def get_vx(self):
return self.__vx

def get_vy(self):
return self.__vx

def get_y(self):
return self.__y

def step(self):
if self.__direction == "right":
self.__x += self.__vx * DELTA_T
elif self.__direction == "left":
self.__x -= self.__vx * DELTA_T

def get_direction(self):
return self.__direction

def turn_around(self):
if self.__direction == "right":
self.__direction = "left"
elif self.__direction == "left":
self.__direction = "right"

def get_x_list(self):
result = []
for i in range(MUSHROOM_WIDTH + 1):
result.append(self.__x + i)
return result

def get_y_list(self):
result = []
for i in range(MUSHROOM_HEIGHT + 1):
result.append(self.__y + i)
return result

def is_crash(self, obj):
is_x_equals = False
for i in range(int(self.__vx * DELTA_T+0.5)):
if self.__x + self.__width + i in obj.get_x_list():
is_x_equals = True
if self.__x - i in obj.get_x_list():
is_x_equals = True

is_y_equals = False
for i in range(int(self.__vy * DELTA_T+0.5)):
if self.__y + self.__height + i in obj.get_y_list():
is_y_equals = True
if self.__y - i in obj.get_y_list():
is_y_equals = True

return is_x_equals and is_y_equals

class Block:
def __init__(self, x, y, width=1, height=1):
self.__image = pygame.image.load("block.png")
self.__x = x
self.__y = y
self.__width = width
self.__height = height

def load_image(self, background_x):
for i in range(self.__width):
for j in range(self.__height):
SCREEN.blit(self.__image, (self.__x + (i * BLOCK_WIDTH) + background_x, self.__y + (j * BLOCK_HEIGHT)))

def get_x_list(self):
result = []
for i in range(BLOCK_WIDTH * self.__width + 1):
result.append(self.__x + i)
return result

def get_y_list(self):
result = []
for i in range(BLOCK_HEIGHT * self.__height + 1):
result.append(self.__y + i)
return result

def get_y(self):
return self.__y

def get_x(self):
return self.__x

def get_width(self):
return self.__width

def get_height(self):
return self.__height

def get_bottom_y(self):
return self.__y + (BLOCK_HEIGHT * self.__height)

def get_right_x(self):
return self.__x + self.__width * BLOCK_WIDTH

player = Player(140, FLOOR_Y - PLAYER_HEIGHT)
blocks = [Block(270, 280, 1, 1), Block(301, FLOOR_Y - BLOCK_HEIGHT * 8, 1, 8),
Block(600, FLOOR_Y - BLOCK_HEIGHT * 8, 2, 8)]
monsters = [Monster(380, FLOOR_Y - MUSHROOM_HEIGHT, 3/33., 3/33., "mushroom")]

def main():
global DELTA_T

finish = False
background_x = 0
background_y = 0
background = pygame.image.load(BACKGROUND_IAMGE)

while not finish:
DELTA_T = clock.tick(REFRESH_RATE)
SCREEN.blit(background, (background_x, background_y))
for event in pygame.event.get():
if event.type == pygame.QUIT:
finish = True

block_on_right = False
block_on_left = False
is_player_on_block = False
for block in blocks:
block.load_image(background_x)
for i in range(int(player.vy * DELTA_T+0.5)):
for x in player.get_x_list():
if player.get_bottom_y() + i == block.get_y() and x in block.get_x_list():
is_player_on_block = True
player.y += i
if player.y - i == block.get_bottom_y() and x in block.get_x_list():
player.set_jump(False)
player.y -= i

for i in range(int(player.vx*DELTA_T+0.5)):
for y in player.get_y_list():
if player.get_right_x() + i == block.get_x() and y in block.get_y_list():
block_on_right = True
player.x += (i - 1)
background_x -= (i - 1)
if player.x - i == block.get_right_x() and y in block.get_y_list():
block_on_left = True
player.x -= (i - 1)
background_x += (i - 1)
for monster in monsters:
if monster.is_crash(block):
monster.turn_around()

keys = pygame.key.get_pressed()

if (keys[pygame.K_UP] or keys[pygame.K_SPACE] or keys[pygame.K_w]) and not player.is_mid_air():
player.set_jump(True)

if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and not block_on_right:
if player.get_direction() != "right":
player.turn_around()
player.set_walk(True)

background_x -= player.vx * DELTA_T
player.x += player.vx * DELTA_T

if (keys[pygame.K_LEFT] or keys[pygame.K_a]) and not block_on_left:
if player.get_direction() != "left":
player.turn_around()
player.set_walk(True)

if background_x != 0:
background_x += player.vx * DELTA_T
player.x -= player.vx * DELTA_T

if not any(keys):
player.stand_still()
player.set_walk(False)

for monster in monsters:
monster.step()
SCREEN.blit(monster.get_image(), (background_x + monster.get_x(), monster.get_y()))

is_player_on_ground = False
for i in range(int(player.vy * DELTA_T+0.5)):
if player.get_bottom_y() + i == FLOOR_Y:
player.y += i
is_player_on_ground = True

if is_player_on_block or is_player_on_ground:
player.set_is_mid_air(False)
else:
player.set_is_mid_air(True)
player.fall()

player.check_jump()

player_image = player.get_image().convert()
player_image.set_colorkey(PINK)

SCREEN.blit(player_image, (player.x + background_x, player.y))
pygame.display.flip()

pygame.quit()

if __name__ == '__main__':
main()

关于Python pygame如何设置FPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59227239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com