Как мне сбросить экран в python turtle, чтобы я мог анимировать объект? - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь нарисовать изображение черепахи, в котором лес, горы и облако всплывают в верхней части экрана.

Я не могу импортировать какие-либо модули, которые необходимо загрузить, он должен быть собственным.

Чтобы анимировать объект поверх фона в Python Turtle, мне нужно нарисовать объект, затем перерисовать фон, а затем перерисовать объект в новой позиции.Проблема в том, что код, который я использую для рисования фона, заставляет деревья и горы располагаться в случайном порядке (чтобы они выглядели более естественно).Мои функции setup () рисуют случайный фон.Я хочу знать, как мне перерисовать тот же самый фон в моей функции main ()?

Вот код, который я использую:

# Elan Shetreat-Klein, 4/9/2019, Project 4
# A program to draw a landscape
from shapes import *
import random
import time

def background():
    s.bgcolor('#87ceeb')
    turtle.pencolor('#402905')
    draw_rectangle(-500, -350, 1000, 200, c='#402905')


def tree(x, scale, leaf_color, trunk_color):
    y = -350 + 200 * scale
    draw_rectangle(x, y, 30 * scale, 200 * scale, c=trunk_color)
    draw_tri(x + 15 * scale, y + 25 * scale, 175 * scale, c=leaf_color)
    draw_tri(x + 15 * scale, y + 100 * scale, 150 * scale, c=leaf_color)
    draw_tri(x + 15 * scale, y + 175 * scale, 100 * scale, c=leaf_color)


def forest():
    dark_greens = ['#006400', '#008000', '#556B2F', '#00611C', '#003300', '#004F00']
    light_greens = ['#397D02', '#476A34', '#308014', '#3D8B37', '#00CD00', '#0AC92B']

    tree_locations = 3 * [x for x in range(-500, 600, 100)]
    random.shuffle(tree_locations)

    draw_rectangle(-500, -150, 1000, 200, c='#3B5323')

    for xPos in tree_locations:
        Xvary = random.randrange(-50, 50)
        Svary = random.randrange(60, 80) / 100
        tree(xPos + Xvary, Svary, dark_greens[random.randrange(0, 5)], '#603311')

    for xPos in tree_locations:
        Xvary = random.randrange(-40, 40)
        Svary = random.randrange(70, 90) / 100
        tree(xPos + Xvary, Svary, light_greens[random.randrange(0, 5)], '#734A12')


def mountain_range():
    mountX = [x for x in range(-450, 550, 150)]
    random.shuffle(mountX)
    mountain_colors = ['#6F4242', '#856363', '#8B6969']
    for xPos in mountX:
        Xvary = random.randrange(-25, 25)
        Svary = random.randrange(90, 110) / 100
        x = xPos + Xvary
        side = 600 * Svary
        y = -350 + (sqrt((3 * side ** 2) / 4)) // 2
        draw_tri(x, y, side, c=mountain_colors[mountX.index(xPos) % 3])


def create_cloud():
    global cloud
    cloud = {}
    for i in range(20):
        x2, y2 = random.randrange(-90, 90), random.randrange(-25, 25)
        cloud[x2] = y2
        print(cloud)


def draw_cloud(x, y):
    turtle.pu()
    turtle.goto(x, y)
    turtle.dot(100, 'white')
    for x2, y2 in cloud.items():
        turtle.goto(x2 + x, y2 + y)
        size = abs((1 - (turtle.distance(x, y)//100)) * 100)
        turtle.dot(size, 'white')


turtle.speed(0)
s = turtle.getscreen()


def setup():
    turtle.tracer(0, 0)
    s.title("Forest with mountains in the backround")
    s.bgcolor('white')
    background()
    mountain_range()
    forest()


def main():
    create_cloud()
    for xPos in range(-500, 500, 1):
        setup()
        draw_cloud(xPos, 300)
        turtle.update()
        time.sleep(0.0001)
main()


turtle.done()

Рандомизация довольно проста,он просто немного меняет размер и положение X для каждого дерева и горы.Я уже понял, как сохранить то же облако, это не проблема.

В коде новый случайный фон перерисовывается сам по себе, и он начинает замедляться.Когда я использовал turtle.clear () или turtle.reset (), экран продолжал мигать синим, поэтому я не уверен, что с этим делать.

Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Трудность, с которой вы столкнулись, связана с использованием одной черепахи. Это можно сделать, не перерисовывая полностью всю сцену каждый раз с некоторым хитрым мониторингом размера буфера отмены - отмена рисования только облака перед перерисовкой.

Или это можно сделать проще, выделив вторую черепаху только для рисования облака и используя clear() и draw_cloud() на этой черепашке между обновлениями, оставляя остальную часть пейзажа нетронутой. Ниже ваш код переработан в том же духе и с другими настройками:

from shapes import *
from random import choice, randrange, shuffle

MOUNTAIN_COLORS = ['#6F4242', '#856363', '#8B6969']
DARK_GREENS = ['#006400', '#008000', '#556B2F', '#00611C', '#003300', '#004F00']
LIGHT_GREENS = ['#397D02', '#476A34', '#308014', '#3D8B37', '#00CD00', '#0AC92B']

def background():
    screen.bgcolor('#87ceeb')
    default_turtle.pencolor('#402905')
    draw_rectangle(-500, -350, 1000, 200, c='#402905')

def tree(x, scale, leaf_color, trunk_color):
    y = -350 + 200 * scale
    draw_rectangle(x, y, 30 * scale, 200 * scale, c=trunk_color)
    draw_tri(x + 15 * scale, y + 25 * scale, 175 * scale, c=leaf_color)
    draw_tri(x + 15 * scale, y + 100 * scale, 150 * scale, c=leaf_color)
    draw_tri(x + 15 * scale, y + 175 * scale, 100 * scale, c=leaf_color)

def forest():
    tree_locations = 3 * [x for x in range(-500, 600, 100)]
    shuffle(tree_locations)

    draw_rectangle(-500, -150, 1000, 200, c='#3B5323')

    for xPos in tree_locations:
        Xvary = randrange(-50, 50)
        Svary = randrange(60, 80) / 100
        tree(xPos + Xvary, Svary, choice(DARK_GREENS), '#603311')

    for xPos in tree_locations:
        Xvary = randrange(-40, 40)
        Svary = randrange(70, 90) / 100
        tree(xPos + Xvary, Svary, choice(LIGHT_GREENS), '#734A12')

def mountain_range():
    mountX = [x for x in range(-450, 550, 150)]
    shuffle(mountX)

    for xPos in mountX:
        Xvary = randrange(-25, 25)
        Svary = randrange(90, 110) / 100
        x = xPos + Xvary
        side = 600 * Svary
        y = -350 + (sqrt((3 * side ** 2) / 4)) // 2
        draw_tri(x, y, side, c=choice(MOUNTAIN_COLORS))

def create_cloud():
    positions = []

    for _ in range(20):
        x, y = randrange(-90, 90), randrange(-25, 25)
        positions.append((x, y))

    return positions

def draw_cloud(x, y):
    cloud_turtle.clear()
    cloud_turtle.penup()
    cloud_turtle.goto(x, y)
    cloud_turtle.dot(100, 'white')

    for x2, y2 in cloud:
        cloud_turtle.goto(x2 + x, y2 + y)
        size = abs((1 - (cloud_turtle.distance(x, y) // 100)) * 100)
        cloud_turtle.dot(size, 'white')

def setup():
    screen.title("Forest with mountains in the background")
    background()
    mountain_range()
    forest()

def animate(xPos=-500):
    draw_cloud(xPos, 300)
    screen.update()

    if xPos < 625:  # have draw_cloud() return cloud width & replace this number
        screen.ontimer(lambda x=xPos + 1: animate(x), 100)
    else:
        screen.tracer(True)  # stop animation

screen = turtle.Screen()
screen.tracer(False)

default_turtle = turtle.getturtle()
default_turtle.hideturtle()

cloud_turtle = turtle.Turtle()
cloud_turtle.hideturtle()
cloud = create_cloud()

setup()
screen.update()

animate()

screen.exitonclick()

Я изменил способ хранения вашего облака из словаря в список позиций кортежей, поскольку словарь не подходит для этой цели.

0 голосов
/ 12 апреля 2019

Существует несколько вариантов: вы можете либо принять случайные решения перед рисованием и сохранить все эти решения для перерисовки, либо сделать вывод вашего случайного модуля детерминированным, предоставив начальное число.Второе - более хакерское решение, но требует меньше изменений в вашем коде.

Измените вторую строку на: import random as really_random

Затем, в вашем основном цикле, прямо перед вызовом setup() добавить строку вроде: random = really_random.Random(0).Эта строка может вам понадобиться и до create_cloud (), поэтому у вас есть ссылка на random.

Если вы хотите менять свой фон каждый раз, когда вы запускаете программу, измените 0 на другое случайное начальное число.Например, ваш основной может выглядеть так:

def main():
    my_random_seed = really_random.randint(0,10000000)
    random = really_random.Random(my_random_seed)
    create_cloud()
    for xPos in range(-500, 500, 1):
        random = really_random.Random(my_random_seed)
        setup()
        draw_cloud(xPos, 300)
        turtle.update()
        time.sleep(0.0001)
...