Python Drawing a Circle with X Radius Using Forward() - python

I'm using Python Turtles to draw a circle using forward() and right().
I have a for loop counting from 0 to 359, and each time it triggers, it moves the turtle forward 1 and right 1.
But the problem is I need specific diameters. I am nearly 100% sure I'll need to use trig, but I've tried to no avail.
I can't figure out the math how to do it. We're supposed to use forward() and right(), NOT circle().
Thanks!

Here is a working example:
import turtle
import math
def circle(radius):
turtle.up()
# go to (0, radius)
turtle.goto(0,radius)
turtle.down()
turtle.color("black")
# number of times the y axis has been crossed
times_crossed_y = 0
x_sign = 1.0
while times_crossed_y <= 1:
# move by 1/360 circumference
turtle.forward(2*math.pi*radius/360.0)
# rotate by one degree (there will be
# approx. 360 such rotations)
turtle.right(1.0)
# we use the copysign function to get the sign
# of turtle's x coordinate
x_sign_new = math.copysign(1, turtle.xcor())
if(x_sign_new != x_sign):
times_crossed_y += 1
x_sign = x_sign_new
return
circle(100)
print('finished')
turtle.done()

Well, a complete circle is 360°, and you are planning on turning 360 times, so each turn should be:
right( 360 ° / 360 ), or
right(1)
The distance traveled will be one circumference, or π * diameter, so your forward might be:
forward( diameter * π / 360 )
I haven't tested this yet -- give it a try and see how it works.

This is one of the exercises in "Think Python," in chapter 4. It really is a horrible exercise to have this early in the book, especially with the "hint" given. I'm using forward and left here, but you can switch left with right.
You should have the polygon function:
def polygon(t, length, n):
for i in range(n):
bob.fd(length)
bob.lt(360 / n)
Then you create a circle function:
def circle(t):
polygon(t, 1, 360)
That will draw a circle, no radius needed. The turtle goes forward 1, then left 1 (360 / 360), 360 times.
Then, if you want to make the circle bigger, you calculate the circumference of the circle. The hint says:
Hint: figure out the circumference of the circle and make sure that
length * n = circumference.
Ok, so the formula for circumference = 2 * pi * radius. And the hint says length * n = circumference. n = 360 (number of sides/degrees). We have circumference, so we need to solve for length.
So:
def circle(t, r):
circumference = 2 * 3.14 * r
length = circumference / 360
polygon(t, length, 360)
Now, call the function with whatever radius you want:
circle(bob, 200)

Related

How do I generate monteCarlopi function in a given circle/square?

Write a function monteCarloPi(n, radius) that takes two arguments, the number of simulations n and the radius of the circle, and returns a float, which is the estimated value for pi. This radius should be the same radius that you used to draw your inscribed circle in the previous problem. Generate a set of random points, and test to see if that value is inside the circle or outside the circle. Use turtle to draw a dot at each location. This can be done using the function turtle.dot(size, color). Find the ratio of the points inside the circle to the number of points in the simulation. The latter number is an estimate for the area of the square. Multiple the ratio by four to get your estimate for pi.
This is what I have and I have no idea why it only draws one dot. Can anybody help me? I am a beginner /:
import turtle as t
import random
def monteCarloPi(n, radius):
'''
Takes two arguments, the number of simulations n and the radius of the circle, and returns a float, which is the estimated value for pi.
'''
t.dot() # Origin (0, 0)
t.pu()
t.goto(0, -radius)
t.pd()
t.circle(radius)
t.pu()
t.goto(-radius ,-radius)
t.pd()
for square in range(4):
t.fd(radius * 2)
t.lt(90)
points_in_circle = 0
points_in_square = 0
x = random.uniform(-radius, radius)
y = random.uniform(-radius, radius)
for dots in range(n):
t.pu()
t.goto(x, y)
t.dot()
origin = x ** 2 + y ** 2
if origin <=1 :
points_in_circle += 1
else:
points_in_square +=1
pi = 4 * (points_in_circle / points_in_square)
return pi
I see a number of potential problems with your code. The last two lines shown aren't indented correctly, they should be after the loop, not in it.
This equation origin = x ** 2 + y ** 2 seems incorrect and might need to instead be origin = (x ** 2 + y ** 2) ** 0.5
These two statements:
x = random.uniform(-radius, radius)
y = random.uniform(-radius, radius)
need to be at the top of the loop, not before the loop, otherwise you're plotting the same point n times, instead of n points. This calculation seems wrong:
pi = 4 * (points_in_circle / points_in_square)
reread the instructions you provided above. You should be dividing by n not points_in_square. This doesn't seem correct:
if origin <=1 :
as we're not working with a unit circle, so I'd expect:
if origin <= radius:
The reworked code based on my above observations:
from turtle import Screen, Turtle
from random import uniform
def monteCarloPi(n, radius):
'''
Takes two arguments, the number of simulations n and the radius of the circle,
and returns a float, which is the estimated value for pi.
'''
turtle.dot() # Origin (0, 0)
turtle.penup()
turtle.sety(-radius)
turtle.pendown()
turtle.circle(radius)
turtle.penup()
turtle.setx(-radius)
turtle.pendown()
for _ in range(4):
turtle.forward(radius * 2)
turtle.left(90)
turtle.penup()
turtle.hideturtle()
points_in_circle = 0
for _ in range(n):
x = uniform(-radius, radius)
y = uniform(-radius, radius)
turtle.goto(x, y)
turtle.dot()
origin = (x ** 2 + y ** 2) ** 0.5
if origin <= radius:
points_in_circle += 1
pi = 4 * points_in_circle / n
return pi
screen = Screen()
turtle = Turtle()
turtle.speed('fastest') # because I have no patience
print(monteCarloPi(100, 100))
screen.exitonclick()

How do I draw this shape in Turtle? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I got a challenge in a learning group today to draw this shape in python turtle library.
I cannot figure out a way to express the geometrical solution to find the angles to turn and the size of the line I need.
Can you please tell me how to draw the first polygon alone? I already know how to make the pattern.
I am in fifth grade. So please give me a solution that I can understand.
Here is the solution I came up with. It is based on this diagram:
Math background
My solution uses "trigonometry", which is a method for calculating the length of one side of a triangle from the length of another side and the angles of the triangle. This is advanced math which I would expect to be taught maybe in 9th or 10th grade. I do not expect someone in 5th grade to know trigonometry. Also I cannot explain every detail of trigonometry, because I would have to write a lot and I do not think I have the teaching skills to make it clear. I would recommend you to look at for example this video to learn about the method:
https://www.youtube.com/watch?v=5tp74g4N8EY
You could also ask your teacher for more information, or research about it on the internet on your own.
Step 1: Calculating the angles
We can do this without trigonometry.
First, we see there is a "pentagon" (5-sided polygon) in the middle. I want to know the inner angle of a corner in this "pentagon". I call this angle X:
How can we calculate the angle X? We first remember that the sum of the inner angles in a triangle is 180°. We see that we can divide a 5-sides polygon into 5-2 triangles like this:
The sum of the inner angle of each of these 5-2 triangles is 180°. So for the whole 5-sided polygon, the sum of the inner angles is 180° * (5-2). Since all angles have the same size, each angle is 180°*(5-2) / 5 = 108°. So we have X = 108°.
The angle on the other side is the same as X. This allows us the calculate the angle between the two X. I will call this angle Y:
Since a full circle is 360°, we know that 360° = 2*X + 2*Y. Therefore, Y = (360° - 2*X) / 2. We know that X = 108°, so we get Y = 72°.
Next, we see there is a triangle containing the Y angle. I want to know the angle Z at the other corner of the triangle:
The inner angles of a triangle sum up to 180°*(3-2) = 180°. Therefore, we know that 180° = 2*Y + Z, so Z = 180° - 2*Y. We know that Y = 72°, so we get Z = 36°.
We will use the angle Z a lot. You can see that every corner of the green star has angle Z. The blue star is the same as the green star except it is rotated, so all blue corners also have angle Z. The corners of the red star are twice as wide as the corners of the green and blue stars, so the corners of the red star have the angle 2*Z.
Step 2: Calculating the lengths
First, we observe that all outer corners are on a circle. We call the radius of this circle R. We do not have to calculate R. Instead, we can take any value we want for R. We will always get the same shape but in different sizes. We could call R a "parameter" of the shape.
Given some value for R, I want to know the following lengths:
Calculating A:
We start with A. We can see the following triangle:
The long side of the triangle is our radius R. The other side has length A/2 and we do not care about the third side. The angle in the right-most corner is Z/2 (with Z = 36° being the angle we calculated in the previous section). The angle S is a right-angle, so S = 90°. We can calculate the third angle T because we know that the inner angles of a triangle sum up to 180°. Therefore, 180° = S + Z/2 + T. Solving for T, we get T = 180° - S - Z/2 = 180° - 90° - 36°/2 = 72°.
Next, we use trigonometry to calculate A/2. Trigonometry teaches us that A/2 = R * sin(T). Putting in the formula for T, we get A/2 = R * sin(72°). Solving for A, we get A = 2*R*sin(72°).
If you pick some value for R, for example R = 100, you can now calculate A with this formula. You would need a calculator for sin(72°), because it would be extremely difficult to calculate this in your head. Putting sin(72) into my calculator gives me 0.951056516. So for our choice R = 100, we know that A = 2 * R * sin(72°) = 2 * 100 * 0.951056516 = 190.211303259.
Calculating B:
We use the same technique to find a formula for B. We see the following triangle:
So the bottom side is the length of our radius R. The right side is B/2. We do not care about the third side. The right-most angle is three times Z/2. The angle S is a right-angle, so we have S = 90°. We can calculate the remaining angle T with 180° = S + T + 3*Z/2. Solving for T, we get T = 180° - S - 3*Z/2 = 180° - 90° - 3*36°/2 = 36°. Ok so T = Z, we could have also seen this from the picture, but now we have calculated it anyways.
Using trigonometry, we know that B/2 = R * sin(T), so we get the formula B = 2 * R * sin(36°) to calculate B for some choice of R.
Calculating C:
We see the following triangle:
So the bottom side has length A/2 and the top side has length B. We already have formulas for both of these sides. The third side is C, for which we want to find a formula. The right-most angle is Z. The angle S is a right-angle, so S = 90°. The top-most angle is three times Z/2.
Using trigonometry, we get C = sin(Z) * B.
Calculating D:
We see the following triangle:
We already have a formula for C. We want to find a formula for D. The top-most angle is Z/2 (I could not fit the text into the triangle). The bottom-left angle S is a right-angle.
Using trigonometry, we know that D = tan(Z/2) * C. The tan function is similar to the sin from the previous formulas. You can again put it into your calculator to compute the value, so for Z = 36°, I can put tan(36/2) into my calculator and it gives me 0.324919696.
Calculating E:
Ok this is easy, E = 2*D.
Halfway done already!
Calculating F:
This is similar to A and B:
We want to find a formula for F. The top side has length F/2. The bottom side has the length of our radius R. The right-most corner has angle Z. S is a right-angle. We can calculate T = 180° - S - Z = 180° - 90° - Z = 90° - Z.
Using trigonometry, we get F/2 = R * sin(T). Putting in the formula for T gives us F/2 = R*sin(90° - Z). Solving for F gives us F = 2*R*sin(90°-Z).
Calculating G:
We see the following triangle:
The top side has length F, we already know a formula for it. The right side has length G, we want to find a formula for it. We do not care about the bottom side. The left-most corner has angle Z/2. The right-most corner has angle 2*Z. The bottom corner has angle S, which is a right-angle, so S = 90°. It was not immediately obvious to me that the red line and the green line are perfectly perpendicular to each other so that S really is a right-angle, but you can verify this by using the formula for the inner angles of a triangle, which gives you 180° = Z/2 + 2*Z + S. Solving for S gives us S = 180° - Z/2 - 2*Z. Using Z = 36°, we get S = 180° - 36°/2 - 2* 36° = 90°.
Using trigonometry, we get G = F * sin(Z/2).
Calculating H:
We see the following triangle:
The right side has length G, we already have formula for that. The bottom side has length H, we want to find a formula for that. We do not care about the third side. The top corner has angle Z, the bottom-right corner has angle S. We already know that S is a right-angle from the last section.
Using trigonometry, we get H = G * tan(Z).
Calculating I:
This is easy, I is on the same line as A. We can see that A can be divided into A = I + H + E + H + I. We can simplify this to A = 2*I + 2*H + E. Solving for I gives us I = (A - 2*H - E)/2.
Calculating J:
Again this is easy, J is on the same line as F. We can see that F can be divided into F = G + J + G. We can simplify that to F = 2*G + J. Solving for J gives us J = F - 2*G.
Writing the Python program
We now have formulas for all the lines we were interested in! We can now put these into a Python program to draw the picture.
Python gives you helper functions for computing sin and tan. They are contained in the math module. So you would add import math to the top of your program, and then you can use math.sin(...) and math.tan(...) in your program. However, there is one problem: These Python functions do not use degrees to measure angles. Instead they use a different unit called "radians". Fortunately, it is easy to convert between degrees and radians: In degrees a full circle is 360°. In radians, a full circle is 2*pi, where pi is a special constant that is approximately 3.14159265359.... Therefore, we can convert an angle that is measured in degrees into an angle that is measured in radians, by dividing the angle by 360° and then multiplying it by 2*pi. We can write the following helper functions in Python:
import math
def degree_to_radians(angle_in_degrees):
full_circle_in_degrees = 360
full_circle_in_radians = 2 * math.pi
angle_in_radians = angle_in_degrees / full_circle_in_degrees * full_circle_in_radians
return angle_in_radians
def sin_from_degrees(angle_in_degrees):
angle_in_radians = degree_to_radians(angle_in_degrees)
return math.sin(angle_in_radians)
def tan_from_degrees(angle_in_degrees):
angle_in_radians = degree_to_radians(angle_in_degrees)
return math.tan(angle_in_radians)
We can now use our functions sin_from_degrees and tan_from_degrees to compute sin and tan from angles measured in degrees.
Putting it all together:
from turtle import *
import math
# Functions to calculate sin and tan ###########################################
def degree_to_radians(angle_in_degrees):
full_circle_in_degrees = 360
full_circle_in_radians = 2 * math.pi
angle_in_radians = angle_in_degrees / full_circle_in_degrees * full_circle_in_radians
return angle_in_radians
def sin_from_degrees(angle_in_degrees):
angle_in_radians = degree_to_radians(angle_in_degrees)
return math.sin(angle_in_radians)
def tan_from_degrees(angle_in_degrees):
angle_in_radians = degree_to_radians(angle_in_degrees)
return math.tan(angle_in_radians)
# Functions to calculate the angles ############################################
def get_X():
num_corners = 5
return (num_corners-2)*180 / num_corners
def get_Y():
return (360 - 2*get_X()) / 2
def get_Z():
return 180 - 2*get_Y()
# Functions to calculate the lengths ###########################################
def get_A(radius):
Z = get_Z()
return 2 * radius * sin_from_degrees(90 - Z/2)
def get_B(radius):
Z = get_Z()
return 2 * radius * sin_from_degrees(90 - 3*Z/2)
def get_C(radius):
Z = get_Z()
return sin_from_degrees(Z) * get_B(radius)
def get_D(radius):
Z = get_Z()
return tan_from_degrees(Z/2) * get_C(radius)
def get_E(radius):
return 2 * get_D(radius)
def get_F(radius):
Z = get_Z()
return 2 * radius * sin_from_degrees(90 - Z)
def get_G(radius):
Z = get_Z()
return get_F(radius) * sin_from_degrees(Z/2)
def get_H(radius):
Z = get_Z()
return get_G(radius) * tan_from_degrees(Z)
def get_I(radius):
A = get_A(radius)
E = get_E(radius)
H = get_H(radius)
return (A - E - 2*H) / 2
def get_J(radius):
F = get_F(radius)
G = get_G(radius)
return F - 2*G
# Functions to draw the stars ##################################################
def back_to_center():
penup()
goto(0, 0)
setheading(0)
pendown()
def draw_small_star(radius):
penup()
forward(radius)
pendown()
Z = get_Z()
left(180)
right(Z/2)
E = get_E(radius)
H = get_H(radius)
I = get_I(radius)
for i in range(0,5):
penup()
forward(I)
pendown()
forward(H)
penup()
forward(E)
pendown()
forward(H)
penup()
forward(I)
left(180)
right(Z)
back_to_center()
def draw_green_star(radius):
pencolor('green')
draw_small_star(radius)
def draw_blue_star(radius):
pencolor('blue')
Z = get_Z()
left(Z)
draw_small_star(radius)
def draw_red_star(radius):
pencolor('red')
Z = get_Z()
penup()
forward(radius)
pendown()
left(180)
right(Z)
G = get_G(radius)
J = get_J(radius)
for i in range(0,10):
pendown()
forward(G)
penup()
forward(J)
pendown()
forward(G)
left(180)
right(2*Z)
back_to_center()
def draw_shape(radius):
draw_green_star(radius)
draw_blue_star(radius)
draw_red_star(radius)
radius = 400
draw_shape(radius)
done()
Output:
Here's a different solution. It's based on a kite polygon where the upper portion is a pair of 3-4-5 right triangles and the lower portion is a pair of 8-15-17 right triangles:
from turtle import Screen, Turtle
KITES = 10
RADIUS = 100
def kite(t):
t.right(37)
t.forward(100)
t.right(81)
t.forward(170)
t.right(124)
t.forward(170)
t.right(81)
t.forward(100)
t.right(37)
turtle = Turtle()
turtle.penup()
turtle.sety(-RADIUS)
for _ in range(KITES):
turtle.circle(RADIUS, extent=180/KITES)
turtle.pendown()
kite(turtle)
turtle.penup()
turtle.circle(RADIUS, extent=180/KITES)
turtle.hideturtle()
screen = Screen()
screen.exitonclick()
(Yes, I'm obsessed with this puzzle.) I was sufficiently impressed by the brevity of #AnnZen's solution, I decided to see if I could come up with an even shorter one. The only unique structure in this polygon is the side of the kite:
So the problem becomes drawing ten of these in a circular fashion, and then reversing the code to draw them again in the opposite direction:
from turtle import *
for _ in range(2):
for _ in range(10):
fd(105)
lt(90)
fd(76.5)
pu()
bk(153)
rt(54)
pd()
lt(72)
lt, rt = rt, lt
done()
My Short code:
from turtle import *
for f, t in [(0,-72),(71,108),(71,0)]*10+[(29,90),(73,72),(73,90),(29,72)]*10:fd(f),rt(t)
Here's the solution:
import turtle
#turtle.tracer(0)
a = turtle.Turtle()
for _ in range(10):
a.forward(100)
a.right(90)
a.forward(73)
a.right(72)
a.forward(73)
a.backward(73)
a.right(108)
a.forward(73)
a.right(90)
a.penup()
a.forward(100)
a.pendown()
a.forward(100)
a.right(108)
#turtle.update()
Let's look at a yet another approach to drawing this shape. We'll start with the same diagram as #f9c69e9781fa194211448473495534
Using a ruler (1" = 100px) and protractor on the OP's original image, we can approximate this diagram with very simple code:
from turtle import Screen, Turtle
turtle = Turtle()
turtle.hideturtle()
turtle.penup() # center on the screen
turtle.setposition(-170, -125)
turtle.pendown()
for _ in range(10):
turtle.forward(340)
turtle.left(126)
turtle.forward(400)
turtle.left(126)
screen = Screen()
screen.exitonclick()
This is equivalent to drawing with a pencil and not lifting it nor overdrawing (backing up) on any line.
To make the shape we want pop out, we divide the two lines that we draw above into segments that are thinner and thicker. The first line breaks into three segments and the second into five:
To do this, we simply break the forward() calls in our loop into wide and narrow segments:
for _ in range(10):
turtle.width(4)
turtle.forward(105)
turtle.width(1)
turtle.forward(130)
turtle.width(4)
turtle.forward(105)
turtle.left(126)
turtle.width(1)
turtle.forward(76.5)
turtle.width(4)
turtle.forward(76.5)
turtle.width(1)
turtle.forward(94)
turtle.width(4)
turtle.forward(76.5)
turtle.width(1)
turtle.forward(76.5)
turtle.left(126)
Finally, we replace the thickness changes with lifting and lowering the pen:
Which is simply a matter of replacing the width() calls with penup() and pendown():
for _ in range(10):
turtle.pendown()
turtle.forward(105)
turtle.penup()
turtle.forward(130)
turtle.pendown()
turtle.forward(105)
turtle.left(126)
turtle.penup()
turtle.forward(76.5)
turtle.pendown()
turtle.forward(76.5)
turtle.penup()
turtle.forward(94)
turtle.pendown()
turtle.forward(76.5)
turtle.penup()
turtle.forward(76.5)
turtle.left(126)

Using recursion to draw nested Triangles

I'd like to draw a series of nested triangles using recursion.
My faulty code below:
def recursiveTri(x, y, shrink):
tt.penup()
tt.setx(x)
tt.sety(y)
if x > -10:
return
for element in range(3):
tt.pendown()
tt.forward(x)
tt.right(120)
recursiveTri(x + shrink, y - shrink, shrink)
def main():
recursiveTri(-300,300,30)
main()
The current code produces the following:
Here is what I mean by nested shapes, except that I would like to draw triangles instead of squares:
And now, just for fun, the "better living through stamping" solution:
import turtle
CURSOR_SIZE = 20
def recursiveTri(side, shrink):
if side > 10:
turtle.shapesize(side / CURSOR_SIZE)
turtle.stamp()
recursiveTri(side - shrink, shrink)
turtle.hideturtle()
turtle.shape('triangle')
turtle.fillcolor('white')
recursiveTri(300, 30)
turtle.dot()
turtle.exitonclick()
This is the default orientation, you can turn it anyway you want before calling recursiveTri(). Stamping is an alternative to drawing that works best with simple geometric patterms like this.
The problem is with
tt.forward(x)
Remember that your x is always negative, and the length of a side is not x, but rather -2 * x, if you want to be symmetrical about zero. Since your triangles are nested, you can also compute the initial y from x, given that it is 1/3 of the way up the main bisector. -sqrt(3) / 3 * x therefore puts the center of the circles circumscribed around and inscribed in your triangle at 0, 0.
In fact, it is probably easier to just fix the length of a side, and compute x and y from that:
import turtle as tt
from math import sqrt
def recursiveTri(side, shrink):
if side < 10: return
tt.penup()
tt.goto(-side / 2, sqrt(3) / 6 * side)
tt.pendown()
for _ in range(3):
tt.forward(side)
tt.right(120)
recursiveTri(side - shrink, shrink)
tt.penup()
tt.home()
tt.dot()
recursiveTri(300, 30)
In this case, shrink is the total amount removed from each side. If you want it to be the amount you step forward, change the recursive call to recursiveTri(side - 2 * shrink, shrink).
The result (without multiplying shrink by 2) is

Polygon divided into isosceles triangle in python

I wanted to draw a polygon divided into the isosceles triangle in python. I tried this code below but there seems to be an error in the variable inside angle.
why does the arrow move backwards? it was supposed to move towards the centre though. Please help me find the bug. Thanks in advance.
import math
import turtle
bob = turtle.Turtle()
bob.speed(1)
def triangularpolygon (t,length,n):
angle = (n-2)*180/n
insideangle=angle/2
rotatingangle=180-insideangle
centrelength = length/2/math.cos(insideangle)
t.fd(centrelength)
for i in range(n):
t.fd(length)
t.lt(rotatingangle)
t.fd(centrelength)
t.bk(centrelength)
t.rt(insideangle)
triangularpolygon(bob,100,6)
There are no error messages. I think the value for the cosine of the angle is negative.
I believe your turtle moves in the wrong direction, and not far enough, because your math is wrong. You're mixing degrees (turtle's default) with radians (math.cos() expectation):
angle = (n-2)*180/n
insideangle=angle/2
centrelength = length/2/math.cos(insideangle)
Your cos() call is returning a negative value -- forward() with a negative value is backward() and vice versa. Let's rework the math and also switch turtle to radians (not required but makes the code consistent):
from math import pi, sin as sine
from turtle import Screen, Turtle
def triangular_polygon(turtle, length, n):
inside_angle = (n - 2) * pi / n / 2
rotating_angle = pi - inside_angle
radius = length / (2 * sine(pi / n))
turtle.penup()
turtle.forward(radius)
turtle.left(rotating_angle)
turtle.pendown()
for _ in range(n):
turtle.forward(length)
turtle.left(rotating_angle)
turtle.forward(radius)
turtle.backward(radius)
turtle.right(inside_angle)
screen = Screen()
bob = Turtle()
bob.radians() # switch turtle to radians to match math functions
bob.speed('slowest')
bob.dot() # mark the center of our screen for reference
triangular_polygon(bob, 100, 6)
bob.hideturtle()
screen.exitonclick()

Create a square with sides at any angle

I am trying to create a rotating turret. The turret rotates correctly the problem is when I make the turret shoot with the space bar the bullet isn't the same size or shape at every angle. I tried using the angle that the turret is facing to do some trig calculations and find the two corner points needed to create the bullet (which is a circle). Nothing I have tried will work. Here is the code:
Barrel = [260,210,270,210,270,170,260,170]
def RotateBarrel():
global angle
angleChange = 2
mountCenterX = 265
mountCenterY = 215
#Rotate Barrel
cycle = 1
while cycle < len(Barrel):
x = Barrel[cycle-1]-mountCenterX
y = Barrel[cycle]-mountCenterY
Barrel[cycle-1] = (x*math.cos(angleChange*math.pi/180)-y*math.sin(angleChange*math.pi/180))+mountCenterX
Barrel[cycle] = (x*math.sin(angleChange*math.pi/180)+y*math.cos(angleChange*math.pi/180))+mountCenterY
cycle += 2
angle += angleChange
if angle == 360: angle = 0
canvas.coords(barrel,Barrel)
self.after(1,RotateBarrel)
def SpinningShoot(event):
global angle
speed = 10
shotXpos = Barrel[6]+10*(math.cos(angle*math.pi/180))
shotYpos = Barrel[7]-10*(math.sin(angle*math.pi/180))
cornerX = Barrel[6]+10*(math.cos((90-angle)*math.pi/180))
cornerY = Barrel[7]-10*(math.sin((90-angle)*math.pi/180))
shot = canvas.create_oval(shotXpos,shotYpos,cornerX,cornerY,fill="white")
Xmotion = speed*math.cos(angle*math.pi/180)
Ymotion = speed*math.sin(angle*math.pi/180)
Shots.append(shot)
ShotsPos.append(shotXpos)
ShotsPos.append(shotYpos)
ShotsMotion.append(Xmotion)
ShotsMotion.append(Ymotion)
It looks to me that your shot is not going to be centered on the "barrel", but the calculation using (90-angle) is going to give you an angular width for the shot of
angle - ( 90 - angle )
which is 2 * angle - 90
(ie the shot will be wider depending on the size of the angle).
I would have thought use (angle - 45 ) and (angle + 45 ) so your shot is always the same angular width and centered on the barrel.
You would also need to increase the "radius" for the second corner. Im confused about the +10 and -10, not quite sure what they would do.
Probably a better approach is to calculate the "centre" of the bullet and then from that just draw the circle centered on it. Im sure there would be a function that takes the centre and radius. So have
radius=10
centrex= radius * cos ( angle * math.pi /180 )
centrey= radius * sin ( angle * math. pi / 180 )
and then pass those two and a radius to a function that does a circle
One other little thing, I would suggest changing the line
if angle == 360: angle = 0
to
if angle >= 360: angle = angle-360
as if angle was initialized as anything other than an even number or you changed the angle step you could "miss" the 360 and then never wrap back around.

Categories