Having trouble timing turtle movement - python

I wrote the following code, which creates expanding squares at two random locations. I would like to write a function f(squares, seconds) so that if the user inputs f(5,10), a new square would begin forming every 10 seconds, until 5 had formed.
I can't seem to find anything which lets me start a new square while one is still forming. I can either make two form at the same time, as in the code below, or have one be completed, and then for another to start forming. Help?
import sys
sys.setExecutionLimit(1000000)
import turtle
import random
wn = turtle.Screen()
#Creates alex the turtle
alex = turtle.Turtle()
alex.color('blue')
alex.pensize(3)
alex.ht()
alex.penup()
#creates bob the turtle
bob = turtle.Turtle()
bob.color('blue')
bob.pensize(3)
bob.ht()
bob.penup()
#Sets variables so that alex starts in a random location
a=random.randrange(360)
b=random.randrange(360)
x=random.randrange(50,150)
y=random.randrange(50,150)
#Sets variables so that bob starts in a random location
l=random.randrange(360)
m=random.randrange(360)
n=random.randrange(50,150)
o=random.randrange(50,150)
#Moves alex to his random starting location
alex.speed(100)
alex.left(a)
alex.forward(x)
alex.left(b)
alex.forward(y)
alex.pendown()
#Moves bob to his random starting location
bob.speed(100)
bob.left(l)
bob.forward(n)
bob.left(m)
bob.forward(o)
bob.pendown()
#Draws the 2 squares
for i in range(1,500):
alex.forward(i)
alex.left(90)
bob.forward(i)
bob.left(90)

The functionality you want requires independent execution threads. You need to work with the multi-threading package and tutorial
You will want logic such as this:
import time
import threading
def draw_square():
# Draw a square in a random place
length = random.randrange(360)
width = random.randrange(360)
x_pos = random.randrange(50,150)
y_pos = random.randrange(50,150)
# Continue with your square-drawing logic;
# you already know how to do this.
while True:
threading.thread(draw_square)
time.sleep(10)

Related

How do I speed up on key press in python turtle

I am trying to speed up my turtle whenever I press the space bar.
I have a code that looks something like this
import turtle
instructions = [20,30,40,20,50,5,20,30,40,200,5]
speed = 0
wn = turtle.Screen()
drone = turtle.Turtle()
speed = 1
def sped():
global speed
speed += 1
for instruction in instructions:
drone.forward(instruction)
drone.left(45)
wn.onkey(sped, "space")
drone.speed(speed)
print(speed)
However, the speed is always 1. I've tried scouring the internet but nothing comes up. How do I fix this?

whats the diffrence between t=Turtle(shape="turtle") from code 1 and t.shape("turtle") from code 2

Code 1
import random
from turtle import Turtle,Screen
t = Turtle()
screen=Screen()
screen.setup(width=900,height=500)
s=["fastest", "fast", "normal", "slow", "slowest"]
userbet=screen.textinput(title="make your bet",prompt="enter color")
color=["red","yellow","green","purple","orange"]
y=[-70,-40,-10,20,50]
for turtle_num in range(0,5):
t=Turtle(shape="turtle")
t.color(color[turtle_num])
t.penup()
t.goto(x=-230,y=y[turtle_num])
screen.exitonclick()
Code 2
import random
from turtle import Turtle,Screen
t = Turtle()
screen=Screen()
screen.setup(width=900,height=500)
s=["fastest", "fast", "normal", "slow", "slowest"]
userbet=screen.textinput(title="make your bet",prompt="enter color")
color=["red","yellow","green","purple","orange"]
y=[-70,-40,-10,20,50]
for turtle_num in range(0,6):
t.shape("turtle")
t.color(color[turtle_num])
t.penup()
t.goto(x=-230,y=y[turtle_num])
screen.exitonclick()
So i wanted to know why is code 2 producing only one turtle whereas code 1 is producing 5 turtle as of my knowledge t=Turtle(shape="turtle") from code 1 and t.shape("turtle") these two lines perform same task mostly i am wrong thats why there is diffrence i would be glad if someone can explain me diffrence.
All is in the "mostly", the difference is huge:
The first code creates a new turtle at each iteration, setting a different color and a different destination goto
for turtle_num in range(0,5):
t = Turtle(shape="turtle")
t.goto(x=-230,y=y[turtle_num])
That means you do : turtle1 go there, turtle2 go there, turtle3 go there
The second code keeps moving the one and only one turtle instance, and changing it's color
t = Turtle()
for turtle_num in range(0,6):
t.goto(x=-230,y=y[turtle_num])
That means : turtle go there, then go there, then go there

How do I prevent the barriers and the doors overlapping?

# Imported Modules for Randomization and Turtle
import turtle as trtl
import random as rand
from random import *
# Painter Configuration and Screen Configuration
painter = trtl.Turtle()
distanceForward = 20
painter.pensize(5)
painter.speed(10000000)
painter.screen.setup(1000, 1000)
walls = 32
#This for loop is essential--> it creates 32 lines, and based on the conditions below, adds walls, barriers, and exits
for i in range(walls):
#Register the beginning position of the Turtle.
xBeginCor = painter.xcor()
yBeginCor = painter.ycor()
#Variables for randomization of Exits and Doors
initialWallDistance = randint(1, distanceForward-5)
doorDistance = randint(1,distanceForward-18)
#Program for the Walls and their Randomization
#Prevents the last 4 lines having barriers protruding
#We feel this method of randomizing the wall distance was really innovative and that it works pretty well
if i < walls - 4:
painter.penup()
painter.forward(initialWallDistance)
painter.left(90)
painter.pendown()
painter.forward(30)
painter.backward(30)
painter.right(90)
painter.penup()
#Preventing overlapping for the Walls and Doors. This does not work perfectly, and sometimes the doors are too small as a result of this
if doorDistance == range(0, 21):
doorDistance + 20
painter.forward(distanceForward - initialWallDistance)
else:
painter.forward(distanceForward - initialWallDistance)
#Creates the randomization of the doors. This works really well, as it makes the turtle go a random distance forward from the beginning of the line, and create a door
painter.goto(xBeginCor, yBeginCor)
painter.pendown()
painter.forward(doorDistance)
painter.penup()
painter.forward(20)
painter.pendown()
painter.forward(distanceForward-doorDistance)
#Turn the turtle to create the next line
painter.right(90)
#Change the length of the line so the next one is a longer distance
distanceForward += 15
#Keeps window open
wn = trtl.Screen()
wn.mainloop()
I need help stopping these doors and barriers happening on top of each other. I have also attached an image describing what I mean.
This code here is what I am working on to prevent the two from going on top of each other:
if doorDistance == range(0, 21):
doorDistance + 20
painter.forward(distanceForward - initialWallDistance)
else:
painter.forward(distanceForward - initialWallDistance)
Nothing is working. At this point I am completely confused, and I have no idea what I am doing. Any explanations/help would be appreciated
Note: I am a beginner, so I will not be able to use any complex techniques
This code doesn't work Python-wise:
if doorDistance == range(0, 21):
doorDistance + 20
It should be something like:
if 0 <= doorDistance <= 20:
doorDistance += 20
But that's not going to fix your problem. Your logic to avoid door and barrier overlap doesn't work. As you spiral from the center, you put up barriers pointing to the next layer, and leave door gaps. But the overlaps happen on the next spiral when all memory of where those barriers are located is lost.
My rework of your code into Python (still broken):
# Imported Modules for Randomization and Turtle
from turtle import Screen, Turtle
from random import randint
WALLS = 32
# Painter Configuration and Screen Configuration
screen = Screen()
screen.setup(1000, 1000)
painter = Turtle()
painter.hideturtle()
painter.pensize(5)
painter.speed('fastest')
distanceForward = 20
# This for loop is essential--> it creates 32 lines, and based on the conditions below, adds walls, barriers, and exits
for wall in range(WALLS):
# Register the beginning position of the Turtle.
beginCor = painter.position()
# Variables for randomization of Exits and Doors
initialWallDistance = randint(1, distanceForward-5)
doorDistance = randint(1, distanceForward-18)
# Program for the Walls and their Randomization
# Prevents the last 4 lines having barriers protruding
# We feel this method of randomizing the wall distance was really innovative and that it works pretty well
if wall < WALLS - 4:
painter.penup()
painter.forward(initialWallDistance)
painter.left(90)
painter.pendown()
painter.forward(30)
painter.penup()
painter.backward(30)
painter.right(90)
# Preventing overlapping for the Walls and Doors. This does not work perfectly, and sometimes the doors are too small as a result of this
if 0 <= doorDistance <= 20:
doorDistance += 20
painter.forward(distanceForward - initialWallDistance)
# Creates the randomization of the doors. This works really well, as it makes the turtle go a random distance forward from the beginning of the line, and create a door
painter.goto(beginCor)
painter.pendown()
painter.forward(doorDistance)
painter.penup()
painter.forward(20)
painter.pendown()
painter.forward(distanceForward - doorDistance)
# Turn the turtle to create the next line
painter.right(90)
# Change the length of the line so the next one is a longer distance
distanceForward += 15
# Keeps window open
screen.mainloop()
Your logic seems like it could produce unsolvable mazes, like your example one.

Create random-path by randomly choosing from lists of stored turtle-graphics functions

I have stored turtle-graphics functions in list and am using random functions to call it to create a random-path, however code does not work.
Can someone please have a look on this and provide suggestion.
from turtle import Turtle
from turtle import Screen
import random
pen = Turtle()
pen.pensize(8)
pen.speed(10)
window = Screen()
window.colormode(255)
moves=[pen.forward(30),pen.backward(30)]
turns=[pen.right(90),pen.left(90)]
is_true = True
while is_true:
pen.color(random.randint(0,255),random.randint(0,255),random.randint(0,255))
random.choice(turns)
random.choice(moves)
window.exitonclick()
I would say the issue here is that you are using functions as data when you could simply use data as data. That is, giving forward() a negative distance is the same as backward(). Giving left() a negative angle is the same as right(). So we can simply do:
from turtle import Screen, Turtle
from random import random, choice
DISTANCES = [30, -30]
ANGLES = [90, -90]
def move():
turtle.color(random(), random(), random())
turtle.left(choice(ANGLES))
turtle.forward(choice(DISTANCES))
screen.ontimer(move, 10)
screen = Screen()
turtle = Turtle()
turtle.pensize(8)
turtle.speed('fastest')
move()
screen.exitonclick()
I also dealt the next issue, your implicit while True:. The way you structured your code, the exitonclick() is never reached and doesn't work. Now it works as we've kept both the drawing and exitonclick() in the event loop.
You execute the methods only when you define the two list. Change the relevant part of the code like this
moves=[pen.forward, pen.backward]
turns=[pen.right, pen.left]
while True:
pen.color(random.randint(0,255), random.randint(0,255), random.randint(0,255))
random.choice(turns)(90)
random.choice(moves)(30)
The first problem is that you don't list function calls in the lists moves and turns but the results of the calls. The second problem is that you don't call functions after the random.choice calls. What you are actually getting from this is the flickering effect of the visible pen tip that endlessly changes the color.
On way to fix it is already shown in buran's answer. Another way that keeps the turn and move arguments out of the loop is the following, here lambda : transforms the function calls into anonymous functions to which references are stored in moves and turns:
Another option is to extract the actual moves and turns into functions
from turtle import Turtle
from turtle import Screen
import random
pen = Turtle()
pen.pensize(8)
pen.speed(10)
window = Screen()
window.colormode(255)
moves=[lambda : pen.forward(30), lambda : pen.backward(30)]
turns=[lambda : pen.right(90), lambda : pen.left(90)]
for _ in range(100):
pen.color(random.randint(0,255),random.randint(0,255),random.randint(0,255))
random.choice(turns)()
random.choice(moves)()
window.exitonclick()
I decided to only draw 10 lines, so the turtle will most likely remain on screen. For a better way to get rid of the while True loop (including explanation) see cdlane's answer!

In Python, how can I execute two Turtle commands simultaneously?

As in having two Turtles moving at once. For example, I import two turtles, then try to have both of them move forward alongside each other. How can I do this?
bob = turtle.Turtle()
john = turtle.Turtle()
def move_turtles(ammount):
for i in range(ammount // 10):
bob.forward(10)
john.forward(10)
move_turtles(100)
There's no way to move them at the same time, although you can use something like that. It moves the turtles by 10 points each, so it gives the impression that they are moving together, but they are actually moving separately by little ammounts. It repeats the operation (ammount //10) times, and moves 10 in each iteration, so if you were to give 50 as an input, it would move 5 times 10 points, resulting in 50. You can then customize the function to move by a little a turtle so they don't overlap and so on.
You can move multiple turtles independently at the same time using timer events -- you can even have them move at different rates, both in time and space:
import turtle
turtle.setworldcoordinates(0, -100, 100, 100)
bob = turtle.Turtle(shape="turtle")
bob.penup()
bob.sety(20)
john = turtle.Turtle(shape="turtle")
john.penup()
john.sety(-20)
def move_bob():
bob.forward(1)
if bob.xcor() < 90:
turtle.ontimer(move_bob, 75)
def move_john():
john.forward(2)
if john.xcor() < 90:
turtle.ontimer(move_john, 100)
move_bob()
move_john()
turtle.exitonclick()
Other folks also use threads to achieve this but timer events are built into the turtle module.
There is a way to control frames using the Turtle module - you need to change the screen attributes.
screen = turtle.Screen()
screen.tracer(0)
This method makes all turtle movement invisible until you run screen.update(), and then every turtle will be visually updated at the same time on the screen. In your case, you can write screen.update() after the movement of both turtles, and they will appear to move at the same time.

Categories

Resources