Есть ли какой-нибудь способ избежать замедления Turtle, чем больше строк она должна напечатать?

#python #turtle-graphics

#python #turtle-графика

Вопрос:

Я создал программу для генерации случайного 2D-массива из единиц и нулей, которые я затем печатаю в виде зеленых «земельных» плиток над синим фоном, чтобы сгенерировать небольшую «карту». Я пытался оптимизировать код настолько, насколько я знаю, но когда я пытаюсь напечатать что-либо выше 100×100, это сильно замедляется. Если я настрою его на печать построчно, я вижу, что для печати строк требуется намного больше времени, чем больше карт, которые turtle уже напечатал. Я не знаю, почему это так (я не очень разбираюсь в turtle или рендеринге в целом), но я бы очень хотел знать, как решить эту проблему. Если это невозможно, могу ли я получить рекомендации для других библиотек / языков, на которых я мог бы попробовать это? Я хотел бы делать больше подобных программ, и я не против изучить что-то новое. 🙂

Вот мой код:

 import turtle
import random
import time

d = turtle.Turtle()
d.ht()
wn = turtle.Screen()
wn.setup(width=0.45,height=0.8,startx=800,starty=50)
wn.bgcolor("#002240")
turtle.tracer(0,0)
d.penup()
interval = 10

def square(col) :
    d.pendown()
    d.color(col)
    d.begin_fill()
    for i in range(4) :
        d.fd(interval)
        d.right(90)
    d.end_fill()
    d.penup()

size = int(input("Enter map size  "))
custom_interval = input("Custom interval?  ")
if custom_interval != '' :
    interval = int(custom_interval)
int_by_size = interval * size

start_gen = time.time()
data = []
for i in range(size) :
    gen_line = []
    [gen_line.append(random.randint(0,1)) for i in range(size)]
    data.append(gen_line)
end_gen = time.time()
print("GEN DONE IN",end_gen-start_gen)

d.goto(-int_by_size/2,int_by_size/2)
start_draw = time.time()

d.pendown()
d.color("blue")
d.begin_fill()
for i in range(4) :
    d.fd(int_by_size)
    d.right(90)
d.end_fill()
d.penup()

for y,line in enumerate(data) :

    for x,tile in enumerate(line) :

        if tile == 1 :
            square("green")
            d.fd(interval)
        else :
            d.fd(interval)

    #Comment out to print entire map at once
    turtle.update()
        
    d.backward(int_by_size)
    d.sety(d.ycor()-interval)
    
end_draw = time.time()
print("DRAW DONE IN",end_draw-start_draw)
           
wn.exitonclick()
 

Ответ №1:

Моя переработка вашего кода ниже ускоряет рисование на порядок, переключаясь с рисования на штамповку и другие трюки:

 from turtle import Screen, Turtle
from random import randint
import time

CURSOR_SIZE = 20

interval = 10

size = int(input("Enter map size: "))
custom_interval = input("Custom interval: ")
if custom_interval != '':
    interval = int(custom_interval)
int_by_size = interval * size

screen = Screen()
screen.setup(width=0.45, height=0.8, startx=800, starty=50)
screen.bgcolor('#002240')
screen.tracer(False)

x, y = interval/2 - int_by_size/2, int_by_size/2 - interval/2

start_gen = time.time()

data = [(randint(False, True) for _ in range(size)) for _ in range(size)]

print("GEN DONE IN", time.time() - start_gen)

start_draw = time.time()

turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.penup()

turtle.color('blue')
turtle.shapesize(int_by_size / CURSOR_SIZE)
turtle.stamp()

turtle.color('green')
turtle.shapesize(interval / CURSOR_SIZE)
turtle.goto(x, y)

for line in data:
    dx = x

    for tile in line:
        if tile:
            turtle.setx(dx)
            turtle.stamp()

        dx  = interval

    # Comment out to print entire map at once
    screen.update()

    y -= interval
    turtle.goto(x, y)

print("DRAW DONE IN", time.time() - start_draw)

screen.tracer(True)
screen.exitonclick()
 

Некоторые из моих оптимизаций, которые вам, возможно, придется отменить, например, сделать данные списком генераторов вместо списка списков (ускоряет генерацию данных, но подходит только для одного прохода). Кроме того, помните, что размер окна width=0.45, height=0.8 зависит от размера вашего экрана — другие пользователи, работающие на других экранах, получат окно другого размера.