You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Arcade游戏定时生成敌人 无total_time属性报错修复

问题描述

使用Python Arcade开发基础僵尸射击游戏(核心玩法为操控角色移动、射击僵尸)时,实现敌人随时间自动生成功能触发如下报错:
AttributeError: 'MyGame' object has no attribute 'total_time'
已在MyGame类中定义self.total_time属性,仍无法定位报错原因。

报错根因

self.total_time的初始化逻辑写在setup()方法内,而setup()仅在玩家点击「Start Game」按钮触发on_click_start时才会执行。
Arcade框架的on_update生命周期函数从窗口创建完成、处于主菜单阶段时就会每帧自动调用,此时还未执行setup(),self.total_time属性尚未创建,执行到self.total_time += delta_time时就会触发属性不存在的错误。

除此之外原代码还存在两个逻辑隐患:

  • 计时、敌人生成逻辑写在if self.scene == SCENE_GAME判断外,主菜单阶段也会累加时间,不符合功能预期
  • 重置计时器的self.total_time = 0.0写在生成敌人的for循环内部,每生成1个敌人就会重置一次计时,导致5个敌人生成完计时器直接归0,永远无法触发下一波敌人生成
修复方案
  • 把所有游戏内计时、敌人生成相关的逻辑,全部移动到on_update方法的if self.scene == SCENE_GAME:代码块内部,保证仅进入游戏场景后才执行这部分逻辑
  • 把重置计时器的代码移到敌人生成的for循环外部,确保每波敌人全部生成完后再重置计时

修正后的on_update方法核心代码如下:

def on_update(self, delta_time):
    """ updates values n stuff """

    if self.scene == SCENE_GAME:

        # call update to move the sprite
        self.player_list.update()
        # Call update on all sprites
        self.bullet_list.update()

        # go through each bullet
        for bullet in self.bullet_list:
            # check each bullet to see if it hit a zombie
            hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list)
            # if it did, remove the bullet
            if len(hit_list) > 0:
                bullet.remove_from_sprite_lists()
            # for each enemy we hit with a bullet, remove enemy and add to the score
            for enemy in hit_list:
                enemy.remove_from_sprite_lists()
                self.score += 1
            # if bullet goes off screen, then remove it
            if bullet.bottom > self.width or bullet.top < 0 or bullet.right < 0 or bullet.left > self.width:
                bullet.remove_from_sprite_lists()

        for enemy in self.enemy_list:
            Enemy.follow_sprite(enemy, self.player_sprite)

        # create a list of all sprites that had a collision with the player.
        hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.enemy_list)
        # go through each sprite, if it got hit, then remove the sprite and lower score and health
        for enemy in hit_list:
            enemy.remove_from_sprite_lists()
            self.score -= 1
            self.health -= 1

        # 计时与敌人生成逻辑移入游戏场景判断内
        self.total_time += delta_time

        if self.total_time > 5:
            for i in range(5):
                # enemy texture
                enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", SPRITE_SCALING)
                enemy.center_x = random.randrange(SCREEN_WIDTH)
                enemy.center_y = random.randrange(SCREEN_HEIGHT)
                self.enemy_list.append(enemy)
            # 计时器重置移到循环外
            self.total_time = 0.0

如果想进一步规避初始化顺序导致的属性问题,也可以在__init__方法中提前给self.total_time赋初始值0.0,做双重保险。

内容的提问来源于stack exchange,提问作者riley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:21:28