Here's the exercise Lessons from a Triangle!
import turtle
def drawPolygon(t, sideLength, numSides):
turnAngle = 360 / numSides
for i in range(numSides):
t.forward(sideLength)
t.left(turnAngle)
def drawFilledCircle(anyTurtle, radius, vcolor):
anyTurtle.fillcolor(vcolor)
anyTurtle.begin_fill()
circumference = 2 * 3.1415 * radius
sideLength = circumference / 360
drawPolygon(anyTurtle, sideLength, 360)
anyTurtle.end_fill()
wn = turtle.Screen()
wheel = turtle.Turtle()
drawFilledCircle(wheel, 20, 'purple')
wn.exitonclick()
1) How come when I try to change the speed of the turtle like wheel.speed(10) it doesn't work? What's the default speed if I don't indicate the speed?
2) How do i put my turtle to the middle of the circle once it's done?
Thank You so Much!
As abarnert said, the link to your exercise is broken, but there are a few things you can do to speed up your program. FWIW, the turtle module has a .circle method, but I guess the point of your exercise is to use a polygon to approximate a circle.
wheel.speed(10) does work (although wheel.speed(0) is even faster). It doesn't appear to make much difference because the sides of your 360-sided polygon are so tiny, and so the turtle has to do several moves & turns just to traverse a single pixel.
Using a 360-sided polygon to draw a circle, no matter what the radius is, is not a great strategy. The code below determines the number of sides from the circumference so that each side is approximately 1 pixel. This will look good for a circle of any radius, and it avoids doing too much work for small circles.
Apart from using turtle.speed to speed things up you can also reduce the canvas's frame delay. Also, if you hide the turtle while drawing, it'll go even faster.
The following code was tested on Python 2.6.6; it should also work without modification on Python 3.x, but on Python 3.x you may remove the from __future__ import division, print_function line.
#!/usr/bin/env python
''' Approximate a circle using a polygon
From http://stackoverflow.com/q/30475519/4014959
Code revised by PM 2Ring 2015.05.27
'''
from __future__ import division, print_function
import turtle
def drawPolygon(t, sideLength, numSides):
turnAngle = 360 / numSides
for i in range(numSides):
t.forward(sideLength)
t.left(turnAngle)
def drawFilledCircle(anyTurtle, radius, vcolor):
anyTurtle.fillcolor(vcolor)
anyTurtle.begin_fill()
circumference = 2 * 3.14159 * radius
#Calculate number of sides so that each side is approximately 1 pixel
numSides = int(0.5 + circumference)
sideLength = circumference / numSides
print('side length = {0}, number of sides = {1}'.format(sideLength, numSides))
drawPolygon(anyTurtle, sideLength, numSides)
anyTurtle.end_fill()
wn = turtle.Screen()
#Set minimum canvas update delay
wn.delay(1)
wheel = turtle.Turtle()
#Set fastest turtle speed
wheel.speed(0)
#wheel.hideturtle()
radius = 20
#Move to the bottom of the circle, so
#that the filled circle will be centered.
wheel.up()
wheel.goto(0, -radius)
wheel.down()
drawFilledCircle(wheel, radius, 'purple')
#Move turtle to the center of the circle
wheel.up()
wheel.goto(0, 0)
#wheel.showturtle()
wn.exitonclick()
Related
I want to draw a flower with turtle. Although I am facing problem in centering the flower (0,0) should be flower's center or where turtle initially is spawned. How can I center it?
import turtle
import math
turtle.speed(-1)
def Flower():
global radius, num_of
for i in range(num_of):
turtle.setheading(i * 360/num_of)
turtle.circle(radius*3.5/num_of,180)
radius = 50
num_of = 10
Flower()
I tried setting turtle to where it starts drawing but number of sides ruin it.
Since the turtle draws from a edge, we need to move the turtle to compensate for the radius of the entire image. To simplify this move, we align the starting point of the image with one (X) axis. We also switch from absolute coordinates (setheading()) to relative coordinates (right()) so our initial rotational offset doesn't get lost or need to be added to every position:
import turtle
import math
radius = 50
num_of = 13
def flower():
outer_radius = radius * 3.5 / math.pi
turtle.penup()
turtle.setx(-outer_radius) # assumes heading of 0
turtle.pendown()
turtle.right(180 / num_of)
for _ in range(num_of):
turtle.right(180 - 360 / num_of)
turtle.circle(radius * 3.5 / num_of, 180)
turtle.speed('fastest')
turtle.dot() # mark turtle starting location
flower()
turtle.hideturtle()
turtle.done()
To get the radius of the flower, we add up the diameters of all the petals and use the standard circumference to radius formula. There are probably simplifications, math-wise and code-wise, we could make.
For a school project, I'm using Python Turtle to make an "avatar". I have curly hair, so I wrote some code to draw a black half-circle, every 10-ish degrees it stops, and makes a much smaller circle of the same color, then resumes.
The code works? It does what it's supposed to do for the first 3 smaller circles, but it seems to be random on the 4th smaller circle. I've even set the degrees to draw the half-circle to 10000 and it only completed the 4th smaller circle by 3/4ths.
import turtle
t = turtle.Turtle() #defining Turtle
def drawHair():
##debug, getting turtle to needed pos.
t.color("Moccasin")
for x in range (90):
t.forward(2.5)
t.left(1)
t.setheading(90)
##
t.color("Black")
cTime = 0 #"Timer" to determine a smaller "Curl"
for x in range (180): #SUPPOSED to draw a half-circle
t.forward(2.5) #
t.left(1) #
cTime = cTime + 1 ##For every "Degree" in the main half-circle,
##add 1 to the "Timer"
print("circle = " + str(cTime)) #debug
if cTime == 10: #If "Timer has reached it's limit"
cTime = 0 #Reset timer
for x in range (360): #Draw a full, smaller circle
t.forward(-0.4) #
t.left(1) #
I know this is more complicated than it should be. I simply want to know why this problem happens and how to fix it.
EDIT : https://imgur.com/a/uYe6UAb (Proof)
You are doing way too many draws, which repl.it seems to not like. There is actually a circle method in Turtle that draws circles (and semicircles) for you! This is a lot faster than drawing it with for loops.
Using this, and a bit of maths, I have come up with this code:
import turtle
from math import cos, sin, pi
t = turtle.Turtle() #defining Turtle
def drawHair():
##debug, getting turtle to needed pos.
t.color("Moccasin")
t.radians()
t.setheading(-pi / 2)
t.circle(140, extent=pi) # bottom semi circle
t.color("Black")
t.circle(140, extent=pi) # top semi circle
for x in range(19):
t.penup()
t.goto(cos(x*pi/18)*180+140, sin(x*pi/18)*180) # position for each curl
t.setheading(x*pi/18 + pi/2)
t.pendown()
t.circle(20)
drawHair()
I've basically used the parametric form of the equation for a circle. This is the result:
Tne problem may be that you're drawing circles that are too detailed for repl.it -- although your code should work, even Python turtle's own circle() function uses only 60 segments, not 360, to draw a circle. Even less for small circles.
Here's a rework of your code to draw all your circles in fewer segments, synchronized with your desire to draw the smaller circles every 10 degrees:
import turtle
def drawHair():
# get turtle to needed position
t.color("Moccasin")
for x in range(15):
t.forward(15)
t.left(6)
t.color("Black")
for x in range(36): # draw a half-circle
t.forward(12.5)
t.left(5)
if x % 2 == 0: # every other segment of the outer circle
for _ in range(72): # Draw a full, smaller circle
t.forward(-2)
t.left(5)
t.color("Moccasin") # finish the face outline
for x in range(15):
t.forward(15)
t.left(6)
t.hideturtle()
t = turtle.Turtle()
drawHair()
turtle.done()
I seems to work on repl.it for me. (Though repl.it does have lengthy pauses.) And the circles still appear round despite the reduced segments:
I assumed that you weren't allowed to use the turtle.circle() method, but if you can, as #Sweeper assumes, then this becomes a much simpler program:
import turtle
def drawHair():
# get turtle to needed position
t.color("Moccasin")
t.circle(143, 90)
t.color("Black")
for x in range(18): # draw a half-circle
t.circle(143, 5)
t.circle(-23) # draw a full, smaller circle
t.circle(143, 5)
t.color("Moccasin")
t.circle(143, 90)
t.hideturtle()
t = turtle.Turtle()
drawHair()
turtle.done()
You'll see the circles are slightly cruder than my first example but you can tune this using the steps parameter of turtle.circle().
Currently, I'm trying to make a game and in the game I would like it so if the character is on top of an object, it picks it up. This is what I have so far:
import turtle
import time
default = turtle.clone()
scar = turtle.clone()
def pickupScar():
if default.distance(-7,48) > 5.0:
default.changeshape('defaultscar.gif')
wn = turtle.Screen()
wn.setup(500,500)
wn.bgpic('TrumpTowers.gif')
wn.register_shape('default.gif')
wn.register_shape('scar.gif')
wn.register_shape('defaultscar.gif')
turtle.hideturtle()
default.shape('default.gif')
scar.shape('scar.gif')
default.pu()
default.left(90)
default.bk(35)
scar.pu()
scar.left(90)
scar.fd(45)
scar.speed(-1)
default.ondrag(default.goto)
Does anybody know how I would go with making the def pickupScar as I'm new to python & turtle. If you recognize what my game is about please don't judge me, it's for a school project and I couldn't think of any game ideas.
Since I don't have your images, nor recognize what your game is about, below is an example of the functionality you describe. On the screen is a black circle and pink square. You can drag the circle and if you drag it onto the square, it will sprout a head and legs becoming a turtle. Dragging off the square, it reverts to being a circle:
from turtle import Screen, Turtle
def drag(x, y):
default.ondrag(None) # disable handler inside handler
default.goto(x, y)
if default.distance(scar) < 40:
default.shape('turtle')
elif default.shape() == 'turtle':
default.shape('circle')
default.ondrag(drag)
wn = Screen()
wn.setup(500, 500)
scar = Turtle('square', visible=False)
scar.shapesize(4)
scar.color('pink')
scar.penup()
scar.left(90)
scar.forward(50)
scar.showturtle()
default = Turtle('circle', visible=False)
default.shapesize(2)
default.speed('fastest')
default.penup()
default.left(90)
default.backward(50)
default.showturtle()
default.ondrag(drag)
wn.mainloop()
I dont know the turtle-graphics, but in real world to determine the distance between two points (for 2D surfaces) we use Pythagorean theorem.
If some object is at (x1, y1) and another at (x2, y2), the distance is
dist=sqrt((x1-x2)^2 + (y1-y2)^2)
So, if dist <= R, turtle (or whatever) is in R radius from desired point
My task is to write a function, drawCircle(radius,fillColor), that asks a user for the specific radius of the circle and which color they'd like the circle to be filled.
I have the circle-drawing down, but I'm struggling with getting the circle to fill with the user-defined color. Any help would be greatly appreciated.
import turtle
def drawCircle(radius, fillColor):
x=360/300 #This gives the angle
r=radius#This is the radius of the circle.
c=fillColor
c=str("")
z=1 #Placeholder for the while loop.
win=turtle.Screen()
tom=turtle.Turtle()
fillColor=tom.color()
tom.begin_fill()
while (z<=300):
tom.forward(r)
tom.right(x)
tom.forward(r)
z=z+1
win.exitonclick()
tom.end_fill()
This is my function call: drawCircle(1,"red")
There are several problems with your code:
You call win.exitonclick before tom.end_fill, so programm exits before filling (as it happens on end_fill)
You do "fillColor=tom.color()" with gets you current color. Instead use "tom.fillcolor(fillColor)"
Unnecessary copying of variables radius->r and fillColor->c
This is python. Use for whenever possible. Instead of counting using z use:
for _ in range(300):
My final code:
import turtle
def drawCircle(radius, fillColor):
x = 360/300 # This gives the angle
win = turtle.Screen()
tom = turtle.Turtle()
tom.fillcolor(fillColor)
tom.begin_fill()
for _ in range(300):
tom.forward(radius)
tom.right(x)
tom.forward(radius)
tom.end_fill()
win.exitonclick()
drawCircle(1, "red")
I have the circle-drawing down
Before addressing your fill issue, I'd argue that your premise isn't true, you don't have circle-drawing down. As #Mysak0CZ shows, your circle of radius 1 is huge -- 1 what? You're drawing a circle but have no real control over its size.
As a professional turtle wrangler, I'd go about the problem as follows. Not only your angle needs to be divided by the number of segments you plan to draw, but you need to compute a circumference based on the requested radius and chop that up as well. I do so below and include a call to turtle's own .circle() method to show that we're in the right ballpark. And I fix your minor fill issue:
import math
from turtle import Turtle, Screen # force object-oriented turtles
SEGMENTS = 60 # how many lines make up the circle
def drawCircle(radius, fillColor):
distance = math.pi * radius * 2 / SEGMENTS # circumference / SEGMENTS
angle = 360 / SEGMENTS
turtle.fillcolor(fillColor)
turtle.begin_fill()
for _ in range(SEGMENTS):
turtle.forward(distance)
turtle.left(angle) # left for .circle() compatibility
turtle.end_fill()
screen = Screen()
turtle = Turtle()
drawCircle(100, 'red')
turtle.circle(100) # for comparison
screen.exitonclick()
Here is my code for a pink circle if you are going through the same Python learning resource. I think the original code was missing an argument.
import turtle
def drawPolygon(t, sideLength, numSides):
t.goto(0, 0)
turnAngle = 360 / numSides
for i in range(numSides):
t.forward(sideLength)
t.right(turnAngle)
def drawCircle(anyTurtle, radius):
circumference = 2 * 3.1415 * radius
sideLength = circumference / 360
drawPolygon(anyTurtle, sideLength, 360)
def drawFilledCircle(anyTurtle, radius, color):
anyTurtle.fillcolor(color)
anyTurtle.begin_fill()
drawCircle(anyTurtle, radius)
anyTurtle.end_fill()
anyTurtle.hideturtle()
wn = turtle.Screen()
wheel = turtle.Turtle()
drawFilledCircle(wheel, 80, "pink")
wn.exitonclick()
I'm looking for best way to automatically find starting position for new turtle drawing so that it would be centered in graphics window regardless of its size and shape.
So far I've developed a function that checks with each drawn element turtle position to find extreme values for left, right, top and bottom and that way I find picture size and can use it to adjust starting position before releasing my code. This is example of simple shape drawing with my picture size detection added:
from turtle import *
Lt=0
Rt=0
Top=0
Bottom=0
def chkPosition():
global Lt
global Rt
global Top
global Bottom
pos = position()
if(Lt>pos[0]):
Lt = pos[0]
if(Rt<pos[0]):
Rt= pos[0]
if(Top<pos[1]):
Top = pos[1]
if(Bottom>pos[1]):
Bottom = pos[1]
def drawShape(len,angles):
for i in range(angles):
chkPosition()
forward(len)
left(360/angles)
drawShape(80,12)
print(Lt,Rt,Top,Bottom)
print(Rt-Lt,Top-Bottom)
This method does work however it seems very clumsy to me so I would like to ask more experiences turtle programmers is there a better way to find starting position for turtle drawings to make them centered?
Regards
There is no universal method to center every shape (before you draw it and find all your max, min points).
For your shape ("almost" circle) you can calculate start point using geometry.
alpha + alpha + 360/repeat = 180
so
alpha = (180 - 360/repeat)/2
but I need 180-alpha to move right (and later to move left)
beta = 180 - aplha = 180 - (180 - 360/repeat)/2
Now width
cos(alpha) = (lengt/2) / width
so
width = (lengt/2) / cos(alpha)
Because Python use radians in cos() so I need
width = (length/2) / math.cos(math.radians(alpha))
Now I have beta and width so I can move start point and shape will be centered.
from turtle import *
import math
# --- functions ---
def draw_shape(length, repeat):
angle = 360/repeat
# move start point
alpha = (180-angle)/2
beta = 180 - alpha
width = (length/2) / math.cos(math.radians(alpha))
#color('red')
penup()
right(beta)
forward(width)
left(beta)
pendown()
#color('black')
# draw "almost" circle
for i in range(repeat):
forward(length)
left(angle)
# --- main ---
draw_shape(80, 12)
penup()
goto(0,0)
pendown()
draw_shape(50, 36)
penup()
goto(0,0)
pendown()
draw_shape(70, 5)
penup()
goto(0,0)
pendown()
exitonclick()
I left red width on image.
I admire #furas' explanation and code, but I avoid math. To illustrate that there's always another way to go about a problem here's a math-free solution that produces the same concentric polygons:
from turtle import Turtle, Screen
def draw_shape(turtle, radius, sides):
# move start point
turtle.penup()
turtle.sety(-radius)
turtle.pendown()
# draw "almost" circle
turtle.circle(radius, steps=sides)
turtle = Turtle()
shapes = [(155, 12), (275, 36), (50, 5)]
for shape in shapes:
draw_shape(turtle, *shape)
turtle.penup()
turtle.home()
turtle.pendown()
screen = Screen()
screen.exitonclick()