How to create new Python Turtle image each iteration? - python

I want to create 100 images via Python Turtle and each iteration there should be only 2 geometric shapes drawn on each image (files test0.jpg, test1.jpg etc). However, in my code each next image is drawn on the previous one, which causes collision. Can you help me please?
import turtle
import random
from PIL import Image
def generate(tur1):
a = random.randint(2, 7)
b = random.randint(2, 7)
c = random.randint(50, 100)
if a != 2:
for i in range(a):
tur1.forward(c)
tur1.left(360.0 / a)
else:
tur1.circle(c)
tur1.penup()
tur1.goto(-200, 0)
tur1.pendown()
if b != 2:
for j in range(b):
tur1.forward(c)
tur1.left(360.0 / b)
else:
tur1.circle(c)
for i in range(0, 100):
tur2 = turtle.Turtle()
tur2.color('green')
tur2.speed(1)
tur2.hideturtle()
generate(tur2)
screen = tur2.getscreen()
screen.setup(600, 600)
canvas = screen.getcanvas()
canvas.postscript(file="test"+str(i)+".eps")
img = Image.open("test"+str(i)+".eps")
img.save("test"+str(i)+".jpg")

You need to use something like turtle.clear() (+1 #JohnnyMopp) or more likely turtle.reset(), or turtle.home() in combination with turtle.clear(), since you moved the turtle. A slight rework of your code:
from turtle import Screen, Turtle
from random import randint
from PIL import Image
def generate(turtle):
a = randint(2, 7)
b = randint(50, 100)
if a == 2:
turtle.circle(b)
else:
for _ in range(a):
turtle.forward(b)
turtle.left(360 / a)
turtle.penup()
turtle.setx(-200)
turtle.pendown()
a = randint(2, 7)
if a == 2:
turtle.circle(b)
else:
for _ in range(a):
turtle.forward(b)
turtle.left(360 / a)
screen = Screen()
screen.setup(600, 600)
turtle = Turtle()
for i in range(10):
# inside loop only because reset() also resets these...
turtle.hideturtle()
turtle.color('green')
turtle.speed('fastest')
eps = "test" + str(i) + ".eps"
jpg = "test" + str(i) + ".jpg"
generate(turtle)
canvas = screen.getcanvas()
canvas.postscript(file=eps)
img = Image.open(eps)
img.save(jpg)
turtle.reset()

Related

i wanna draw a chessboard and here is my code(edited)

it has no error now but i want to draw a chess board but this thing just randomly output something else:)))))
i think there is something wrong with the fill function tho
import turtle
screen = turtle.Screen()
screen.setup(800,800)
screen.bgcolor('pink')
screen.colormode(255)
screen.title("chessboard")
turtle = turtle.Turtle()
def draw(length,angle):
for i in range (4):
turtle.forward(length)
turtle.right(angle)
length = 30
angle = 90
coor = -120
num = 64
def board(length):
draw(length,angle)
turtle.forward(length)
def limit():
for q in range (8):
board(length)
def pos(coor,length):
for w in range(8):
turtle.penup()
turtle.setpos(coor,coor+30*w)
turtle.pendown()
limit()
def fill():
for q in range (8):
for w in range(8):
if (q+w)%2==0:
turtle.fillcolor('#000000')
else:
turtle.fillcolor('#FFFFFF')
def repeat():
for h in range (8):
draw(length,angle)
turtle.forward(length)
def color():
turtle.begin_fill()
repeat()
pos(coor,length)
fill()
turtle.end_fill()
turtle.speed(0)
turtle.penup()
turtle.goto(coor, coor)
turtle.pendown()
turtle.hideturtle()
screen.update()
color()
it has no error now but i want to draw a chess board but this thing just randomly output something else:)))))
i think there is something wrong with the fill function tho
I'm just learning python as well, so I found your problem being an interesting thing to try to do myself.
Please see below a solution that works, using some ideas from your code and my own implementation too.
If anything of the above helps you fix your own code, or have any questions I might be able to answer, please let me know :)
import turtle
# draw a square at given pos
def draw_square(t, fwd, angle):
for _ in range(4):
t.forward(fwd)
t.right(angle)
def changePos(t, startPos, endPos, penUp):
if penUp:
t.pu()
t.goto(startPos, endPos)
if penUp:
t.pd()
# Let's skip the drawing all together?
turtle.tracer(0, 0)
# taking input for the side of the square
squareSize = 100
angle = 90
boardSquares = 8
startPos = -(squareSize * (boardSquares/2)), (squareSize * (boardSquares/2)) #start from top-left
print("Start position: ", startPos)
screen = turtle.Screen()
screen.setup(850, 850)
screen.bgcolor('pink')
screen.title("chessboard")
# create the white squares
squares = turtle.Turtle()
squares.hideturtle()
squares.fillcolor("white")
squares.pensize(1)
squares.pencolor("red")
changePos(squares, startPos[0], startPos[1], True)
for r in range(8):
for c in range(8):
if (r + c) % 2 == 0:
squares.fillcolor('#000000')
else:
squares.fillcolor('#FFFFFF')
changePos(squares, startPos[0] + (squareSize * c), startPos[1] - (squareSize * r), True)
squares.begin_fill()
draw_square(squares, squareSize, angle)
squares.end_fill()
# let's draw the board edge
board = turtle.Turtle()
board.hideturtle()
changePos(board, startPos[0], startPos[1], True)
board.pensize(5)
board.pencolor("brown")
draw_square(board, boardSquares * squareSize, angle)
turtle.update()
turtle.exitonclick()

How can i print random color circles in turtle?

the below code is one part of my code. I would like to print random colored circles. But it does not work. Can someone please help me to correct this code? circles shouldnt be overalapped!!
ERROR is bad color sequence: (164, 13, 120)
from random import randint
from svg_turtle import SvgTurtle
import turtle
from turtle import Turtle
import json
def fiber_circle(fiber, width, height):
fiber_r=25
fiber_num = 100
cursor_size = 20
fiber.hideturtle()
fiber.screen.bgcolor("white")
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
fiber.color(r,g,b)
fiber.screen.colormode(255)
fiber.shape("circle")
fiber.shapesize(fiber_r / cursor_size)
fiber.speed("fastest")
fiber.penup()
fibers = []
for _ in range(fiber_num):
fiberr = fiber.clone()
fiberr.setposition(
randint(-width / 2, width / 2),
randint(-height / 2, height / 2),
)
Your program, if it ran, would simply change the turtle cursor into different colors, but in one location. If you want to draw randomly colored circles all over your window, you can try something like the following which uses dot() to draw them:
from turtle import Screen, Turtle
from random import randint
FIBER_RADIUS = 25
FIBER_NUMBER = 100
CURSOR_SIZE = 20
def fiber_circle(fiber):
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
x = randint(FIBER_RADIUS - width//2, width//2 - FIBER_RADIUS)
y = randint(FIBER_RADIUS - height//2, height//2 - FIBER_RADIUS)
fiber.color(r, g, b)
fiber.goto(x, y)
fiber.dot(FIBER_RADIUS * 2) # dot() takes a diameter
screen = Screen()
screen.colormode(255)
width, height = screen.window_width(), screen.window_height()
fiber = Turtle()
fiber.hideturtle()
fiber.speed("fastest")
fiber.penup()
for _ in range(FIBER_NUMBER):
fiber_circle(fiber)
screen.exitonclick()
Alternatively, you can use your original approach of shaping, sizing and coloring the turtle itself, but then use stamp() to leave behind a circle while moving the turtle randomly around the screen:
...
def fiber_circle(fiber):
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
x = randint(FIBER_RADIUS - width//2, width//2 - FIBER_RADIUS)
y = randint(FIBER_RADIUS - height//2, height//2 - FIBER_RADIUS)
fiber.color(r, g, b)
fiber.goto(x, y)
fiber.stamp()
screen = Screen()
screen.colormode(255)
width, height = screen.window_width(), screen.window_height()
fiber = Turtle()
fiber.hideturtle()
fiber.shape('circle')
fiber.shapesize(FIBER_RADIUS * 2 / CURSOR_SIZE) # CURSOR_SIZE is effectively a diameter
fiber.speed('fastest')
fiber.penup()
for _ in range(FIBER_NUMBER):
fiber_circle(fiber)
...

python canvas.find_overlapping appears to have inverted y-axis

I am trying to find the color of the canvas under a Python turtle. I use canvas.find_overlapping but it is only successful when I negate the ycor, implying that the y-axis is inverted in the canvas object, compared to what is shown. Is there a problem with my code or is the y-axis inverted?
import turtle
wn = turtle.Screen()
maze_drawer = turtle.Turtle()
maze_drawer.color("purple")
maze_drawer.speed("fastest")
path_width = 15
def get_pixel_color(x, y):
c = turtle.Screen().getcanvas()
# -y should not work??
items = c.find_overlapping(x, -y, x, -y)
if len(items) > 0:
return c.itemcget(items[0], "fill") # get 0 object (canvas)
# draw simplified maze
wall_len = 0
for i in range(10):
maze_drawer.left(90)
wall_len += path_width
maze_drawer.forward(wall_len)
# navigate maze from center
maze_runner = turtle.Turtle()
maze_runner.color("green")
maze_runner.penup()
maze_runner.goto(-path_width, -path_width)
# test in y dir: maze_runner.setheading(90)
clear = True
while(clear):
maze_runner.forward(1)
color_at_turtle = get_pixel_color(maze_runner.xcor(), maze_runner.ycor())
if (color_at_turtle == "purple"):
clear = False
wn.exitonclick()
Neat use of tkinter pixel detection within turtle! If the inverted Y coordinate is bothersome, you can flip it from turtle's perspective:
from turtle import Screen, Turtle
screen = Screen()
width, height = screen.window_width() / 2, screen.window_height() / 2
screen.setworldcoordinates(-width, height, width, -height) # flip Y coordinate
Then your code doesn't have to think about negating Y as long as you know you're drawing upside down:
from turtle import Screen, Turtle
PATH_WIDTH = 15
def get_pixel_color(x, y):
canvas = screen.getcanvas()
items = canvas.find_overlapping(x, y, x, y)
if items:
return canvas.itemcget(items[0], "fill") # get 0 object (canvas)
return None
screen = Screen()
width, height = screen.window_width() / 2, screen.window_height() / 2
screen.setworldcoordinates(-width, height, width, -height)
maze_drawer = Turtle(visible=False)
maze_drawer.color("purple")
maze_drawer.speed("fastest")
# draw simplified maze
wall_len = 0
for _ in range(20):
maze_drawer.left(90)
wall_len += PATH_WIDTH
maze_drawer.forward(wall_len)
# navigate maze from center
maze_runner = Turtle()
maze_runner.color("dark green", "green")
maze_runner.penup()
maze_runner.goto(-PATH_WIDTH, -PATH_WIDTH)
def run_maze():
maze_runner.forward(1)
x, y = maze_runner.position()
color_at_turtle = get_pixel_color(x, y)
if color_at_turtle == "purple":
maze_runner.backward(PATH_WIDTH - 1)
maze_runner.left(90)
x, y = maze_runner.position()
if -width < x < width and -height < y < height:
screen.ontimer(run_maze, 10)
run_maze()
screen.exitonclick()

Python while loop with no expressions

Is is possible to have a while loop in Python with no expressions?
I know in other languages you can do something like:
while(flag) {};
I'm trying to do something similar in Python but cannot find an answer.
Here is what I have so far:
import turtle
from random import randrange
def is_in_screen(t, w): #CHECKS TO SEE IF STILL IN SCREEN
flag = True
r = w.window_width() / 2
l = r * -1
u = w.window_height() / 2
d = u * -1
x_cor = t.xcor()
y_cor = t.ycor()
if (x_cor < l or x_cor > r or y_cor < d or y_cor > u):
flag = False
return flag
def move_to(t, w): #MOVE IN RANDOM DIRECTION AND RANDOM DISTANCE
t.forward(randrange(1, 100))
if (randrange(1, 2) == 1):
t.left(randrange(1, 180))
else:
t.right(randrange(1, 180))
return is_in_screen(t, w)
def random_movement(t1, t2, w):
while (move_to(t1, w) and move_to(t2, w)): #<<<<<<<<LOOP IN QUESTION
i = 0
def main():
t1 = turtle.Turtle()
t2 = turtle.Turtle()
w = turtle.Screen()
t1.color("green")
t2.color("purple")
random_movement(t1, t2, w)
w.exitonclick()
main()
The reason I'm trying to do no expressions is because I want the second turtle to not move if the first turtle goes out of bounds. Also, I do not want return statements in the function.
You're looking for the pass keyword.
while (flag):
pass
Below is a rework of your code with the while expr: pass that everyone's suggesting along with some other style and idiom changes to tighten up the code:
from turtle import Screen, Turtle
from random import randrange
def is_in_screen(turtle, screen):
r = screen.window_width() / 2
u = screen.window_height() / 2
x, y = turtle.position()
return -r < x < r and -u < y < u
def move_to(turtle, screen):
turtle.forward(randrange(1, 100))
turtle.left(randrange(-180, 180)) # negative left turn is a right turn
return is_in_screen(turtle, screen)
def random_movement(turtle_1, turtle_2, screen):
while move_to(turtle_1, screen) and move_to(turtle_2, screen): pass
screen = Screen()
t1 = Turtle()
t1.color("green")
t2 = Turtle()
t2.color("purple")
random_movement(t1, t2, screen)
screen.exitonclick()

How to add a countdown timer to my turtle program?

I'm trying to make a game using turtle where the player has to click as many randomly distributed circles in a set amount of time, but I'm stumped on how to create a timer inside the game. Whenever I try to set the timer, it counts down before the game starts or counts down after 1 circle spawns. I want to have it count down as the game starts, and have the game end once the timer ends.
I'm also trying to create a score counter, but am I using circle.onclick wrong?
This is what I've been trying to do:
from turtle import Turtle, Screen
from random import random, randint
import time
CURSOR_SIZE = 20
def score():
num=0
print("Score: ",num)
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
else:
break
circle.showturtle()
circle.onclick(lambda x, y, t=circle: t.hideturtle())
circle.onclick(num=num+1)
return radius, circle
screen = Screen()
screen.bgcolor("lightgreen")
screen.title("Speed Clicker")
width, height = screen.window_width(), screen.window_height()
circles = []
for _ in range(0, 20):
for i in range(40):
print(str(40-i)+" seconds remain")
time.sleep(1)
rgb = (random(), random(), random())
circles.append(my_circle(rgb))
screen.mainloop()
The last thing I'm curious about is if it's possible to have the timer and score printed ON the game, rather than on the Python Shell.
I've made a few alterations and this seems to work. I have put the score and the time left in the title bar of the game. Thanks
import turtle
from random import random, randint
import time
CURSOR_SIZE = 20
num=0
def increase_score():
global num
num += 1
def my_circle(color):
radius = randint(10, 50)
circle = turtle.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
else:
break
circle.showturtle()
circle.onclick(lambda x,y,t=circle: (circle.hideturtle(), increase_score()))
return radius, circle
screen = turtle.Screen()
screen.bgcolor("lightgreen")
screen.title("Speed Clicker")
width, height = screen.window_width(), screen.window_height()
circles = []
gameLength = 5
# Higher number means faster blocks
# 1-10
difficulty = 10
startTime = time.time()
while True:
time.sleep(1/difficulty)
rgb = (random(), random(), random())
timeTaken = time.time() - startTime
circles.append(my_circle(rgb))
screen.title('SCORE: {}, TIME LEFT: {}'.format(num,int(round(gameLength - timeTaken,0))))
if time.time() - startTime > gameLength:
break
screen.title('FINISHED! FINAL SCORE: {}'.format(num))
screen.mainloop()

Categories