3

我对 Python/PyGame 中的定时事件有疑问。我正在制作一个 2D 横向滚动平台游戏,目标是接触所有敌人,在收集完所有敌人后,我希望将相机中心放在“出口块”上。

在相机以“退出块”为中心后,我想移除它周围的块,并将相机重新对准玩家。所以玩家可以看到周围的方块是如何被移除的,并且可以到达“退出方块”。

在收集完所有敌人后,我已经获得了以“退出块”为中心的代码,但是在移除周围的块之前,相机切换到了玩家。在相机以玩家为中心后,方块会被移除。

我在这里缺少关键部分。删除周围的块后,我尝试了 pygame.time.wait() 。有什么帮助吗?请告诉我我提供的代码是否不够。

编辑: 我已将我的主要游戏循环分解为:

level.handle_events(pygame.event.get())
level.update()
level.render(screen)
pygame.display.flip()

问题可能是,主循环处理 USEREVENT,然后更新相机并且仅在完成绘图之后,这就是为什么看不到周围块的移除?但我仍然不知道如何进行..

相关代码:

玩家的初始化

self.EXITBLOCKCLEAR = pygame.USEREVENT + 1

玩家的碰撞检测

for e in enemies_group:
    if pygame.sprite.collide_rect(self, e)
        if len(enemies_group) == 0:
           self.exit_block_reveal = True
           pygame.time.set_timer(self.EXITBLOCKCLEAR, 3000)

等级更新

if self.player.exit_block_reveal == False:
    self.camera.update(self.player)     # camera follows player
else:
    self.camera.update(self.exit_block) # camera centered on "exit block"

关卡的事件处理

if event.type == self.player.EXITBLOCKCLEAR:
    if self.player.exit_block_reveal == True:
        for block in self.disappearing_block_group:
            block.kill()
            self.disappearing_block_group.remove(block) # remove the surrounding blocks

        if len(self.disappearing_block_group) == 0:     # when blocks are removed, center camera back to player
            self.player.exit_block_reveal = False

最新编辑:让代码工作

我到处玩,让它按我想要的方式工作。现在这对我来说非常有效。

更新的代码(这些是对原始代码的唯一更改)

使用此代码,当我收集最后一个敌人时,相机移动到“退出方块”3 秒,周围的方块被移除,再过 3 秒相机中心回到玩家。

级别的初始化

self.i = 0

关卡的事件处理

if event.type == self.player.EXITBLOCKCLEAR:
    for block in self.disappearing_block_group:
        block.kill()
        self.disappearing_block_group.remove(block)

    if len(self.disappearing_block_group) == 0 and self.i < 1:
        self.i += 1
        self.player.exit_block_reveal = True
    else:
        self.player.exit_block_reveal = False
        pygame.time.set_timer(self.player.EXITBLOCKCLEAR, 0) # stop calling USEREVENT
4

1 回答 1

0

问题是您在关卡事件处理程序中设置的块清除代码,然后在屏幕实际重绘之前重置用于重新定位相机的开关。一旦事件处理程序看到它,它就会清除退出块。列表 被清空,函数继续。清除所有块的循环之后的下一条指令检查是否还有剩余的块 - 。我们知道不会有,因为迭代器刚刚将它们全部杀死。块触发,在更新程序知道它改变之前设置回False。exit_block_revealTruedisappearing_exit_groupif len(self.disappearing_block_group) == 0:ifexit_block_reveal

简而言之:碰撞检测器设置exit_block_reveal为 True,但事件处理程序在更新程序看到它之前将其设置回 False。

您的解决方案通过向块删除功能添加一个循环来工作,但我认为您可以在没有该附加属性的情况下做到这一点。考虑对事件处理程序的这种修改,其中在切换之前而不是之后disappearing_block_group执行检查: exit_block_reveal

if event.type == self.player.EXITBLOCKCLEAR:
    if self.player.exit_block_reveal:
        if not self.disappearing_block_group:  # disappearing_block_group still has contents at this point, so player.exit_block_reveal won't toggle!
            self.player.exit_block_reveal = False

        for block in self.disappearing_block_group:
            block.kill()
        self.disappearing_block_group = list()  # ** SEE NOTE **

在此,我所做的只是将切换开关移到了真值检查exit_block_reveal上方。disappearing_block_group因为该列表仍然有内容,if not self.disappearing_block_group:所以直到下一个循环才运行。此时,列表已被删除(或初始化,如果您如图所示重新分配它),并且if块运行。由于不再有元素disappearing_block_group,因此该for块无事可做并运行零次迭代。

注意:您也可以一次性清除整个列表,而不是删除每个元素。你根本不需要这样!如果您有兴趣,这只是您的一种选择。

希望这可以帮助!

于 2015-02-17T08:21:43.787 回答