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".
Related
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()
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()
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()
I'm working on a game in Python-3 that requires moving a Turtle object horizontally (AKA sideways) without changing my heading.
turtle.goto(x,y) or turtle.setx(x) turtle.sety(y) won't work because I want the object to show up when moving, just like when you do turtle.fd(distance).
Here is the code I have now:
import turtle
turtle.speed('slowest')
turtle.lt(90)
turtle.fd(20)
turtle.rt(90)
With this code, the turtle turns, moves forward, and turns back. Is there a way I could move sideways without having to turn?
Thanks a lot!
Any comments will be welcome!
turtle.goto(x,y) or turtle.setx(x) turtle.sety(y) won't work because I
want the object to show up when moving
Your premise is false -- the turtle will show up when moving with all of these operations:
import turtle
turtle.speed('slowest')
turtle.sety(turtle.ycor() + 100)
turtle.done()
This moves the turtle vertically while maintaining a horizontal heading. It doesn't teleport, it's the same visible motion as a .forward()
However, if you have some other reason not to use goto(), setx(), sety(), etc. and want to use forward(), backward() instead, there's a way we can do this. The turtle cursor has a concept of tilt, allowing it to look in one direction while moving in another:
import turtle
turtle.speed('slowest')
turtle.tracer(False) # hide the heading change ...
turtle.setheading(90)
turtle.settiltangle(-90) # ... until we can tilt it
turtle.tracer(True)
turtle.forward(100)
turtle.done()
One situation where we might use this is a space invaders style game where the turtle wants to face towards the top of the window but we want to use forward() and backward() to control its motion side-to-side on the screen:
""" Oversimplified Example """
from turtle import Turtle, Screen
screen = Screen()
turtle = Turtle('turtle', visible=False)
turtle.settiltangle(90)
turtle.penup()
turtle.showturtle()
screen.onkey(lambda: turtle.forward(10), "Right")
screen.onkey(lambda: turtle.backward(10), "Left")
screen.listen()
screen.mainloop()
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()