I am trying to learn python and so far it has gone well. However i keep getting an infinite loop error after a while of my code running. The code given below is that of a star with 7 angles.
import turtle
n = 7
def drawStar(t, sz, s):
"""Get turtle t to draw a star of sz sides, s size"""
for i in range(sz):
t.right(180)
t.forward(s)
t.right(180/n)
wn = turtle.Screen()
wn.bgcolor("lightgreen")
alex = turtle.Turtle()
alex.color("hotpink")
#
n = 7
for i in range(15):
alex.up()
alex.forward(30)
alex.right(144)
alex.down()
print(n)
drawStar(alex,n,30)
wn.exitonclick()
Folks have pointed out that your use of range(15) instead of range(5) redraws the stars three times making your program take longer. (Sufficiently that you mistook it for an infinite loop.)
There are additional ways to improve the performance of the program. The easy bandaid is to add alex.speed("fastest") which will cause the turtle to race through the drawing and end sooner.
However, if we instead do alex.speed("slowest") we'll see the other problem with the program: the turtle spends too much time turning one way and turning back the other. At times it turns the long way around a circle instead of the short way. So let's rework the code to address this issue:
from turtle import Turtle, Screen
N = 7
def drawStar(turtle, sides, size):
""" Get turtle turtle to draw a star of sides sides of size size """
turtle.right(18)
for _ in range(sides - 1):
turtle.forward(size)
turtle.right(6 * 180 / sides)
turtle.forward(size)
screen = Screen()
screen.bgcolor("lightgreen")
alex = Turtle()
# alex.speed("fastest")
alex.color("hotpink")
for i in range(5):
alex.up()
alex.forward(30)
alex.down()
drawStar(alex, N, 30)
alex.left(8)
alex.hideturtle()
screen.exitonclick()
Under normal speed, and only 5 iterations instead of 15, this optimization of turns knocks 1/3 off the time it takes to draw the stars! Yet produces the same result:
Related
I am trying to make this game where once you hit the borders of the box the turtle will return to the position it was at directly before it hit the border of the box. I am pretty new so any help would be appreciated. So far I have if y cord is greater than the box it goes back to right before it hit but it doesn't seem to be working.
import turtle
wn = turtle.Screen()
wn.bgcolor('black')
line = turtle.Turtle()
line.goto(-450,-15)
line.speed(9999)
line.pendown
line.color('white')
line.forward(850)
line.left(90)
line.forward(400)
line.left(90)
line.forward(850)
line.left(90)
line.forward(410)
line.color('black')
fred = turtle.Turtle()
fred.penup()
fred.goto(-430, 0)
fred.shape('square')
fred.color('white')
fred.penup()
fred.delay = 0.1
fred.direction = "Stop"
#Set Up (Controls)
wn.listen()
def ahead():
fred.forward(10)
def behind():
fred.backward(10)
if fred.ycor() < -500:
fred.goto(0, -500)
if fred.ycor() > 500:
fred.goto(0, 500)
wn.onkey(behind,"a")
wn.onkey(ahead,"d")
wn.mainloop()
You should use if inside functions - and values in if you may have to calculate manually.
def ahead():
fred.forward(10)
#print(fred.xcor())
if fred.xcor() > 430 - 50: # minus turtle width
fred.backward(10)
def behind():
fred.backward(10)
#print(fred.xcor())
if fred.xcor() < -430 :
fred.forward(10)
But problem will be if you will have more elements which should stop turtle.
turtle doesn't have function to detect collisions and you may have to access tkinter functions for this or you would have to create own function which checks xcor, ycor with coordinates from some list. And list should have coordinates for all objects. And this may need to calculate coordinates manually.
turtle is nice for drawing figures but not for games. There are better modules - like PyGame, Arcade, PGzero (PyGame Zero)
I have written a programme that creates a random walk using certain distribution. For example, if it is a Cauchy distribution, the program generates an adequate random number and appends it to the list. Then this list is used by the turtle as a list of steps in a random direction. Now I would like to measure the distance between the turtle in each step and point (0,0) where the random walk is starting and I can't seem to find a good solution for that. It cannot be done with turtle.distance() because I want to draw a graph of dependence this distance on step count. My first idea was to get coordinates of each point that my turtle stops and then try to calculate distance using the Pythagoras theorem, but I make mistakes somewhere along the road and can't acquire them. Could someone explain why, please? Or maybe there is a better way to do this?
cauchylist = []
for i in randomlist:
cauchylist.append(0.15*math.tan(((i-0.5)*math.pi)) )
Franklin = turtle.Turtle()
u = input("Which walk to walk? C - Cauchy or G - Gauss.")
if u == "C":
start()
walk(Franklin, cauchylist)
cv = turtle.getcanvas()
cv.postscript(file="walk_cauchy.ps")
Franklin.penup()
Franklin.fd()
Franklin.end_poly()
coordinates = Franklin.get_poly()
turtle.done()
The distance of the current position of the turtle to the origin is calculated by squaring the posi-values, adding them and getting the square root from that:
from turtle import *
from math import sqrt
from random import seed, choice
seed(42) # ensure same randoms for demonstation purposes
def calc_dist(t):
return sqrt(sum(map(lambda x:x*x, t.pos())))
t = Turtle()
dists = []
for _ in range(20):
t.forward(choice(range(100))-50)
t.left(choice(range(360))-180)
dists.append(calc_dist(t))
print(dists)
Output:
[31.0, 68.97157492789178, 87.25113481192517, 98.48389701852805, 134.17622966161073,
141.40760908816227, 138.90181656585844, 128.76423765225354, 113.79561063931857,
108.70118700467432, 66.53516784607132, 87.40888728250773, 113.65616399911761,
115.22672747425487, 122.12225694530929, 128.35176588895283, 157.57222689310848,
128.33399580245668, 129.3846600939952, 153.87822281203412]
Do the calculation sqrt(sum(map(lambda x:x*x, t.pos()))) after each move of the turtle and store the result in a list.
get_poly() will return a tuple of tuples.
Example:
coordinates = turtle.get_poly()
coordinates = ((0.00,0.00), (100.00,0.00), (128.19,10.26), (136.87,59.50))
You can easily acess each tuple with a for loop
for c in coordinates:
print(c)
Output:
(0.00,0.00)
(100.00,0.00)
(128.19,10.26)
(136.87,59.50)
I would like to measure the distance between the turtle in each step
and point (0,0) where the random walk is starting and I can't seem to
find a good solution for that. It cannot be done with
turtle.distance()
This premise doesn't hold. We can do turtle.distance(0, 0) which doesn't affect the turtle's state but gives us the distance to the origin. To demonstrate, my rework of #PatrickArtner's example using distance():
from turtle import Screen, Turtle
from random import seed, randint
seed(42) # repeatable randomness for demonstration purposes
screen = Screen()
turtle = Turtle()
distances = []
for _ in range(20):
turtle.forward(randint(-50, 50))
turtle.left(randint(-180, 180))
distances.append(turtle.distance(0, 0))
print(distances)
screen.exitonclick()
Console Output
> python3 test.py
[31.0, 68.97157492789178, 87.25113481192517, 98.48389701852807, 134.17622966161073,
141.40760908816227, 138.90181656585844, 128.7642376522535, 113.79561063931855,
108.70118700467431, 66.5351678460713, 87.4088872825077, 113.65616399911758,
115.22672747425486, 122.12225694530927, 128.35176588895283, 157.57222689310848,
128.33399580245668, 129.3846600939952, 153.87822281203412]
>
I cannot use t.forward and t.left commands because I get an error
"invalid command name . canvas turtle". I think it's because my turtle
walk is defined by function looking like that:
def walk(turtle, steps):
x = 0
y = 0
for i in steps:
kat = random.random() * 360
turtle.setheading(kat)
turtle.forward(math.fabs(i))
bounds(turtle)
However, if I don't use it as on the example You gave, I create list
full of only last distance value. Can anything be done about that?
We'd need to see more code to address this issue, e.g. the definition of bounds() and so forth.
With python, I'm trying to make a function that gets the colour that the turtle is currently on top of. I've found that turtle.pos() gives me coordinates of its location, how can I use those coordinates to get colours?
I think the best way to do this would be using the steps shown here: https://www.kite.com/python/answers/how-to-find-the-rgb-value-of-a-pixel-in-python
One way to go about this is to append every turtle you create into a list, then in your main game loop, loop through the list of turtle to see if the turtle.distance() is smaller than a certain value:
import turtle
wn = turtle.Screen()
turtles = []
yertle = turtle.Turtle('turtle')
while True:
wn.tracer(0)
for t in turtles:
if yertle.distance(t) < 20 and yertle != t:
print(f'Touched {t.color()}')
wn.update()
In the above code I used if yertle.distance(t) < 20 which is for when all the turtles are the default size: 20.
I'm doing a homework and I want to know how can I move turtle to a random location a small step each time. Like can I use turtle.goto() in a slow motion?
Someone said I should use turtle.setheading() and turtle.forward() but I'm confused on how to use setheading() when the destination is random.
I'm hoping the turtle could move half radius (which is 3.5) each time I update the program to that random spot.
You use the term half radius twice in your question's title and text, but never really explain it. For purposes of your question, we're just talking about some arbitrary small distance -- correct?
I would avoid import time and time.sleep() as they work against an event-driven world like turtle. Instead, I would use turtle's own ontimer() method to keep things in synch:
from turtle import Screen, Turtle
from random import randrange
HALF_RADIUS = 3.5 # unexplained constant
DELAY = 1000 # milliseconds
WIDTH, HEIGHT = 640, 480
CURSOR_SIZE = 20
def forward_slowly(distance):
if distance > 0:
turtle.forward(min(distance, HALF_RADIUS))
remaining = max(distance - HALF_RADIUS, 0)
screen.ontimer(lambda d=remaining: forward_slowly(d), DELAY)
else:
screen.ontimer(move_target, DELAY)
def move_target():
x = randrange(CURSOR_SIZE - WIDTH//2, WIDTH//2 - CURSOR_SIZE)
y = randrange(CURSOR_SIZE - HEIGHT//2, HEIGHT//2 - CURSOR_SIZE)
target.goto(x, y)
target.pendown()
turtle.setheading(turtle.towards(target))
forward_slowly(turtle.distance(target))
screen = Screen()
screen.setup(WIDTH, HEIGHT)
turtle = Turtle('turtle')
turtle.speed('slowest')
turtle.width(3)
target = Turtle('turtle')
target.speed('fastest')
target.color('red')
target.penup()
move_target()
screen.exitonclick()
(Any resemblence to a Pepé Le Pew cartoon is purely coincidental.)
Do you mean that you want to move a small step, stop, and repeat? If so, you can ‘import time’ and add ‘time.sleep(0.1)’ after each ‘forward’
I am trying to generate a list of random Y coordinates for a turtle graphics program that needs to draw flowers, but to prevent the flowers from drawing over each other I need to draw them from back to front. What I need to do is sort the random list from largest to smallest, then have it draw the flowers in that order.
I have already set up the program to generate 9 random numbers and sort them from largest to smallest, but I don't know how to draw the numbers from that list in order and assign them the Y value of the flower
This is my code for generating the random list:
def draw_stem(t,StemX,StemY):
StemYcoordinates=random.sample(range(-200,0),9)
sorted(StemYcoordinates, key=int)
But I am having trouble connecting it to this part of the code where it goes to the xy position where I want the flower to be drawn
for i in range(9):
t.setheading(90)
t.pensize(7-(StemYcoordinate//40))
t.color("#39ff14")
t.penup()
t.goto(StemX,StemYcoordinates)
t.down()
any help would be greatly appreciated
I think for your code, you will need to use the setpos() method.
This method treats the screen in turtle like a coordinate plane with four quadrants.
Using this, set the x and y coordinates accordingly, or randomly if you want to.
For example, this puts the turtle in a random spot every time you run it:
from turtle import *
t = Turtle()
t.penup()
from random import randint
x = randint(-200, 200)
y = randint(-200, 200)
t.setpos(x, y)
Hope this Helps!!!
Based on the description of your problem, you seem to want something like:
from turtle import Screen, Turtle
from random import sample, random
RADIUS = 100
PETALS = 10
def draw_petal(t, radius):
heading = t.heading()
t.circle(radius, 60)
t.left(120)
t.circle(radius, 60)
t.setheading(heading)
def draw_flower(t):
for _ in range(PETALS):
draw_petal(t, RADIUS)
t.left(360 / PETALS)
def draw_flowers(t, stemX):
stemYcoordinates = sorted(sample(range(-200, 0), 9))
for stemYcoordinate in stemYcoordinates:
t.setheading(90)
t.pensize(7 + stemYcoordinate // 40)
t.color(random(), random(), random())
t.penup()
t.goto(stemX, stemYcoordinate)
t.pendown()
draw_flower(t)
screen = Screen()
turtle = Turtle(visible=False)
turtle.speed('fastest') # because I have no patience
draw_flowers(turtle, 0)
screen.exitonclick()
But if this isn't what you're looking for, take the time to reread and edit your question to clarify what you want to do. Add more (if not all) of the code you've written so far, to make it clear what you need help with.