Есть ли способ заставить их двигаться вместе?
Лучшее, на что мы можем надеяться, это заставить их двигаться одновременно. Ниже приведены три все более сложных подхода к этой проблеме. Но сначала давайте установим наш базовый код: две черепахи направляются друг к другу и останавливаются, когда они встречаются в начале координат:
from turtle import Screen, Turtle
screen = Screen()
a = Turtle('square', visible=False)
a.speed('slow')
a.color('red')
a.penup()
a.setx(-300)
a.setheading(0)
a.pendown()
a.showturtle()
b = Turtle('circle', visible=False)
b.speed('slow')
b.color('green')
b.penup()
b.setx(300)
b.setheading(180)
b.pendown()
b.showturtle()
### Subsequent variations start here ###
a.forward(300)
b.forward(300)
### Subsequent variations end here ###
screen.mainloop()
Выше не делается то, что мы хотим, когда одна черепаха движется, а затем другая. Для нашего первого варианта мы просто разбиваем движение на более мелкие единицы и чередуем:
###
for _ in range(300):
a.forward(1)
b.forward(1)
###
Наш следующий вариант использует события таймера для управления движением двух черепах:
###
def move(turtle):
turtle.forward(1)
if turtle.distance(0, 0) > 1 :
screen.ontimer(lambda t=turtle: move(t), 50)
move(a)
move(b)
###
Наш последний вариант использует потоки для независимого управления двумя черепахами. Каждая черепаха является потоком, и есть третий, основной поток, который обрабатывает все графические операции для потоков черепахи. Это необходимо, так как Turtle работает поверх tkinter, у которого есть проблемы с обработкой графики из вторичных потоков:
###
from threading import Thread, active_count
from queue import Queue
QUEUE_SIZE = 1
def process_queue():
while not actions.empty():
action, *arguments = actions.get()
action(*arguments)
if active_count() > 1:
screen.ontimer(process_queue, 100)
actions = Queue(QUEUE_SIZE) # a thread-safe data structure
def move(turtle):
while turtle.distance(0, 0) > 1:
actions.put((turtle.forward, 1))
Thread(target=move, args=[a], daemon=True).start()
Thread(target=move, args=[b], daemon=True).start()
process_queue()
###