How to get position of turtles ? (turtle module python) - python

I'm using turtle module and I want to get the position of turtles. I looked at the documentation, but maybe I just don't see it.
I would like to know if two turtles are at the same position, so a code like this :
from turtle import *
turtle1 = Turtle()
turtle2 = Turtle()
pos1 = ... #Should be turtle1 position
pos2 = ... #SHould be turtle2 position
if pos1 == pos2:
#do stuff

Since turtles crawl a floating point plane, an == (equal) comparison won't work well in the long run. You want to get the distance between two turtles and decide how close together represents same for your application:
from turtle import Screen, Turtle
turtle1 = Turtle()
turtle2 = Turtle()
if turtle1.distance(turtle2) < 5: # pick distance that works for your app
# do stuff

Related

How to draw circles around a pentagon using turtle?

I would like 5 circles, one per side of the pentagon
enter image description here
import turtle
turtleStar = turtle.Turtle()
for s in range(5):
turtleStar.forward(100)
turtleStar.right(144)
turtleStar.left(36)
turtleStar.forward(62)
for p in range(4):
turtleStar.right(72)
turtleStar.forward(62)
for c in range(5):
r = 50
turtleStar.circle(r)
turtleStar.right(100)
Use one loop, draw the circles as you traverse the pentagon
Do some math or work out on paper what you want the turtle to do (e.g. what's the exterior angle of a pentagon?)
Make sure to read the documentation and make sure the methods you call do what you think they do
This code worked for me:
import turtle
import math
turtleStar = turtle.Turtle()
for s in range(5):
turtleStar.right(180-54)
turtleStar.circle(50/math.cos(math.pi*(90-54)/180))
turtleStar.left(180-54)
turtleStar.forward(100)
turtleStar.left(72)
I appreciate everyones help! I got was I looking for below!
import turtle
turtleStar = turtle.Turtle()
for s in range(5):
turtleStar.forward(100)
turtleStar.right(144)
turtleStar.left(36)
turtleStar.forward(62)
for p in range(4):
turtleStar.right(72)
turtleStar.forward(62)
for c in range(5):
turtleStar.right(72)
turtleStar.forward(31)
turtleStar.circle(60)
turtleStar.forward(31)

How to detect if two turtles are near each other or touch each other

So I am trying to make a snake game in python, and i reached the point where the snake has to eat the fruit / point to grow. So to do that I made two turtles. One is the snake's head and one is the fruit that has to be eaten. Except I don't know how to make it so when the snake head turtle touches the fruit the fruit will randomly go to another location.
Here's the code I have so far:
import turtle
import random
import time
points = 0
game_over = False
# Create map
screen = turtle.Screen()
screen.bgcolor('black')
# Create turtles :)
snake = turtle.Turtle()
snake.color('white')
snake.penup()
point_master = turtle.Turtle()
point_master.color('white')
point_master.penup()
snake.penup()
# Code snake so it can move :D
snake_speed = 2
def travel():
snake.forward(snake_speed)
screen.ontimer(travel, 10)
screen.onkey(lambda: snake.setheading(90), 'Up')
screen.onkey(lambda: snake.setheading(180), 'Left')
screen.onkey(lambda: snake.setheading(0), 'Right')
screen.onkey(lambda: snake.setheading(270), 'Down')
# Here is where we code it so when the snake touches the fruit the fruit will relocate.
# Continues to make snake move :)
screen.listen()
travel()
screen.mainloop()
In turtle we have xcor(), ycor(), setx() and sety().
xcor() finds where is the object(in this case it can be your snake or the food ) on x axis.
ycor() is the same but it finds the location on y axis.
setx() you move the x axis
Example:
if .......:
turtle.setx(-20)
this means if .... happens turtle will go -20 in x axis
Same in sety() the difference is the turtle will go in y axis
In your case you can do something like this
xy=random.randint(0,100)
food = turtle.Turtle()
food.goto(10, 50)
#lets say that in first level it will start on 10,50 cordinates
if snake.xcor == food.xcor and snake.ycor == food.xcor:
food.goto(xy, xy)
#xy was the random number between 0-100
#for setx() and sety() you can use it on your key bindings

How to make unfilled polies without retracing path in turtle?

I am working on a turtle project where the user can draw their own avatar.
The thing is, I want the user to be able to decide whether the turtle they drew will be filled, or not.
The filled part is simple, as, by default, the polies will get filled,
but the only way I know how to avoid filling is to retrace the lines so that the end of the line meets the start of the line.
Is there a built-in method or a more efficient way to keep the polies empty?
The problem with my current method is that the more lines (parameter) the lines there are for each turtle, the more stucky the program runs (the area doesn't influence the smoothness of the program).
import turtle
wn = turtle.Screen()
pen = turtle.Turtle('circle')
pen.shapesize(0.1, 0.1)
cor = []
# function to draw with the pen
def drag(x, y):
wn.tracer(0)
pen.goto(x, y)
cor.append(pen.pos())
# function to break out of while loop
def fill():
global done
done = True
# function to break out of while loop and set fill to False
def nofill():
global done, fill
done = True
fill = False
wn.listen()
wn.onkeypress(fill, 'f')
wn.onkeypress(nofill, 'n')
pen.ondrag(drag)
done = False
fill = True
while not done:
wn.update()
pen.begin_poly()
if fill:
for c in cor:
pen.goto(c)
else:
for c in cor[::-1]: # first go backards, then forward to avoid fill
pen.goto(c)
for c in cor:
pen.goto(c)
pen.end_poly()
wn.register_shape("mypen", pen.get_poly())
wn.clear()
example = turtle.Turtle('mypen')
Example with fill:
Run the above code.
Draw a shape.
Press f
Example without fill:
Run the above code.
Draw a shape.
Press n
Is there a built-in method or a more efficient way to keep the
polies empty?
I'm not aware of any functionality to avoid closed polygons on turtle cursors -- your solution is clever! Below is my rework of your code to simplify this approach:
from turtle import Screen, Turtle
def drag(x, y):
''' function to draw with the pen '''
turtle.goto(x, y)
done = False
filled = True
def fill():
''' function to break out of while loop '''
global done
done = True
def nofill():
''' function to break out of while loop and set fill to False '''
global done, filled
done = True
filled = False
screen = Screen()
screen.tracer(False)
screen.onkeypress(fill, 'f')
screen.onkeypress(nofill, 'n')
screen.listen()
turtle = Turtle('circle')
turtle.shapesize(0.1)
turtle.ondrag(drag)
turtle.begin_poly()
while not done:
screen.update()
turtle.end_poly()
screen.clear()
polygon = turtle.get_poly()
if not filled:
polygon = (*polygon, *polygon[::-1])
screen.register_shape("mypen", polygon)
example = Turtle('mypen')
screen.tracer(True)
screen.mainloop()
The problem with my current method is that the more lines
(parameter) the lines there are for each turtle, the more stucky
the program runs
Unfortunately, the above code doesn't reduce the extra/excessive lines problem nor the general stuckiness of it (whatever stucky means, #Nick.)

Python Multiple Turtles Moving (seemingly) Simultaneously

I'm working on testing something for my teacher, he wants to see how the program below could possibly run faster if we simulated the simultaneous (i know it can't be perfectly simultaneous, this is just an experiment for the sake of learning/practicing) movement of multiple turtles. I've tried using modules like multiprocessing, threading, and even some crazy stupid attempt to time and delay (I'm in high school and I just learned about classes in python because of a previous question I asked I think last week)
So after many failed attempts I'm asking if someone has a few ideas of what else to try, or a direction to go in to simulate simultaneous movement of the turtles
import turtle
from turtle import Turtle
turtle.getscreen().delay(0)
class MyTurtle(Turtle):
def petal(self):
for i in range(90):
self.fd(1)
self.rt(1)
self.rt(90)
for i in range(90):
self.fd(1)
self.rt(1)
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
for i in range(9):
self.pencolor('red')
self.begin_fill()
self.petal()
self.lt(230)
self.end_fill()
def stempetal(self):
self.seth(90)
self.rt(15)
self.fillcolor('green')
self.begin_fill()
self.petal()
self.end_fill()
tony = MyTurtle(shape='turtle')
todd = MyTurtle(shape='turtle')
tina = MyTurtle(shape='turtle')
tiny = MyTurtle(shape='turtle')
tweeny = MyTurtle(shape='turtle')
def flower1():
todd.speed('fastest')
todd.fillcolor('blue')
todd.flowerhead()
todd.seth(270)
todd.stem()
todd.stempetal()
def flower2():
tony.speed('fastest')
tony.setpos(80, -15)
tony.pencolor('green')
tony.goto(0, -200)
tony.fillcolor('purple')
tony.goto(80,-15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.speed('fastest')
tina.setpos(-80, -15)
tina.pencolor('green')
tina.goto(0, -200)
tina.fillcolor('teal')
tina.goto(-80,-15)
tina.lt(40)
tina.flowerhead()
def flower4():
tiny.speed('fastest')
tiny.setpos(160, -25)
tiny.pencolor('green')
tiny.goto(0, -200)
tiny.fillcolor('black')
tiny.goto(160, -25)
tiny.flowerhead()
def flower5():
tweeny.speed('fastest')
tweeny.setpos(-160, -25)
tweeny.pencolor('green')
tweeny.goto(0, -200)
tweeny.fillcolor('pink')
tweeny.goto(-160,-25)
tweeny.lt(40)
tweeny.flowerhead()
flower2()
tony.hideturtle()
flower4()
tiny.hideturtle()
flower3()
tina.hideturtle()
flower5()
tweeny.hideturtle()
flower1()
todd.hideturtle()
thank you for your time
The solution is to disable updating the position of each turtle, and then force the whole screen to update once the new position is computed.
import turtle
# our two turtle instances
first, second = turtle.Turtle(), turtle.Turtle()
first.tracer(False) # disable updating view on screen for this turtle!
second.tracer(False)
# make one move - note this will not appear on screen.
first.forward(50)
second.left(20)
# when you are ready to see the whole screen update
turtle.update()
To do what you want, you will have to essentially make it so that every new action is done before a turtle.update(). You cannot keep it to a serial execution as you are doing now - in other words, you can't run flower1, then flower2, in sequence.
Here's an example of a pair of turtles that will generate a random pattern on the screen at the same time:
import turtle
import random
# our two turtle instances
turtles = [turtle.Turtle(), turtle.Turtle()]
for turtle_object in turtles:
turtle_object.tracer(False)
for _ in range(10000): # make ten thousand moves.
for t in turtles:
# list the possible moves available
possible_moves = [t.forward, t.back, t.right, t.left]
# give it a random value
random_value = random.randint(0, 100)
# make a random move
random.choice(possible_moves)(random_value)
# update the whole screen now that the new positions have been calculated
turtle.update()
The trick here is to note that every new position for each turtle is calculated, then the screen as a whole is told to update, and only then do you move on to the next move. Every move must be as granular as possible.
You've asked for two different things, 'run faster' and 'simulate simultaneous movement'. I believe we can do both (separately) but I don't believe that tracer() and update() are the answer in this situation as they'd just be a band-aid to cover over the real issue.
wants to see how the program below could possibly run faster
If you want it to run faster, fix the bottleneck which is the petal() function. Replace it with something that uses turtle's built-in circle() function which is faster. For example:
def petal(self):
self.circle(-60, 90)
self.rt(90)
self.circle(-60, 90)
This speeds up your code by a factor of 25X with no other changes.
simulate simultaneous movement of the turtles
This can be done with turtle's own ontimer() event hander and some careful programming. Surprisingly, we use your original petal() logic as it breaks up the graphics into minute steps between which we can switch off processing to another timed event:
from random import randint
from turtle import Turtle, Screen
class MyTurtle(Turtle):
def petals(self, size=30, count=8, speed=100):
if size == 30:
self.begin_fill()
if size > 0: # drawing leading edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
if size == 0: # switch to other edge of petal
self.rt(90)
if size > -30: # drawing trailing edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
self.end_fill() # finish this petal
self.lt(230) # prepare for the next petal
if count > 0: # drawing the next petal
screen.ontimer(lambda: self.petals(count=count - 1, speed=speed), speed)
return
self.hideturtle() # finished drawing
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
self.pencolor('red')
self.petals(speed=randint(50, 250))
def flower2():
tony.color('green', 'purple')
tony.penup()
tony.goto(0, -200)
tony.pendown()
tony.showturtle()
tony.goto(80, -15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.color('green', 'turquoise')
tina.penup()
tina.goto(0, -200)
tina.pendown()
tina.showturtle()
tina.goto(-80, -15)
tina.lt(40)
tina.flowerhead()
def flower5():
tweeny.color('green', 'pink')
tweeny.penup()
tweeny.goto(0, -200)
tweeny.pendown()
tweeny.showturtle()
tweeny.goto(-160, -25)
tweeny.lt(40)
tweeny.flowerhead()
tony = MyTurtle(shape='turtle', visible=False)
tina = MyTurtle(shape='turtle', visible=False)
tweeny = MyTurtle(shape='turtle', visible=False)
screen = Screen()
screen.ontimer(flower2, 100)
screen.ontimer(flower3, 120)
screen.ontimer(flower5, 100)
screen.mainloop()
RUNNING IMAGE
It won't be any faster, as it's just a simulation. (Well, it does go a little faster as I made petal drawing slightly cruder in return for speed.) If you look closely, you can see the turtles are (intentionally) moving at their own individual speed.

How to stop turtles at certain coordinates?

I am very new to programming (using Python 3). I want to know how one would stop a turtle from moving when it reaches a certain point, when using keypresses. I have managed to do it but it only works once or couple of times because the x coordinate of the turtle changes when I've moved it around for a bit, e.g instead of 40.00 the turtle will then land on -40.0001 or -39.9996.
import turtle
wn = turtle.Screen()
a = turtle.Turtle()
def up():
a.setheading(90)
if a.pos() != (40.00, 80.00):
a.forward(20)
else:
False
def left():
a.setheading(180)
a.forward(20)
def right():
a.setheading(0)
a.forward(20)
def down():
a.setheading(270)
a.forward(20)
wn.onkey(up, "Up")
wn.onkey(left, "Left")
wn.onkey(right, "Right")
wn.onkey(down, "Down")
wn.listen()
wn.mainloop()
For now I just want stop the turtle at (-40.00, 80.00) while moving up. I will appreciate any help I can get, thanks.
Don't check the pos directly, instead check if a.distance(40.0, 80.0) < 1.0 or some small threshold.
Alternative: after you move the turtle or before you check its position, you can round the returned coordinates so that they snap to exact numbers.
>>> round(40.01)
40.0

Categories

Resources