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

基于Python Turtle的太空侵略者游戏点击屏幕重置功能实现问题

错误原因

  • 直接将全量代码包裹进循环会重复导入依赖、重复创建画布/精灵/事件绑定,出现变量重定义、资源冲突问题
  • 封装函数时没有正确处理变量作用域,也没有在重启前清空上一轮游戏的残留对象,因此触发变量未定义报错

实现方案

将游戏初始化+运行逻辑封装为独立函数,pygame相关全局初始化仅执行一次,游戏结束后绑定屏幕点击事件,触发时清空上一轮画布内容后重新调用游戏函数即可,修改后完整代码如下:

import turtle
import math
import random
import pygame

# 全局初始化仅执行一次,避免重复初始化报错
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load("Sounds/music.mp3")
pygame.mixer.music.play(loops=-1)
bubblefiredsound = pygame.mixer.Sound("Sounds/bubblefired.mp3")
enemyhitsound = pygame.mixer.Sound("Sounds/enemyhit.mp3")
screen = turtle.Screen()

def start_game():
    # SCREEN SETUP
    screen.bgcolor("black")
    screen.title("Space Invaders")
    screen.bgpic("TurtleInvadersBackground.png")

    # CUSTOM SHAPES
    turtle.register_shape("Enemy.gif")
    turtle.register_shape("Turtle.gif")
    turtle.register_shape("Bubble.gif")

    # BORDERS
    border_pen = turtle.Turtle()
    border_pen.speed(0)
    border_pen.color("white")
    border_pen.penup()
    border_pen.setposition(-300, -300)
    border_pen.pendown()
    border_pen.pensize(3)
    for side in range(4):
        border_pen.fd(600)
        border_pen.lt(90)
    border_pen.hideturtle()

    # SCORE
    score = 0
    score_pen = turtle.Turtle()
    score_pen.speed(0)
    score_pen.color("white")
    score_pen.penup()
    score_pen.setposition(-290, 270)
    scorestring = "Score: %s" % score
    score_pen.write(scorestring, False, align="left", font=("Bubble3D", 20, "normal"))
    score_pen.hideturtle()

    # MAIN TURTLE
    MajorTom = turtle.Turtle()
    MajorTom.color("blue")
    MajorTom.shape("Turtle.gif")
    MajorTom.penup()
    MajorTom.speed(0)
    MajorTom.setposition(0, -250)
    MajorTom.setheading(90)

    playerspeed = 0

    # NUMBER OF ENEMIES
    number_of_enemies = 5
    enemies = []
    for i in range(number_of_enemies):
        enemies.append(turtle.Turtle())

    for enemy in enemies:
        enemy.color("red")
        enemy.shape("Enemy.gif")
        enemy.penup()
        enemy.speed(0)
        x = random.randint(-200, 200)
        y = random.randint(100, 250)
        enemy.setposition(x, y)

    enemyspeed = 5

    # CREATE THE PROJECTILE BUBBLE
    bubble = turtle.Turtle()
    bubble.color("blue")
    bubble.shape("Bubble.gif")
    bubble.penup()
    bubble.speed(0)
    bubble.setheading(90)
    bubble.hideturtle()
    bubble.setpos(0, -300)

    bubblespeed = 20
    bubblestate = "ready"

    # MOVEMENT (LEFT AND RIGHT)
    def move_left():
        nonlocal playerspeed
        playerspeed = -7

    def move_right():
        nonlocal playerspeed
        playerspeed = 7

    def stop_player():
        nonlocal playerspeed
        playerspeed = 0

    def fire_bubble():
        nonlocal bubblestate
        if bubblestate == "ready":
            bubblestate = "fire"
            x = MajorTom.xcor()
            y = MajorTom.ycor() + 10
            bubble.setposition(x, y)
            bubble.showturtle()
        if bubblestate == "fire":
            bubblefiredsound.play()

    def CollisionDetection(t1, t2):
        distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))
        return distance < 32

    # KEYBINDINGS
    screen.listen()
    screen.onkeypress(move_left, "a")
    screen.onkeypress(move_right, "d")
    screen.onkeyrelease(stop_player, "a")
    screen.onkeyrelease(stop_player, "d")
    screen.onkey(fire_bubble, "space")

    # GAME LOOP
    game_over = False
    while not game_over:
        # MOVE PLAYER
        MajorTom.setx(MajorTom.xcor() + playerspeed)

        # BORDER CONTROL
        if MajorTom.xcor() > 285:
            MajorTom.setx(285)
            playerspeed = 0
        elif MajorTom.xcor() < -285:
            MajorTom.setx(-285)
            playerspeed = 0

        for enemy in enemies:
            # ENEMY MOVEMENT
            x = enemy.xcor()
            x += enemyspeed
            enemy.setx(x)

            # MOVE THE ENEMY BACK AND DOWN
            if enemy.xcor() > 280 or enemy.xcor() < -280:
                for e in enemies:
                    y = e.ycor()
                    y -= 40
                    e.sety(y)
                enemyspeed *= -1

            # BUBBLE HITS ENEMY
            if CollisionDetection(bubble, enemy):
                enemyhitsound.play()
                bubble.hideturtle()
                bubblestate = "ready"
                bubble.setposition(0, -400)
                x = random.randint(-200, 200)
                y = random.randint(100, 250)
                enemy.setposition(x, y)
                score += 10
                scorestring = "Score: %s" % score
                score_pen.clear()
                score_pen.write(scorestring, False, align="left", font=("Bubble3D", 20, "normal"))

            if CollisionDetection(MajorTom, enemy) or enemy.ycor() < -300:
                MajorTom.hideturtle()
                enemy.hideturtle()
                GameOverPen = turtle.Turtle()
                GameOverPen.hideturtle()
                GameOverPen.penup()
                GameOverPen.goto(0,0)
                GameOverPen.speed(0)
                GameOverPen.color("pink")
                GameOverPen.write("GAME OVER!", align="center", font=("Bubble3D", 90, "normal"))
                GameOverPen.goto(0, -20)
                GameOverPen.write("\nClick to try again!", align="center", font=("Arial", 20, "normal"))
                game_over = True
                break

        # BUBBLE MOVEMENT
        if bubblestate == "fire":
            y = bubble.ycor()
            y += bubblespeed
            bubble.sety(y)
        
        if bubble.ycor() > 275:
            bubble.hideturtle()
            bubblestate = "ready"
    
    # 游戏结束后绑定点击重启事件
    screen.onclick(lambda x,y: restart())

def restart():
    # 清空上一轮所有画布内容
    screen.clear()
    # 重新启动游戏
    start_game()

# 首次启动游戏
start_game()
turtle.mainloop()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 19:54:00