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()
Related
I have a function that draws a circle based on the screensize of the window. Currently, if I make the window smaller, the entire circle isn't visible. Is there any way to find out if the window has been resized so I can redraw the circle to fit in the window?
Here's my code to draw the circle:
def draw_circle():
# Get circle radius
screensize = s.screensize()
if screensize[0] > screensize[1]:
smaller = 1
else:
smaller = 0
radius = screensize[smaller]
# Draw circle
t.pensize(15)
t.pu()
t.goto(0, -radius)
t.pd()
t.circle(radius)
t.pu()
I have tried to add an if statement that checks if the screensize changes in my main loop, but that didn't work either.
P.S. I tried searching Google and StackOverflow and found no answers.
There's no need to poll in a loop. Once you get the underlying Tkinter canvas with turtle.getcanvas(), you can look up the non-turtle Tkinter approach and use that. For example, adapting Tkinter track window resize specifically? to turtle gives the following minimal example:
import turtle
def resize(event):
print(event.width, event.height)
turtle.getcanvas().bind("<Configure>", resize)
turtle.exitonclick()
Note that this doesn't change the screen size, so you can draw your circle relative to the window instead:
import turtle
def draw():
r = min(turtle.window_width(), turtle.window_height()) / 2 - 30
turtle.clear()
turtle.penup()
turtle.begin_fill()
turtle.goto(0, -r)
turtle.pendown()
turtle.circle(r)
turtle.end_fill()
turtle.update()
def resize(event):
draw()
turtle.tracer(0)
turtle.hideturtle()
turtle.getcanvas().bind("<Configure>", resize)
draw()
turtle.exitonclick()
Drawing relative sizes for everything tends to be pretty tedious, so I recommend avoiding this if at all possible for your app.
I want to implement a process like this
time.sleep(1)
display a red square with turtle.stamp()
time.sleep(1)
remove the red square with turtle.clearstamps(-1)
Here is my code:
import turtle
import time
snakes = turtle.Turtle()
snakes.ht()
snakes.shape("square")
snakes.up()
time.sleep(1)
snakes.color("Red")
snakes.stamp()
# turtle.update()
time.sleep(1)
snakes.clearstamps(-1)
turtle.done()
When I run this code, the red square doesn't appear at all. It seems that the red square has been deleted by 'clearstamps()'. However, I take the step 3 to delay it for 1 second before deleting it.
With some trys, I find that if I add a update after I create a stamp (just the comment part of the program above), the program will work successfully, with the 1 second delay before deleting.
I wonder why I should add this update(), since I don't turn off my tracer in my program.
Thanks for your help!
I would avoid using time.sleep() in turtle, as it can interfere with the event loop, and instead use turtle's own ontimer() method:
from turtle import Screen, Turtle
def action():
stamp = turtle.stamp()
screen.ontimer(lambda: turtle.clearstamp(stamp), 1000)
turtle = Turtle()
turtle.hideturtle()
turtle.color('red')
turtle.shape('square')
screen = Screen()
screen.ontimer(action, 1000)
screen.mainloop()
With Python 3.6 and the Turtle module, I would like to know how to print the coordinates of the turtle on screen.
My questions are: How do I print text on the screen, and how do I make that text the player's coordinates?
Here is my code.
from turtle import Turtle, Screen
play = Screen()
play.bgcolor("black")
play.screensize(250, 250)
play.title("Turtle Keys")
def position():
coord = follow.coor()
coord.color("white")
coord.setposition(130, 100)
run = Turtle("triangle")
run.speed("fastest")
run.color("white")
run.penup()
run.setposition(250, 250)
print(position)
Thank you.
Edit I tried write, but it throws a name not defined error.
Here is how you can write the turtle position on screen: the write method from the turtle module, must be called on a Turtle object.
import turtle
playground = turtle.Screen() # use nouns for objects, play is a verb
playground.bgcolor("black")
playground.screensize(250, 250)
playground.title("Turtle Keys")
tom = turtle.Turtle() # use nouns for objects, run is a verb
tom.color("white")
tom.setposition(130, 100)
tom.speed("fastest")
tom.color("white")
p = tom.pos() # here you get the coordinates of the turtle
tom.write(str(p), True) # and you print a string representation on screen
tom.penup()
print(p) # this prints to the console
playground.exitonclick()
The way I approach this type of problem is to dedicate a turtle to each fixed label on the screen. That way you can permanentely locate a turtle at that position and simply do undo() to clear the old text followed by write() to write the new.
Here's a dynamic example where you can drag the turtle around the screen with your mouse and the current position will be written to the center of the screen:
from turtle import Turtle, Screen
FONT = ('Arial', 24, 'normal')
playground = Screen()
playground.setup(500, 500)
playground.bgcolor("black")
runner = Turtle("triangle")
runner.color("white")
runner.speed("fastest")
runner.penup()
runner.setposition(200, 200)
marker = Turtle(visible=False) # our virtual magic marker
marker.penup()
marker.color("yellow")
marker.write(runner.position(), align='center', font=FONT) # so we can undo it
def drag_handler(x, y):
runner.ondrag(None) # disable handler while in handler
marker.undo() # erase previous position
marker.write((x, y), align='center', font=FONT)
runner.setheading(runner.towards(x, y)) # head towards new location
runner.setposition(x, y)
runner.ondrag(drag_handler)
runner.ondrag(drag_handler)
playground.mainloop()
Use the functions xcor() and ycor() to get coordinates. Use the function write() to write on the screen.
See documentation: https://docs.python.org/3/library/turtle.html
Maybe this will help:
def write_pos(self, position):
self.pu()
self.bk(len(str(position))-len(str(position))/2)
self.pd()
self.write(str(position))
self.pu()
self.fd(len(str(position))-len(str(position))/2)
self.pd()
write_pos(run, run.position())
Ok. Here's the explanation.
So I defined a function writing the position of something (in this case, the turtle).
When I do:
self.pu()
self.bk(len(str(position))-len(str(position))/2)
I:
Lift the pen up and
Move backward some steps, so I can center the text.
I then do:
self.pd()
self.write(str(position))
Which:
Puts the pen down and
Writes (or outputs) the position
After that, when I do:
self.pu()
self.fd(len(str(position))-len(str(position))/2)
self.pd()
I:
Pick the pen up
Move it back to the original position and
Put the pen down again
EDIT:
I just realized that you can do it a much more simple way of using write like this:
write(run.position(), False, center)
It writes the turtles position, it doesn't move, and it still writes the text but with the canter as the place where it aligns.
EDIT #2:
I already figured out the problem.
Your using write directly and not actually calling it from the object. You should call write like this:
run.write(run.position(), align="center")
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()
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".