基于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
相关产品推荐
相关产品推荐

