【问题标题】:Pygame Program Lagging With Multiple Sprites (~170)Pygame 程序滞后于多个精灵 (~170)
【发布时间】: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


【解决方案1】:

我正在开发 pygame,当您不使用 spritesheets 时,延迟很明显....尝试使用 spritesheets,这样您只需一次上传包含所有 sprites 的单个图像。

如果您的主角有 20 个不同的图像(帧),包括空闲、跑步、行走、跳跃、射击等,而您不使用 spritesheet,会发生什么情况?

Pygame 需要在每个循环中一张一张地上传所有这些图像,造成延迟。

相反,一个 spritesheet 是一个单一的图像,包含所有 sprite,每个 sprite 都有一个 (x,y,width,height),因此当需要特定 sprite 帧时 pygame 知道每个 sprite 的边界。

尝试并使用 spritesheets,它会让你的游戏运行流畅,更少的处理能力和更少的显卡使用等,更少的热量等。

100 张图片,每张重 100kb...很多,但单个 spritesheet 图片仅重 100kb....hmmm

如果您的游戏只有 5 个精灵,如果没有延迟,请使用图像,但如果您的游戏有更多并且存在延迟,请使用精灵表,它还有助于让您的工作更有条理,并且在您想要打包时起来,将其转换为 .exe 或其他文件,它的重量会更轻。

注意:我不久前发布了我的答案,但我只是想补充一点,当您加载图像时,请尝试在 init 方法中加载它们一次,并在更新方法中仅引用它们.不要在循环中“pygame.image.load(filename)”,它会滞后。

祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    相关资源
    最近更新 更多