Filling in a shape drawn by two turtles - python

How do I fill in this shape I drew?
Here's the code:
t = turtle.Turtle()
t2 = t.clone()
#the shapes do not go beyond the screen
for count in range(2):
t.circle(100, 180)
t.right(180)
t2.circle(200, 180)

set t.color(turtle.bgcolor())
start begin_fill on first t2 and then t
draw
end_fill t2 first
and then end_fill t
Entire code:
>>> import turtle
>>> t = turtle.Turtle(); t2 = t.clone()
>>> t.color(turtle.bgcolor())
>>> t2.begin_fill(); t.begin_fill()
>>> t2.circle(200, 180)
>>> for count in range(2):
t.circle(100, 180)
t.right(180)
>>> t2.end_fill(); t.end_fill()

My inclination would be to draw the shape with a single turtle to simplify the problem:
import turtle
turtle.begin_fill()
turtle.circle(100, 180)
turtle.circle(200, -180)
turtle.circle(100, 180)
turtle.end_fill()
turtle.hideturtle()
turtle.done()
The approach of #Superior is perfectly valid (+1), but I'd code it differently:
from turtle import Screen, Turtle
screen = Screen()
t1 = Turtle()
t1.begin_fill()
t1.circle(200, 180)
t1.end_fill()
t2 = Turtle()
t2.color(screen.bgcolor())
t2.begin_fill()
for _ in range(2):
t2.circle(100, 180)
t2.right(180)
t2.end_fill()
screen.exitonclick()
The above can also be done just as easy with a single turtle. And finally, for completeness, we could draw this figure via stamping, which we can do with one or more turtles:
from turtle import Screen, Turtle
screen = Screen()
t1 = Turtle()
t1.hideturtle()
t1.shape('circle')
t1.penup()
t1.shapesize(20)
t1.stamp()
t1.color(screen.bgcolor())
t1.shapesize(stretch_len=10)
t2 = t1.clone()
t2.shapesize(stretch_wid=10)
for sign in (-1, 1):
t2.sety(sign * 100)
t2.stamp()
t1.shape('square')
t1.backward(100)
t1.stamp()
screen.exitonclick()
Generally, I wouldn't clone() turtles unless there's some feature set on the original turtle that you want to preserve in the clone. In your code, you clone a brand new turtle which has no benefit over creating a new turtle instance. In the stamping example above, cloning is used to preserve the color and stretch-width of the original turtle before the original turtle itself changes.

Related

How can I detect the collision of multiple turtle objects?

I have a bunch of turtle objects on the screen.
They don't do anything yet but I am trying to detect collision of turtle objects the simplest way. I know I am supposed to compare all turtle elements turtle.pos with the turtle.pos of all the other elements, but I am not sure how to do it.
Also, I am concerned with not comparing any one item with its own position.
from turtle import *
import random
screen = Screen()
screen.bgcolor("grey")
screen.setup(width=800, height=600)
my_turtles = []
for i in range(10):
turtle = Turtle()
turtle.penup()
turtle.setx(random.randrange(-50, 50))
turtle.sety(random.randrange(-50, 50))
my_turtles.append(turtle)
#for t in turtles:
# if t.pos == anyother t.pos_except_itself
# do something
screen.listen()
screen.exitonclick()
The last thing you want to do is directly compare one turtle.position() with another turtle.position(). The reason is that turtles wander a floating point plane, and directly comparing coordinate values rarely works the way you want. Instead, you need to decide on the minimal distance between (the centers of) two turtles that will be considered a collision. Once you know that distance, then a loop like:
for a in turtles:
if any(a != b and a.distance(b) < SAFE_MARGIN for b in turtles):
# collision, do something here
Here's a rework of your code that does this, causing any turtles that have overly invaded each other's personal space to blink:
from turtle import Screen, Turtle
from random import randrange
RADIUS = 10
def blink_turtles():
for a in turtles:
if any(a != b and a.distance(b) < RADIUS for b in turtles):
a.color(*reversed(a.color()))
screen.ontimer(blink_turtles, 1000)
screen = Screen()
screen.setup(width=800, height=600)
turtles = []
for _ in range(15):
turtle = Turtle()
turtle.hideturtle()
turtle.shape('turtle')
turtle.color('red', 'green')
turtle.penup()
turtle.goto(randrange(-50, 50), randrange(-50, 50))
turtle.showturtle()
turtles.append(turtle)
blink_turtles()
screen.exitonclick()

How to draw a circle using turtle in python?

I wanted ask how can I draw a circle using turtle module in python just using turtle.forward and turtle.left? I use the code below:
for i in range(30):
turtle.forward(i)
turtle.left(i)
turtle.done()
What I get is that the line does not stop once I get the full cirle. How can I code so that I have a circle of specific radius and that I have a full stop once the circle is drawn (without using turtle.circle).
I made this image as a reference,
Essentially you need to draw the inscribed polygon with n sides.
The initial left turn will be ϴ/2.
Then forward by a = 2rsin(ϴ/2).
Each forward is followed by a left turn of the full ϴ, except that after the last forward we want only a left turn of ϴ/2 so that the heading will be correctly updated to be tangential to the circle (or arc).
Something like this,
import turtle
import math
def circle2(radius,extent=360,steps=360):
if extent<360 and steps==360:
steps=extent
theta=extent/steps
step_size=2*radius*math.sin(math.radians(theta/2))
turtle.left(theta/2)
turtle.forward(step_size)
for i in range(1,steps):
turtle.left(theta)
turtle.forward(step_size)
turtle.left(theta/2)
turtle.hideturtle()
turtle.speed(0)
turtle.getscreen().tracer(False)
circle2(50)
circle2(100,180)
turtle.up()
turtle.home()
turtle.down()
circle2(130)
circle2(130,360,10)
turtle.update()
turtle.mainloop()
If you want to draw a circle the best thing to do is to simplyfy the problem, if we consider moving 1 space for each degree of the circle then we can simply write this as
def draw_circle1():
for _ in range(360):
turtle.forward(1)
turtle.left(1)
Now what do we know about this basic circle that we drew? well we know it took 360 steps and each step was 1. so the circle has a circumference of 360. we can use a bit of math to calculate the radius.
circumference = 2 * 3.14... * radius
360 = 2 * 3.14... * radius
360 / 2 / 3.14... = radius
radius = 57.29...
So now we can reverse this, if we want to specify a circle of a given radius, we can calculate what circumference that circle should have. divide that by the 360 degrees and we know what size step to take before each turn of 1 degree.
def draw_circle(radis):
circumfrence = 2 * math.pi * radis
step_size = circumfrence / 360
for _ in range(360):
turtle.forward(step_size)
turtle.left(1)
if we run this for 3 separate circles each increasing in size you see it gives us a consistent result
draw_circle(20)
draw_circle(40)
draw_circle(60)
turtle.hideturtle()
turtle.done()
So now we have a function which can accept a radius and draw a circle based on that radius
A spirograph code
from turtle import Turtle
import random
josh = Turtle()
josh.color('DarkRed')
def random_color()->tuple:
r = random.randint(0,255)
g = random.randint(0,255)
b = random.randint(0,255)
return (r,g,b)
josh.speed('fastest')
josh.pensize(2)
for i in range(72):
josh.circle(100)
josh.right(5)
colormode(255)
josh.pencolor(random_color())
screen = Screen()
screen.setup(800,800)
screen.exitonclick()
Example here,
import turtle
def circle(distance, sections):
angle = 360/sections
for i in range(1, sections+1):
turtle.forward(distance)
turtle.left(angle)
circle(20, 30)
turtle.done()
Create a SPIROGRAPH using turtle. Final output:
import random
import turtle
from turtle import Turtle, Screen
tim = Turtle()
tim.shape('arrow')
turtle.colormode(255)
def random_colour( ):
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
return (r, g, b)
tim.speed('fastest')
def draw_spirograph(size_of_gap):
for _ in range(int(360/size_of_gap)):
tim.color(random_colour())
tim.circle(100)
tim.setheading(tim.heading()+size_of_gap)
draw_spirograph(5)
screen = Screen()
screen.exitonclick()

How to make all the turtles move simultaneously

I want to move all the turtles at the same time, and I want to be able to create 100 turtles. I have to create each one separately in the code so creating 100's of them, or more, will take a long time. I want a way to be able to set the number of turtles I want -- a number from 100 and up. And I want them to move all the same time. I would like to set boundary for as well. Any ideas on how to do any of this or all of it will be appreciated.
To conclude, I want to be able to:
Set the number of turtle generated.
Move all of it at once not one
each time.
Set boundary so it can't go anywhere.
Note: I also know there are a couple questions that were asked but no efficient answer was provided. My code:
import turtle
import numpy as np
tlist = list()
colorlist = ["red", "green", "black", "blue", "brown"]
for i in range(5):
tlist.append(turtle.Turtle(shape="turtle"))
tlist[i].color(colorlist[i])
tlist[i].speed(1)
screen = turtle.getscreen()
for i in range(30):
for t in tlist:
t.speed(1)
t.right((np.random.rand(1) - .5) * 180)
t.forward(int((np.random.rand(1) - .5) * 100))
screen.update()
You don't need "one smart person in here" to solve this, you need to spend more of your own time searching the wealth of turtle examples on SO. However, I will take this on as a personal challenge to write minimalist code to put 100 turtles into bounded random motion:
from turtle import Screen, Turtle
from random import randint
WIDTH, HEIGHT = 600, 600
CURSOR_SIZE, TURTLE_SIZE = 20, 10
TURTLES = 100
def move():
for turtle in screen.turtles():
turtle.forward(1)
x, y = turtle.position()
if not (TURTLE_SIZE - WIDTH/2 < x < WIDTH/2 - TURTLE_SIZE and TURTLE_SIZE - HEIGHT/2 < y < HEIGHT/2 - TURTLE_SIZE):
turtle.undo() # undo forward()
turtle.setheading(randint(1, 360)) # change heading for next iteration
screen.update()
screen.ontimer(move)
screen = Screen()
screen.tracer(False)
screen.setup(WIDTH, HEIGHT)
for turtle in range(TURTLES):
turtle = Turtle()
turtle.penup()
turtle.shapesize(TURTLE_SIZE / CURSOR_SIZE)
turtle.shape('turtle')
turtle.setheading(randint(1, 360))
turtle.goto(randint(TURTLE_SIZE - WIDTH/2, WIDTH/2 - TURTLE_SIZE), randint(TURTLE_SIZE - HEIGHT/2, HEIGHT/2 - TURTLE_SIZE))
move()
screen.exitonclick()

Python drawing images and dynamic shape size

I have a couple of questions. Firstly, I am wondering how to I get shape sizes for shapes I call to be dynamic, and adjust based on my movement of the window that they are in. Is there a simple command for this? Secondly, I am wondering if instead of using something like Turtle to draw images, how do I get an image to just appear once I run drawing code, as opposed to watching it be drawn?
from turtle import *
import math
radius = 100
t = turtle.Turtle()
radius = 100
colormode(255)
t.speed(1)
t.color(0,255,0)
fillcolor(200, 125, 200)
t.begin_fill()
t.circle(radius)
t.end_fill()
exitonclick()
One way you can go about this is by designing a turtle cursor and stamping it. Cursors are drawn all at once and have more graphics operations at their disposal, like resizing, shear, etc. Here's a simple example using turtle's built in circle shape but you can just as easily design your own and register it as a cursor:
RADIUS = 100
CURSOR_SIZE = 20
screen = Screen()
screen.colormode(255)
turtle = Turtle("circle", visible=False)
turtle.speed('fastest')
turtle.penup()
turtle.pencolor(0, 255, 0)
turtle.fillcolor(200, 125, 200)
turtle.shapesize(RADIUS / CURSOR_SIZE, outline=5)
turtle.stamp()
turtle.goto(250, 250)
turtle.shapesize(2 * RADIUS / CURSOR_SIZE, outline=10)
turtle.stamp()
screen.exitonclick()

Python - Make One Turtle Object Always Above Another

I would like to create a program where one Turtle object always stays above all of the other Turtle objects. I don't know if this is possible, but any help would be apprecated.
This is my code:
from turtle import *
while True:
tri = Turtle()
turtle = Turtle()
tri.pu()
tri.pencolor("white")
tri.color("black")
tri.shape("turtle")
tri.bk(400)
turtle = Turtle()
turtle.pu()
turtle.pencolor("white")
turtle.shape("square")
turtle.color("white")
turtle.pu()
turtle.speed(0)
tri.speed(0)
turtle.shapesize(100,100,00)
setheading(towards(turtle))
while tri.distance(turtle) > 10:
turtle.ondrag(turtle.goto)
tri.setheading(tri.towards(turtle))
tri.fd(5)
clearscreen()
Why not just do all the drawing for the "bottom" turtle first? Then do the drawing for the "top" turtle? This should make the top turtle always visible.
My Observed Rules of Turtle Layering:
Multiple Turtles moving to same location: last to arrive is on top.
Same thing drawn by multiple turtles: there are no rules!
To illustrate my second point, consider this code:
from turtle import Turtle, Screen
a = Turtle(shape="square")
a.color("red")
a.width(6)
b = Turtle(shape="circle")
b.color("green")
b.width(3)
b.goto(-300, 0)
b.dot()
a.goto(-300, 0)
a.dot()
a.goto(300, 0)
b.goto(300, 0)
screen = Screen()
screen.exitonclick()
Run it and observe the result. On my system, the final goto() draws a long green line over the red one but the green line disappears as soon as it has finished drawing. Comment out the two calls to dot() and observe again. Now the green line remains over the red one. Now change the calls from dot() to stamp() or circle(5) instead. Observe and formulate your own rule...
Now back to your example, which is badly flawed (you're actually manipulating three turtles, not two!) Here's my simplification:
from turtle import Turtle, Screen
tri = Turtle(shape="turtle")
tri.color("black")
tri.pu()
turtle = Turtle(shape="square")
turtle.shapesize(4)
turtle.color("pink")
turtle.pu()
def drag_handler(x, y):
turtle.ondrag(None)
turtle.goto(x, y)
turtle.ondrag(drag_handler)
turtle.ondrag(drag_handler)
tri.bk(400)
while tri.distance(turtle) > 10:
tri.setheading(tri.towards(turtle))
tri.fd(5)
screen = Screen()
screen.mainloop()
You can tease tri by dragging the pink square until tri catches up with it. Ultimately, tri will land on top as long as the square isn't moving when tri catches it. If you drag the square over tri, then it will temporarily cover him as it is the "last to arrive".

Categories