尝试仅更新可见精灵时使用 pygame 的工件

问题描述 投票:0回答:1

我正在学习 pygame 库的基础知识,但已经很困难了。此时的“游戏”只有玩家和墙壁。有 2 个主要表面:“世界”(实际的游戏地图)和“屏幕”(用作“view_src”的视口,具有缩放和滚动功能,“视口”是相应的矩形)。

问题是:我想至少实现基本的优化,并且只渲染实际可见的精灵,因此我将“所有”组过滤为与视口发生碰撞的任何内容。这正如预期的那样。但是当我在“可见”临时组上调用渲染函数时,我会得到伪影,而在“所有”上调用它们则效果很好。

这是游戏循环中的相关片段:

        # clear old sprites
        all.clear(world, background) # this should clear the OLD position of all sprites, right?


        # handle input and generic game logic here
        if player.move(key_state, walls) != (0,0): # moves the player's rect if possible
            scroll_view(world, player.last_move, view_src) # shifts view_src if applicable


        # this does very little and should be unrelated to the issue
        all.update()


        # draw the new scene
        visible = pg.sprite.Group([ spr for spr in all.sprites() if view_src.colliderect(spr.rect) ])
        print(visible.sprites()) # confirms the visible sprites are chosen correctly
        visible.draw(world) # results in drawing each sprite in its new AND old position
        #all.draw(world) # acts as it should if used instead

        scaled = pg.transform.scale(world.subsurface(view_src), viewport.size)
        screen.blit(scaled, viewport.topleft)
        pg.display.flip()

(我在循环末尾执行 .empty() “可见”组)

即使我提前确定“可见”并调用

visible.clear(world, background)
,然后继续
all.draw(world)
,我也会遇到完全相同的问题,只有在“all”上同时调用 .clear() 和 .draw() 时,它才有效。这已经是在咨询了人工智能之后,人工智能告诉我这工作得很好,所以希望一个好的老式人类可以为我指明正确的方向。

python pygame game-development
1个回答
0
投票

在 Kingsley 的推动下找到了问题并解决了。

问题:

Group.clear() 清除由同一组的最后一个

.draw()
绘制的精灵。因此,为
.clear()
.draw()
使用不同的组是行不通的,并且每次重新分配“可见”组也会丢失其运行所需的连续性。

解决方案:

在循环之前初始化“visible”,在迭代之间保留它,并根据需要添加/删除精灵。

固定代码:

        # clear old sprites
        visible.clear(world, background) # this should clear the OLD position of all sprites, right?

        # handle input and generic game logic here
        if player.move(key_state, walls) != (0,0):
            scroll_view(world, player, view_src)

        # "step event", update positions etc here
        all.update()

        # draw the new scene
        visible.empty()
        visible.add([ spr for spr in all if view_src.colliderect(spr.rect) ])
        visible.draw(world)
        render_view(screen, world, view_src, viewport) # this is still what it was before
© www.soinside.com 2019 - 2024. All rights reserved.