<p>我看到的主要问题是@furas所指的:<code>enemy_attack()</code>通过递归和计时器调用自身<code>turtle.Turtle</code>调用时不带括号。我不认为以任何方式调用<code>enemy_attack()</code>都是一个好主意,相反,应该在主程序循环中调用它</p>
<p>使用<code>ontimer()</code>的一个问题是,您需要确保使用的超时时间大于执行函数所需的时间。除非它被设计为同时运行自身的多个实例。如果它写的是一个全局变量,那么它可能一次只能写一个</p>
<p>在基于事件的环境(如turtle)中,不应该有<code>while True:</code>(或<code>time.sleep()</code>)。<code>ontimer()</code>方法应该同时处理这两个问题</p>
<p>在Python方面,您不应该执行以下操作:</p>
<pre><code>if bullet.isvisible() == False:
if enemy.isvisible() == True:
if game_over == False:
if shooting == True:
</code></pre>
<p>相反,你应该:</p>
<pre><code>if not bullet.isvisible():
if enemy.isvisible():
if not game_over:
if shooting:
</code></pre>
<p>下面,我把你的代码拆开,按照我期望的海龟游戏的设计方式重新组装。可能还有bug,但现在似乎可以玩了:</p>
<pre><code>from turtle import Screen, Turtle
from random import randint
ENEMY_SPEED = 1
PLAYER_SPEED = 4
BULLET_SPEED = 6
SMALL_FONT = ('Courier', 15, 'normal')
LARGE_FONT = ('Courier', 24, 'normal')
def go_up():
player.setheading(90)
player.forward(PLAYER_SPEED)
def go_right():
player.setheading(0)
player.forward(PLAYER_SPEED)
def go_left():
player.setheading(180)
player.forward(PLAYER_SPEED)
def go_down():
player.setheading(-90)
player.forward(PLAYER_SPEED)
def enemy_attack():
for enemy in enemies:
if enemy.isvisible():
enemy.setheading(enemy.towards(player))
enemy.forward(ENEMY_SPEED)
else:
rand_direction = randint(0, 3)
if rand_direction == 0:
x = randint(-240, 200)
enemy.goto(x, 325)
elif rand_direction == 1:
x = randint(-240, 200)
enemy.goto(x, -325)
elif rand_direction == 2:
y = randint(-210, 210)
enemy.goto(-325, y)
elif rand_direction == 3:
y = randint(-210, 210)
enemy.goto(325, y)
enemy.showturtle()
def shoot():
if not bullet.isvisible():
bullet.goto(player.position())
bullet.setheading(player.heading())
bullet.showturtle()
kill_counter = 0
enemy_spawn_number = 5
lives = 3
def move():
global kill_counter, enemy_spawn_number, lives
enemy_attack()
if player.distance(collectible) < 20:
collectible.goto(randint(-260, 260), randint(-260, 260))
if bullet.isvisible():
if not (-310 < bullet.xcor() < 310 and -310 < bullet.ycor() < 310):
bullet.hideturtle()
else:
bullet.forward(BULLET_SPEED)
playerX, playerY = player.position()
if playerX > 285:
player.setx(playerX - 5)
elif playerX < -285:
player.setx(playerX + 5)
elif playerY > 285:
player.sety(playerY - 5)
elif playerY < -285:
player.sety(playerY + 5)
for enemy in enemies:
if bullet.isvisible() and bullet.distance(enemy) < 15:
bullet.hideturtle()
enemy.hideturtle()
enemy.sety(325)
kill_counter += 1
killcount.clear()
killcount.write("Kill Count: {}".format(kill_counter), align='right', font=SMALL_FONT)
if kill_counter == enemy_spawn_number:
enemy = enemy_prototype.clone()
enemy.showturtle()
enemies.append(enemy)
for enemy in enemies:
enemy.sety(325)
enemy_spawn_number += 5
if enemy.distance(player) < 20:
enemy.hideturtle()
player.goto(0, 0)
lives -= 1
if lives == 2:
life3.hideturtle()
elif lives == 1:
life2.hideturtle()
elif lives == 0:
life1.hideturtle()
if lives == 0:
collectible.hideturtle()
player.hideturtle()
for enemy in enemies:
enemy.hideturtle()
over_message.write("Game Over! Press Esc to exit.", align='center', font=LARGE_FONT)
else:
screen.ontimer(move, 70)
screen.update()
screen = Screen()
screen.setup(width=600, height=600)
screen.title("Defend.")
screen.bgcolor('black')
screen.tracer(0)
player = Turtle()
player.shape('triangle')
player.color('white')
player.penup()
life1 = Turtle()
life1.shape('triangle')
life1.color('yellow')
life1.penup()
life1.goto(265, -260)
life1.setheading(-90)
life2 = life1.clone()
life2.goto(240, -260)
life3 = life2.clone()
life3.goto(215, -260)
over_message = Turtle()
over_message.hideturtle()
over_message.color('white')
over_message.penup()
killcount = over_message.clone()
killcount.goto(270, 270)
killcount.write("Kill Count: 0", align='right', font=SMALL_FONT)
collectible = Turtle()
collectible.shape('square')
collectible.color('blue')
collectible.penup()
collectible.goto(randint(-260, 260), randint(-260, 260))
bullet = Turtle()
bullet.hideturtle()
bullet.shape('square')
bullet.shapesize(0.5, 1)
bullet.color('grey')
bullet.penup()
bullet.goto(500, 500)
enemy_prototype = Turtle()
enemy_prototype.hideturtle()
enemy_prototype.shape('circle')
enemy_prototype.color('red')
enemy_prototype.penup()
enemy_prototype.sety(325)
enemy = enemy_prototype.clone()
enemy.showturtle()
enemies = [enemy]
screen.onkeypress(go_up, 'w')
screen.onkeypress(go_right, 'd')
screen.onkeypress(go_left, 'a')
screen.onkeypress(go_down, 's')
screen.onkeypress(screen.bye, 'Escape')
screen.onkeypress(shoot, 'space')
screen.listen()
move()
screen.mainloop()
</code></pre>
<p>我认为您应该解决的下一个问题是代码中阻止您调整屏幕大小的所有数字常量:</p>
<pre><code>life1.goto(265,-260)
life2.goto(240,-260)
life3.goto(215,-260)
killcount.goto(250,250)
x = randint(-240, 200)
x = randint(-240, 200)
y = randint(-210, 210)
y = randint(-210, 210)
x = randint(-290, 290)
y = randint(-290, 290)
if bullet.xcor()>310 or bullet.xcor()<-310 or bullet.ycor()>310 or bullet.ycor()<-300:
if player.xcor()>285:
elif player.xcor()<-285:
elif player.ycor()>285:
elif player.ycor()<-285:
</code></pre>
<p>这些都应根据屏幕大小进行定义:</p>
<pre><code>screen.setup(width=600, height=600)
</code></pre>
<p>以及他们操纵的对象。(即代码中没有大数字!)</p>