小能豆

为什么我的 Python Turtle 程序运行时间越长,速度就越慢?

py

我正在尝试制作一款简单的 galaga 类游戏,其中飞船沿着屏幕底部来回移动并自动射击。它一开始按预期运行,但很快就大幅减慢了速度。我认为它可能是因为它有越来越多的子弹需要跟踪,但限制屏幕上的子弹数量似乎根本没有帮助。

主循环:

while game_is_on:

    screen.update()
    ship.slide()
    bullet_manager.shoot(ship.xcor())
    bullet_manager.move_bullets()

来自 bullet_manager:

def shoot(self, xcor):
    self.chance +=1
    if self.chance %6 == 0:
        new_bullet = Turtle("square")
        new_bullet.color("red")
        new_bullet.shapesize(stretch_wid=.1)
        new_bullet.pu()
        new_bullet.seth(90)
        new_bullet.goto(xcor, -200)
        self.all_bullets.append(new_bullet)


def move_bullets(self):
    for bullet in self.all_bullets:
        bullet.forward(10)
        self.all_bullets = self.all_bullets[-10:]

阅读 6

收藏
2025-01-13

共1个答案

小能豆

你的游戏运行缓慢可能是由于 Turtle 对象的累积和过多的计算。尽管你试图通过限制 self.all_bullets 的长度来控制子弹数量,Python 的 list 操作 self.all_bullets[-10:] 仍然可能导致性能问题。此外,未销毁或隐藏的 Turtle 对象可能仍会参与计算。

以下是一些建议来优化你的代码:


问题分析

  1. Turtle 对象的数量:
  2. 即使你限制了 self.all_bullets 的长度,屏幕上的 Turtle 对象不会被销毁或移除。它们仍然存在于内存中,造成性能下降。

  3. 屏幕更新频率:

  4. screen.update() 更新整个屏幕,每帧都重新渲染所有图形。如果屏幕上的对象太多,会导致性能下降。

  5. 清理离开屏幕的子弹:

  6. 子弹离开屏幕后并未被删除,可能会继续被渲染和计算。

优化方法

1. 移除离开屏幕的子弹

确保每帧都检查子弹是否超出了屏幕边界,并将其从 self.all_bullets 中移除。

def move_bullets(self):
    for bullet in self.all_bullets[:]:  # 使用切片以避免在循环中修改列表
        bullet.forward(10)
        # 检查子弹是否超出屏幕边界
        if bullet.ycor() > 300:  # 假设屏幕顶部的 y 坐标为 300
            bullet.hideturtle()  # 隐藏子弹
            self.all_bullets.remove(bullet)

2. 限制屏幕上的子弹数量

shoot 方法中控制 self.all_bullets 的数量,确保只生成有限的子弹。

def shoot(self, xcor):
    self.chance += 1
    if self.chance % 6 == 0:
        # 限制最大子弹数量
        if len(self.all_bullets) >= 10:  # 假设最大允许子弹数为 10
            return
        new_bullet = Turtle("square")
        new_bullet.color("red")
        new_bullet.shapesize(stretch_wid=.1)
        new_bullet.pu()
        new_bullet.seth(90)
        new_bullet.goto(xcor, -200)
        self.all_bullets.append(new_bullet)

3. 减少屏幕更新的开销

尽量减少屏幕刷新操作。如果可能,使用 ontimer 或降低刷新频率。

while game_is_on:
    screen.update()
    ship.slide()
    bullet_manager.shoot(ship.xcor())
    bullet_manager.move_bullets()
    time.sleep(0.01)  # 降低循环频率

完整的优化代码示例

class BulletManager:
    def __init__(self):
        self.all_bullets = []
        self.chance = 0

    def shoot(self, xcor):
        self.chance += 1
        if self.chance % 6 == 0:
            if len(self.all_bullets) >= 10:  # 限制最大子弹数量
                return
            new_bullet = Turtle("square")
            new_bullet.color("red")
            new_bullet.shapesize(stretch_wid=.1)
            new_bullet.pu()
            new_bullet.seth(90)
            new_bullet.goto(xcor, -200)
            self.all_bullets.append(new_bullet)

    def move_bullets(self):
        for bullet in self.all_bullets[:]:
            bullet.forward(10)
            if bullet.ycor() > 300:  # 子弹超出屏幕顶部
                bullet.hideturtle()
                self.all_bullets.remove(bullet)


# 主循环
while game_is_on:
    screen.update()
    ship.slide()
    bullet_manager.shoot(ship.xcor())
    bullet_manager.move_bullets()
    time.sleep(0.01)  # 控制更新频率

进一步优化建议

  1. 使用自定义绘图库:
  2. 如果 Turtle 性能不足,可以考虑使用 pygamearcade 库,它们在处理高频图形更新时效率更高。

  3. 批量更新对象:

  4. 通过批处理屏幕更新减少单帧的开销,而不是每帧重新渲染所有对象。

  5. 优化对象管理:

  6. 将子弹作为轻量对象存储(例如仅存储位置和状态),减少 Turtle 的开销。
2025-01-13