#python #turtle-graphics
#python #черепаха-графика
Вопрос:
У меня возникла проблема, из-за которой вражеская черепаха останавливается, когда я стреляю. Я относительно новичок в Python, поэтому я знаю, что мой код довольно плох. Кажется, я не могу понять, почему это происходит, но я предполагаю, что это как-то связано с циклом while.
вот код: (я добавил примечания, чтобы было легко перейти к важным его частям)
import turtle
import os
#wn is window
#bp = border
bullet = 'ready'
#screen setup
wn = turtle.Screen()
wn.bgcolor('black')
wn.title('SPACE.INVADERS')
#border
bp = turtle.Turtle()
bp.speed(0)
bp.color('green')
bp.penup()
bp.setposition(-300,-300)
bp.pendown()
count=0
while count != 5:
count= (count 1)
bp.fd(600)
bp.lt(90)
bp.hideturtle()
#player
p = turtle.Turtle()
p.color('red')
p.shape('triangle')
p.penup()
p.speed(0)
p.setposition(0,-250)
p.setheading(90)
#enemy
e = turtle.Turtle()
e.penup()
e.speed(0)
e.shape('square')
e.shapesize(1.25,1.25)
e.color('orange')
e.setpos(-250,250)
e.speed(1)
#p = player
#ps = player speed
ps = 15
#moving left and right
def left_mov():
x = p.xcor()
x -= ps
p.setx(x)
def right_mov():
x = p.xcor()
x = ps
p.setx(x)
#shooting
def shoot():
global bullet
if bullet == 'ready':
bullet = 'fire'
shot= turtle.Turtle()
shot.penup()
shot.speed(0)
shot.goto(p.pos())
shot.color('white')
shot.shape('triangle')
shot.shapesize(0.5)
shot.lt(90)
shot.speed(1)
shot.fd(550)
bullet = 'ready'
#bindings
turtle.listen()
turtle.onkey(left_mov, 'Left')
turtle.onkey(right_mov, 'Right')
turtle.onkey(shoot, 'space')
#enemy movement
while True:
e.fd(500)
e.rt(90)
e.fd(25)
e.rt(90)
e.fd(500)
e.lt(90)
e.fd(25)
e.lt(90)
Ответ №1:
Я предполагаю, что это как-то связано с циклом while
Да, этого не должно быть там! В мире, управляемом событиями, таком как turtle, никогда не должно быть while True:
цикла. Вместо этого нам нужно событие таймера, которое запускается через регулярные промежутки времени и выполняет постепенные обновления движущихся объектов (врага и пули), чтобы казалось, что они движутся одновременно. Ниже приведена моя доработка вашего кода с использованием события таймера:
from turtle import Screen, Turtle
# moving left and right
def left_move():
player.setx(player.xcor() - player_speed)
def right_move():
player.setx(player.xcor() player_speed)
# screen setup
screen = Screen()
screen.bgcolor('black')
screen.title('SPACE.INVADERS')
# border
border = Turtle(visible=False)
border.speed('fastest')
border.color('green')
border.penup()
border.setposition(-300, -300)
border.pendown()
for _ in range(4):
border.forward(600)
border.left(90)
# player
player = Turtle('triangle')
player.speed('fastest')
player.color('red')
player.penup()
player.setposition(0, -250)
player.setheading(90)
player_speed = 15
# enemy
enemy = Turtle('square')
enemy.speed('fast')
enemy.shapesize(1.25)
enemy.color('orange')
enemy.penup()
enemy.setpos(-250, 250)
enemy_speed = 6 # enemy speed
enemy_direction = 1 # enemy direction
# bullet
bullet = Turtle('triangle', visible=False)
bullet.speed('fastest')
bullet.color('white')
bullet.shapesize(0.5)
bullet.penup()
bullet.left(90)
bullet_speed = 9 # bullet speed
# shooting
def shoot():
if not bullet.isvisible():
bullet.goto(player.position())
bullet.showturtle()
def move():
global enemy_direction
if bullet.isvisible():
if bullet.ycor() > 275:
bullet.hideturtle()
else:
bullet.forward(bullet_speed)
# enemy movement
enemy.forward(enemy_direction * enemy_speed)
enemy.settiltangle(enemy.tiltangle() 3) # just for fun
x, y = enemy.position()
if x > 250 or x < -250:
enemy_direction *= -1
enemy.sety(y - 25)
screen.ontimer(move, 50)
# bindings
screen.onkey(left_move, 'Left')
screen.onkey(right_move, 'Right')
screen.onkey(shoot, 'space')
screen.listen()
move()
screen.mainloop()
Это должно дать вам базовую функциональность, необходимую для продвижения вперед и добавления обнаружения столкновений (пуля во врага, враг в игрока, игрок в стену) и подсчета очков.
Также обратите внимание, что turtles являются глобальными объектами, поэтому создавать новый маркер каждый раз, когда он вам нужен, — плохая идея. Даже если вы обычно разрешаете перекрывающиеся маркеры, сохраните для этой цели набор маркеров многократного использования.