【发布时间】:2018-04-27 19:17:39
【问题描述】:
首先,我事先在 stackoverflow 上研究过这个主题,但我想了解更多关于它的信息,所以我提出了一个新问题。
所以基本上,我一直在使用 Pygame 1.9.3,并且成功地制作了一个简单的带有图形的 2D 游戏。我正在使用 Sprite 类,因此我经常使用 Group() 方法。我使用 groupName.draw(screen) 将图形绘制到屏幕上。
我的游戏的一个组成部分是与地形交互的能力,例如移除图块和放置图块。每个图块都是绘制到屏幕上的块 Sprite Group 的一部分。
但是,随着块图块数量的增加,我的程序开始明显滞后。以下是我为解决这个问题所做的工作:
- 对我所有加载的图像都使用了 .convert_alpha()
- 只加载一次图片
- 更改目标 FPS(使用 60 atm)
- 更改我的程序,使 blockGroup.draw() 命令仅在环境变化时调用。基本上,如果环境发生变化,我会重新绘制块,截取我的窗口,然后对该图像进行 blit 处理,直到环境再次发生变化(正如预期的那样,这会导致截屏时出现延迟)
但是,我的游戏仍然滞后。
当然,如果我增加我的块精灵的大小(这意味着我在加载它们各自的图像时如何调整它们的大小),我最终可以放置更多块而不会出现延迟,直到以后发生,因为总共有更少的精灵,但这是不适合我想要完成的工作。
此外,我已经实现了 2 组与该地形交互的 NPC。因此,我的程序需要检查主游戏循环中的大量碰撞是可以理解的,但尽管如此,除非我添加了一个由约 30 个 NPC 组成的团队(我目前只与10 个 NPC,每队 5 个)。
当我的程序开始滞后时,我计算出精灵总数(将每组中的所有精灵相加)为 170。
所以,最后,我的问题是:如果我打算有一个程序同时使用多个精灵(多个精灵约为 170 个),那么 pygame 在速度方面是否根本不适合这项工作?
我相信我已经使用了良好的实施实践,例如在精灵被删除后从它们各自的组中删除它们以及上面的简短列表。
我有一个请求提供一些代码,所以这里有一些重要的部分,我已经包括在内。
主游戏循环:
# Main Game Loop
while gameRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameRunning = False
keys = pygame.key.get_pressed()
if keys[LEFT_KEY]:
player1.goLeft()
if keys[RIGHT_KEY]:
player1.goRight()
if keys[JUMP_KEY]:
player1.jump()
if keys[DOWN_KEY]:
player1.ducking = True
if keys[SPRINT_KEY] and player1.movementKeyPressed:
player1.startSprinting()
if keys[SHOW_SCORES_KEY]:
Screen.DISPLAY_SCORES = True
# KEYUP EVENT
elif event.type == pygame.KEYUP:
if event.key == LEFT_KEY or event.key == RIGHT_KEY or event.key == SPRINT_KEY:
player1.stopMovingX()
player1.isSprinting = False
if event.key == DOWN_KEY:
player1.ducking = False
if event.key == SHOW_SCORES_KEY:
Screen.DISPLAY_SCORES = False
# MOUSE
if event.type == pygame.MOUSEBUTTONDOWN:
# Left Click
if event.button == ATTACK_KEY:
player1.attack()
# Right Click
elif event.button == PLACE_BLOCK_KEY:
player1.requestToPlaceBlock()
# Clear the screen
Screen.gameScreen.fill(Colors.WHITE)
# Update Sprites
EntityLists.npcGroup.update()
EntityLists.redTeamGroup.update()
EntityLists.blackTeamGroup.update()
EntityLists.corpseGroup.update()
# Update Blocks
EntityLists.blockGroup.update()
#
print(len(EntityLists.blockGroup) + len(EntityLists.redTeamGroup) + len(EntityLists.blackTeamGroup) +
len(EntityLists.npcGroup) + len(EntityLists.wallGroup))
if Screen.takeScreenShot:
# Blit background first
Screen.gameScreen.blit(background, (0, 0))
# Draw blocks and wall next
EntityLists.wallGroup.draw(Screen.gameScreen)
EntityLists.blockGroup.draw(Screen.gameScreen)
# Next, take screenshot
pygame.image.save(Screen.gameScreen, "BACKGROUND_AND_BLOCKS.png")
backgroundAndBlocks = pygame.image.load('BACKGROUND_AND_BLOCKS.png')
# Reset variable
Screen.takeScreenShot = False
# Blit
Screen.gameScreen.blit(backgroundAndBlocks, (0, 0))
# Draw Entities
EntityLists.npcGroup.draw(Screen.gameScreen)
EntityLists.redTeamGroup.draw(Screen.gameScreen)
EntityLists.corpseGroup.draw(Screen.gameScreen)
EntityLists.blackTeamGroup.draw(Screen.gameScreen)
# Player names
Screen.drawNames()
# Draw Death Messages
Screen.displayDeathMessages()
# Draw scores if viable
if Screen.DISPLAY_SCORES:
Screen.displayScores()
# Update screen
pygame.display.flip()
# FPS
clock.tick(Screen.TARGET_FPS)
pygame.quit()
非常感谢您的宝贵时间。
【问题讨论】:
-
向我们展示代码,最好是 MCVE
-
@depperm 会尽力而为,一分钟
-
你会使用脏精灵吗?您是否对代码的不同方面(例如
time库,或者只是profile)进行计时以找出实际发生延迟的位置? -
@Martijn 直到现在我才听说过脏精灵。所以不,我不使用脏精灵。至于时间,不,但我确实将clock.tick() 用于我的FPS。我将尝试实现脏精灵,看看是否会有所作为。
-
@Martijn 那么我对脏精灵的理解正确吗?我做了以下事情:获取draw函数的返回值,然后调用pygame.display.update()传入return val作为参数
标签: python performance pygame