I want to make a fractal tree in python. I have made the tree, but I want to have 2 turtles or more to draw my fractal tree all at once. Is there a way to do that? I've looked for solutions but none of them is what I really want. Here is my code:
import turtle
tree = turtle.Turtle()
tree.ht()
tree.penup()
tree.sety(-200)
tree.left(90)
import turtle
tree0 = turtle.Turtle()
tree0.ht()
tree0.penup()
tree0.sety(-200)
tree0.left(90)
startx = tree.xcor()
starty = tree.ycor()
startx = tree0.xcor()
starty = tree0.ycor()
def fractalright(angle, length, x, y):
tree.speed(0)
tree.setx(x)
tree.sety(y)
tree.pendown()
tree.forward(length)
tree.right(angle)
length = length - 20
x = tree.xcor()
y = tree.ycor()
if length < 0:
return
tree.penup()
fractalright(angle, length, x, y)
tree.penup()
tree.setx(x)
tree.sety(y)
tree.left(angle)
fractalright (-angle, length, x, y)
def fractalleft(angle, length, x, y):
tree0.speed(0)
tree0.setx(x)
tree0.sety(y)
tree0.pendown()
tree0.forward(length)
tree0.right(angle)
length = length - 20
x = tree0.xcor()
y = tree0.ycor()
if length < 0:
return
tree0.penup()
fractalleft(angle, length, x, y)
tree0.penup()
tree0.setx(x)
tree0.sety(y)
tree0.left(angle)
fractalleft (-angle, length, x, y)
I am using python 3 and please let me know if you know a solution. Thanks!!
The key to using module threading
with turtle
is to not allow additional threads to manipulate the turtles -- they instead queue up their turtle requests and let the main thread process them:
import queue
from threading import Thread, active_count
from turtle import Turtle, Screen
def forward(turtle, distance):
graphics.put((turtle.forward, distance))
def right(turtle, angle):
graphics.put((turtle.right, angle))
def left(turtle, angle):
graphics.put((turtle.left, angle))
def fractalright(turtle, angle, length):
forward(turtle, length)
if length - 20 > 0:
right(turtle, angle)
fractalright(turtle, angle, length - 20)
left(turtle, angle)
fractalright(turtle, -angle, length - 20)
forward(turtle, -length)
def fractalleft(turtle, angle, length):
forward(turtle, length)
if length - 20 > 0:
left(turtle, angle)
fractalleft(turtle, angle, length - 20)
right(turtle, angle)
fractalleft(turtle, -angle, length - 20)
forward(turtle, -length)
def process_queue():
while not graphics.empty():
action, argument = graphics.get()
action(argument)
if active_count() > 1:
screen.ontimer(process_queue, 100)
START_X, START_Y = 0, -200
screen = Screen()
screen.mode('logo') # make starting direction 0 degrees towards top
tree1 = Turtle(visible=False)
tree1.color('green')
tree1.penup()
tree1.goto(START_X, START_Y)
tree1.pendown()
tree2 = Turtle(visible=False)
tree2.color('dark green')
tree2.penup()
tree2.goto(START_X, START_Y)
tree2.pendown()
graphics = queue.Queue(1) # size = number of hardware threads you have - 1
def fractal1():
fractalright(tree1, 30, 100)
def fractal2():
fractalleft(tree2, 30, 100)
thread1 = Thread(target=fractal1)
thread1.daemon = True # thread dies when main thread (only non-daemon thread) exits.
thread1.start()
thread2 = Thread(target=fractal2)
thread2.daemon = True # thread dies when main thread (only non-daemon thread) exits.
thread2.start()
process_queue()
screen.exitonclick()
We're using the queue module for thread-safe communications. I rewrote your fractalright()
and fractalleft()
functions to minimize the variety of graphics operations they require.
If all goes correctly, you should see the light green and dark green portions of the tree being drawn independently at the same time. Your computer needs to have at least a couple of hardware threads available.