Using Turtle module in Python to move shrinking turtle up window screen - python

I am supposed to define a function, movingTurtle, that uses the Python turtle module, sets the turtle to an actual turtle shape, and moves that turtle up from the bottom of the screen towards the top, getting smaller as it moves along. Here is the code I currently have:
def movingTurtle(mTurtle, window):
'''
Create turtle that is the shape of an actual
turtle, then have it move from the bottom of screen
to the top, getting smaller as it moves along its path
'''
width = window.window_width()
height = window.window_height()
bottom = -height/2
top = height/2
mTurtle.shape("turtle")
mTurtle.penup()
mTurtle.setposition(0, bottom)
x = int(height/10)
y = int(height/10)
z = int(height/10)
for i in range(bottom, top):
mTurtle.setposition(0, i)
#x -= .1
#y -= .1
#z -= .1
#mTurtle.shapesize(x, y, z)
def main():
# set window size
width = int(input('Enter the width of the screen: '))
height = int(input('Enter the height of the screen: '))
turtle.setup(width,height)
print('='*50)
#========================================================
# get reference to turtle window
window = turtle.Screen()
# set window title bar
window.title('Lab20 - Turtle Object')
#========================================================
# Moving turtle
mTurtle = turtle.Turtle()
# function call
try:
movingTurtle(mTurtle,window)
except:
print('movingTurtle is not either defined or there is a',
'problem with the function')
#========================================================
main()
(The reason for the main() part is because I actually have several other functions - this is for a project)
Even with the bottom four lines commented out, I can't even get the turtle to move from the top to the bottom. At first, I had:
for i in range(-height, height):
mTurtle.setposition(0, i)
etc.
But I realized that that made it so that the turtle started way further down than the actual size of the window, I needed to cut that size in half. But when I had that code, the turtle did move from bottom to top at least.
I tried to put in for i in range(-height/2, height/2) and that's when my turtle stopped appearing at all.
So, then I tried to hold those values in the variables bottom and top, thinking that maybe for some reason I couldn't put them in the range parameters?
For some reason this isn't working and I'm not sure why.
Before, when my turtle was moving from bottom to top, the last 4 lines were shrinking it, but it would get so small it would disappear by the time it reached the middle of the screen. I think this was because I didn't have the height divided by two.

With respect to turtle motion, I believe that #JasonYang's comment is spot on (+1) though lacking in explanation. Turtles wander a floating point plane, but the range() wants int values. We use integer division \\ to convert turtle's floating point values to what range() wants:
import sys
from turtle import Screen, Turtle
def movingTurtle(mTurtle, window):
height = window.window_height()
top, bottom = height // 2, -height // 2 # use // for range() below, turtle doesn't care
mTurtle.shape('turtle')
mTurtle.setheading(90) # turtle faces direction of motion
mTurtle.penup()
mTurtle.sety(bottom)
for y in range(bottom + 1, top):
mTurtle.sety(y)
def main():
width = int(input("Enter the width of the screen: "))
height = int(input("Enter the height of the screen: "))
screen = Screen()
screen.setup(width, height)
screen.title("Lab20 - Turtle Object")
try:
movingTurtle(Turtle(), screen)
except:
print("movingTurtle is not either defined or there is a problem with the function", file=sys.stderr)
screen.exitonclick()
main()

Related

Turtle drawing a hexagon and hexagon grid

current code
#import the turtle modules
import turtle
#Start a work Screen
ws=turtle.Screen()
#Define a Turtle Instance
geekyTurtle=turtle.Turtle()
#executing loop 6 times for 6 sides
for i in range(6):
#Move forward by 90 units
geekyTurtle.forward(90)
#Turn left the turtle by 300 degrees
geekyTurtle.left(300)
My goal is to make a hexagon grid pattern and I am failing to do it properly. My first issue is if you run the code you get a hexagon but the top is flat, I can't get it to get the pointy corners to get on top. Second I tried to make the grid and it failed and I am not sure why I am unable to copy the same hexagon and clone it next to the other. I will or should have a file of the image that I am going for below.
The output I am getting:
The output I am trying to get:
Before going into loop, turn 30 degrees.
geekyTurtle.right(30)
In order to have its clone beside, just put the turtle to the new place and draw the shape again:
for i in range(6):
geekyTurtle.forward(90)
geekyTurtle.left(300)
geekyTurtle.up()
geekyTurtle.goto(90 * 3 ** .5, 0)
geekyTurtle.down()
for i in range(6):
geekyTurtle.forward(90)
geekyTurtle.left(300)
Put it in a loop to have it for more than two times
You can use the idea of .up() and .goto(x, y) and .down() to draw grids.
It seems like this is a problem that recursion could simplify in a fractal-like way. Each side of the initial hexagon is itself a hexagon, and so forth, filling the available space:
from turtle import Screen, Turtle
SIDE = 75 # pixels
def hexagon(side, depth):
if depth > 0:
for _ in range(6):
turtle.forward(side)
turtle.right(60)
hexagon(side, depth - 1)
turtle.left(120)
screen = Screen()
screen.tracer(False) # because I have no patience
turtle = Turtle()
turtle.penup()
turtle.width(2)
turtle.sety(-SIDE) # center hexagons on window
turtle.pendown()
turtle.left(30) # optional, orient hexagons
hexagon(SIDE, depth=6) # depth depends on coverage area
turtle.hideturtle()
screen.tracer(True)
screen.exitonclick()

How to put the figure inside a circle using turtle?

I got a simple figure using turtle. But the problem is I dunno how to put that figure inside circle.
Code:
import turtle
painter = turtle.Turtle()
painter.pencolor("blue")
for i in range(50):
painter.forward(100)
painter.left(123*2)
painter.circle(70)
turtle.done()
A bit of trigonometry in my head and I figured the angle. Not sure if I got the radius correct though. Ideally figure out the coordinates of the center instead, but a quick and dirty solution is:
import turtle
painter = turtle.Turtle()
painter.pencolor("blue")
for i in range(50):
painter.forward(100)
painter.left(123*2)
painter.right(123)
painter.right(90)
painter.penup()
painter.forward(10)
painter.left(90)
painter.pendown()
painter.circle(70)
turtle.done()
You will need to move the turtle to the correct starting position. NOTE that's not the circle's center! It starts drawing the circle from its rightmost position - i.e., if you want a circle with radius 70 around (0,0), then move to (70,0), e.g.:
painter.penup()
painter.goto(70,0)
painter.pendown()
painter.circle(70)
FYI: I can't immediately figure out where the center of your drawing is, but I suspect it is NOT at (0,0). In all cases, you should place the turtle to the right of your shape's center, offset by the circle's radius, to make the circle go around it.
Another approach would be to average the positions of your arbitrary image and then use that average as the center of the surrounding circle:
from turtle import Screen, Turtle, Vec2D
CIRCLE_RADIUS = 70
POLYGON_LENGTH = 100
POINTS = 50
screen = Screen()
painter = Turtle()
painter.speed('fastest')
painter.pencolor("blue")
total = Vec2D(0, 0)
for _ in range(POINTS):
painter.forward(POLYGON_LENGTH)
total += painter.position()
painter.left(246)
x, y = total * (1.0 / POINTS) # Vec2D can multiply by scalar but not divide
painter.penup()
painter.goto(x, y - CIRCLE_RADIUS)
painter.setheading(0)
painter.pendown()
painter.circle(CIRCLE_RADIUS)
screen.exitonclick()

randomly positioned circle clicking game

So I'm still very new to python and trying to learn through making small projects.
The game I'm making is meant to test your mouse accuracy by creating a bunch of random circles which the player is meant to click in a given amount of time. At the end of the game, it should tell the player their score, and how many misclicks they had.
I've been using turtle to try and do this, but I'm stuck:
import turtle
import random
t = turtle.Pen()
win = turtle.Screen()
win.bgcolor("lightgreen")
win.title("clicky")
def mycircle(red, green, blue):
t.color(red, green, blue)
t.begin_fill()
x = random.randint(10,50)
t.circle(x)
t.end_fill()
t.up()
y = random.randint(0,360)
t.seth(y)
if t.xcor() < -300 or t.xcor() > 300:
t.goto(0, 0)
elif t.ycor() < -300 or t.ycor() > 300:
t.goto(0, 0)
z = random.randint(0,100)
t.forward(z)
t.down()
for i in range(0, 20):
a = random.randint(0,100)/100.0
b = random.randint(0,100)/100.0
c = random.randint(0,100)/100.0
mycircle(a, b, c)
The main issues I've been trying to figure out are:
How can I make the circles spawn further from each other? They overlap
quite often and I want that to be avoided.
How can I make the circles spawn instantly rather than having to be
drawn?
How can I make the circles spawn further from each other?
We can keep track of circles already created and make sure their centers are at least a diameter away from each other. Your current circle placement logic is too complicated along with being faulty. Let's try to simplify it and make sure circles are drawn completely within the window.
How can I make the circles spawn instantly rather than having to be
drawn?
We could stamp them rather than draw them. However, since you are drawing so few circles, we can make every circle a turtle. This makes determining if you clicked on a circle, and removing that circle, simpler. I've added code, for you to expand on, that removes any circle that you click on:
from turtle import Turtle, Screen
from random import random, randint
CURSOR_SIZE = 20
def my_circle(color):
radius = randint(10, 50)
circle = Turtle('circle', visible=False)
circle.shapesize(radius / CURSOR_SIZE)
circle.color(color)
circle.penup()
while True:
nx = randint(2 * radius - width // 2, width // 2 - radius * 2)
ny = randint(2 * radius - height // 2, height // 2 - radius * 2)
circle.goto(nx, ny)
for other_radius, other_circle in circles:
if circle.distance(other_circle) < 2 * max(radius, other_radius):
break # too close, try again
else: # no break
break
circle.showturtle()
circle.onclick(lambda x, y, t=circle: t.hideturtle()) # expand this into a complete function
return radius, circle
screen = Screen()
screen.bgcolor("lightgreen")
screen.title("clicky")
width, height = screen.window_width(), screen.window_height()
circles = []
for _ in range(0, 20):
rgb = (random(), random(), random())
circles.append(my_circle(rgb))
screen.mainloop()
One issue you need to work out is making sure your circle color isn't too similar to (or the same as) your background color, otherwise you'll be hunting an invisible circle. Also, we might be able to speed up the circle drawing process even more, if needed.

Change the on-screen position of the Turtle Graphics window?

Is it possible to change the position of the turtle console on screen?
My main objective is to write code that can move the window, that's all.
I'm using Python 3.4.0 under Windows 10.
If any extra information is needed please ask.
Why do folks always jump into tkinter before reading the turtle documentation?
Yes, you can set the screen position of the turtle graphics window using the same setup() method you use to size it:
from turtle import Turtle, Screen
def animate():
global offset
screen.setup(width=0.333, height=0.333, startx=offset, starty=offset)
turtle.dot(offset)
offset += 10
if offset < 300:
screen.ontimer(animate, 100)
screen = Screen()
turtle = Turtle()
offset = 30
animate()
screen.exitonclick()
startx, if positive, is the starting position in pixels from the left edge of the screen, or from the right edge if negative. Similarly, starty, if positive, is the starting position from the top edge of the screen, or from the bottom edge if negative. By default, the window is centered on the screen.
Your title asks about the position of the Turtle Graphics window on the screen but the body of your question asks about the Turtle Console. These might be considered two different windows.
My main objective is to write code that can move the window
I can't tell if you just want to set the initial position of the window or actually move the window around the screen so I rewrote my example to demonstrate the later.
Yes. You need to get the root window that contains the Tkinter Canvas that the turtle is using as its TurtleScreen. Once you have that window you can change its geometry.
Here's a simple demo.
import turtle
turtle.setup(width=0.5, height=0.5)
screen = turtle.Screen()
width, height = screen.window_width(), screen.window_height()
canvas = screen.getcanvas()
left, top = 30, 100
geom = '{}x{}+{}+{}'.format(width, height, left, top)
canvas.master.geometry(geom)
t = turtle.Turtle()
turtle.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