我正在学习 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() 时,它才有效。这已经是在咨询了人工智能之后,人工智能告诉我这工作得很好,所以希望一个好的老式人类可以为我指明正确的方向。
在 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