Python Pygame击败Em游戏//敌人攻击计时器永远不会达到零

Python Pygame击败Em游戏//敌人攻击计时器永远不会达到零,python,timer,pygame,Python,Timer,Pygame,我正在与Pygame合作一个击败em的游戏,我遇到了一个问题,敌人会永远抓住玩家,不放他走。计时器应该运行,当它达到零时,敌人应该将玩家推开,但它永远不会达到零 变量contact是一组实际接触玩家的敌人。它使用pygame.sprite.Group()函数。如果精灵重叠(玩家和所有敌人列表中的任何敌人),则它们将添加到组中。如果精灵停止重叠(敌人走开,或者玩家走开),那么敌人将从该群中移除 contact = pygame.sprite.spritecollide(heroBoonrit, e

我正在与Pygame合作一个击败em的游戏,我遇到了一个问题,敌人会永远抓住玩家,不放他走。计时器应该运行,当它达到零时,敌人应该将玩家推开,但它永远不会达到零

变量contact是一组实际接触玩家的敌人。它使用pygame.sprite.Group()函数。如果精灵重叠(玩家和所有敌人列表中的任何敌人),则它们将添加到组中。如果精灵停止重叠(敌人走开,或者玩家走开),那么敌人将从该群中移除

contact = pygame.sprite.spritecollide(heroBoonrit, enemy_list, False)
对于时钟的每一个滴答声,我都会设置它来检查是否有任何敌人接触玩家,如果有,然后检查每一个敌人,看看是否有任何敌人处于抓取状态(villan.grabbing\u冷却时间)。这只是一个开/关开关,意味着敌人正在用抓取动作进行攻击。我可能会想出一个更符合逻辑的变量名

如果这些条件得到满足,那么就会发生一些事情,例如向上(或向下)捕捉玩家的位置,以便与敌人处于相同的y坐标上。变量heroBoonrit.hold\u cooldown是另一个开/关开关,表示他当前被关押。玩家和敌人都有自己的变量,分别称为heroBoonrit.Hold_countdown和villan.grabbing_countdown。我看到的问题(通过运行print()进行诊断)是,敌人的倒计时递减1,然后停止递减,而我的英雄的倒计时一直递减到0。因此,敌人从不松手

我有一种感觉,可能有一种更优雅、更干净的方式来处理玩家和敌人的行为,而不是为玩家设置开关,以决定他是否被击昏、抓获等(此外,还有相应的倒计时),但我只做了一个月的编程,如果有任何反馈,我将不胜感激。也许在时钟的每一个滴答声之后,敌手的守时计时器会再次重置为60…我在其他帖子中读到,当你使用Pygame Group()函数时,你不能轻易地遍历该组。仍然在学习许多细节

我在我的主游戏循环中运行了这个命令,以发现敌人的抓取倒计时计时器仅从60到59,然后停止倒计时:

print("||Shit Clown|| Grabbing = ", enemyShit_Clown.grabbing_cooldown, " Countdown = ", enemyShit_Clown.grabbing_countdown, "||Boonrit|| Grabbed = ", heroBoonrit.held_cooldown, " Countdown = ", heroBoonrit.held_countdown)
这是我遇到问题的代码块

    for villan in contact:
        for villan in enemy_list:
            if villan.grabbing_cooldown:
                heroBoonrit.held_cooldown = True
                heroBoonrit.rect.y = villan.rect.y
                heroBoonrit.rect.x = (villan.rect.x + 30)
                heroBoonrit.held_countdown = villan.grabbing_countdown
                villan.grabbing_countdown -= 1
                heroBoonrit.held_countdown -= 1
                if villan.grabbing_countdown <= 0:
                    villan.grabbing_countdown = 0
                    heroBoonrit.held_countdown = 0
                    villan.grabbing_cooldown = False
                    heroBoonrit.held_cooldown = False
                    heroBoonrit.rect.x += 30
            elif villan.attacking_cooldown:
                if heroBoonrit.blocking != True:
                    heroBoonrit.hp -= 100
                else:
                    heroBoonrit.hp -= 10
为了繁殖敌人:

enemyShit_Clown = Enemy("Shit Clown", 1, 4, 1000, 10, 90, False, False, False, False, False, False, 0, 0, 0, 0, 0, True, 60, 0)
enemyShit_Clown.image = pygame.image.load(os.path.join('res','img','chars','shit_clown-3.png')).convert()
enemyShit_Clown.rect.x = 300 #random.randrange(300, 400)
enemyShit_Clown.rect.y =  300 #random.randrange(200, 400)
enemy_list.add(enemyShit_Clown)
all_sprites_list.add(enemyShit_Clown)

非常感谢您的帮助

我看不出恶棍停止倒计时的任何明显原因。也就是说,我确实看到您在hero.update代码和主循环中都在倒计时。我希望您的英雄倒计时的速度是恶棍的两倍,但不是恶棍的60倍

我想建议一些代码更改。首先,去掉
\uuuu init\uuu
代码中的大多数参数。只需将默认值设置为0或False或其他任何值

接下来,我看到您创建了一个角色,然后为其分配了一个图像。这应该在构造函数中,可能有一个默认参数来选择不同的起始图像

接下来,在英雄的
update
方法中有倒计时代码,但在恶棍中没有。我认为这是一个错误。将倒计时移到更新例程中,不要担心在主循环中搜索它

最后,对于您缺少的OO编程,有一条经验法则:“告诉,不要问。”

基本上,这意味着,除其他外,您不应该访问另一个对象的属性,并且您绝对不应该修改另一个对象的属性

我建议您为这些内容编写方法,如下所示:

class Villain: 
    def grab(self, hero):
        """Start a grabbing attack on hero, if not blocked/busy"""

        if self.grabbing:
            # Already grabbing someone. Fail.
            return False

        ticks = 60

        if hero.grabbed(self, ticks):
            self.grabbing = hero
            self.grabbing_countdown = ticks
            hero.moveto(self.rect.y, self.rect.x + 30)
            return True
        else:
            return False

    def update(self, *args):
        :
        blah blah blah
        :
        if self.grabbing:
            self.grabbing_countdown -= 1

            if self.grabbing_countdown == 0:
                self.grabbing.release(self)
                self.grabbing.push_away(self.rect.x, self.rect.y, 30)
                self.grabbing = None

《接触中的恶棍:敌人中的恶棍》\u列表:这是打字错误还是什么?@AustinHastings Hastings-我修正了我帖子中的缩进。代码中的缩进已经是正确的。谢谢你指出这一点。接下来,我看到:
heroBoonrit.hold\u cooldown=True
然后是:
heroBoonrit.hold\u倒计时=villan.grabbing_countdown
。你需要弄清楚它是布尔值还是整数,然后清理你的代码。Re:
对于villan
:为什么你要用同一个变量在两个不同的东西上循环?内部的一个掩盖了外部的一个,而你只是循环了太多。@AustinHastings-heroBoonrit.hold_冷却是布尔值用于确定他是否被拘留。heroBoonrit.Hold_countdown是一个整数变量,它是一个倒计时到零的计时器。它们是两个不同的变量(可能应该以不同的名称命名,以避免混淆)。感谢您的建议。关于“告诉,不要问”心态,由于一个对象被阻止访问/更改另一个对象的属性,一些基本的东西(如击中玩家)是如何工作的?如果敌人攻击,敌人对象图像将更改为攻击图像,villan.attacking=True,则在攻击动画持续时间内,倒计时开始,然后villan.attacking=False。在计时器中,主游戏循环检查精灵直肠重叠,如果重叠,它会检查敌人是否处于攻击状态,如果是,它会将玩家更改为眩晕=真实状态?我想说的是,你告诉英雄你试图击中它,它会告诉你这是否可能(返回值)。如果可能,你假设英雄会尽自己的一份力,你也会尽自己的一份力。(在这种情况下,返回false意味着“由于规则原因(例如:玩家被阻挡或被另一个怪物抓住),我不可能命中”,而不是“因为我闪避,所以你没有命中”。)一个稍微无关的问题。当我繁殖敌人时,我怎么能直接称呼他们?如果我只有一个敌人
class Villain: 
    def grab(self, hero):
        """Start a grabbing attack on hero, if not blocked/busy"""

        if self.grabbing:
            # Already grabbing someone. Fail.
            return False

        ticks = 60

        if hero.grabbed(self, ticks):
            self.grabbing = hero
            self.grabbing_countdown = ticks
            hero.moveto(self.rect.y, self.rect.x + 30)
            return True
        else:
            return False

    def update(self, *args):
        :
        blah blah blah
        :
        if self.grabbing:
            self.grabbing_countdown -= 1

            if self.grabbing_countdown == 0:
                self.grabbing.release(self)
                self.grabbing.push_away(self.rect.x, self.rect.y, 30)
                self.grabbing = None