Почему три планеты (черепахи) не могут быть нарисованы одновременно? - PullRequest
0 голосов
/ 12 ноября 2018

Я написал файл python для имитации орбиты планет, но не могу нарисовать их одновременно. В документе о черепах сказано: «Чтобы использовать несколько черепах на экране, нужно использовать объектно-ориентированный интерфейс». Но как это сделать?

# -*- coding:utf-8 -*-

import math
import turtle

#define a class of planets, which rotate in a oval
class Planet(turtle.Turtle):
    def orbit(self, a, b, t):
        c = math.sqrt(a ** 2 - b ** 2)
        self.goto(a * math.cos(t / 200) + c, b * math.sin(t / 200))

def Sun():
    sun.color('yellow')
    sun.pd()
    sun.showturtle()
    for t in range(1000):
        sun.orbit(0, 0, t)

def Mercury():
    mercury.color('blue')
    mercury.speed(0)
    mercury.pu()
    mercury.goto(50+math.sqrt(50 ** 2 - 49.9 ** 2), 0)
    mercury.pd()
    mercury.showturtle()
    mercury.lt(90)
    for t in range(1000):
        mercury.orbit(50, 49.9, t)

def Earth():
    earth.color('red')
    earth.speed(0)
    earth.pu()
    earth.goto(75+math.sqrt(75 ** 2 - 74.9 ** 2), 0)
    earth.pd()
    earth.showturtle()
    earth.lt(90)
    for t in range(1000):
        earth.orbit(75, 74.9,t)

sun = Planet(shape='circle')
mercury = Planet(shape='circle')
earth = Planet(shape='circle')

turtle.Screen().ontimer(Sun, 100)
turtle.Screen().ontimer(Mercury, 100)
turtle.Screen().ontimer(Earth, 100)

turtle.Screen().mainloop()

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Я был с @PeterWood до этого момента:

Вы можете хранить планеты в списке:

планет = [ртуть, земля]

Это имеет смысл только для меня, если этот список является переменной класса из Planet и автоматически обновляется в процессе создания новой планеты.Т.е. не внешняя сущность, на которую ссылается метод объекта!Но даже тогда, движется ли Солнце планет (через список) или планеты движутся сами по себе вокруг Солнца.

Будучи поклонником событий таймера, я бы поступил иначе.Я бы позволил планетам присоединиться без регистрации, вручную или иным образом, а также добавить возможность имитировать разные скорости планет:

from math import sqrt, cos, sin, pi
from turtle import Screen, Turtle

class Star(Turtle):
    def __init__(self, colour):
        super().__init__(shape='circle')

        self.color(colour)

class Planet(Turtle):
    def __init__(self, colour, a, b, period):
        super().__init__(shape='circle')

        self.color(colour)
        self.a = a
        self.b = b
        self.period = period

        self.t = 0
        self.speed('fastest')
        self.shapesize(0.25)

        self.penup()
        self.orbit()
        self.pendown()

    def orbit(self):
        c = sqrt(self.a ** 2 - self.b ** 2)
        angle = self.t / (2 * pi)

        self.goto(self.a * cos(angle) + c, self.b * sin(angle))

        self.t += 1
        screen.ontimer(self.orbit, self.period)

screen = Screen()

sun = Star('yellow')
mercury = Planet('blue', 50, 49.9, 88)
earth = Planet('red', 75, 74.9, 365)

screen.mainloop()

У этого подхода есть свои проблемы, как в кодированиии в реальности, но это делает вещи довольно простыми и имеет место для добавления функций:

enter image description here

0 голосов
/ 12 ноября 2018

Вы выполняете всю орбиту для каждой планеты, прежде чем перейти к следующей.

Вы можете создать функцию для выполнения чередования орбит:

def orbit_planets():
    for t in range(1000):
        mercury.orbit(50, 49.9, t)
        earth.orbit(75, 74.9,t)

turtle.Screen().ontimer(orbit_planets, 100)

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

Однако вы можете поместить этот код в класс Planet:

class Planet(turtle.Turtle):
    def __init__(self, colour, a, b):
        turtle.Turtle.__init__(self)
        self.color(colour)
        self.speed(0)
        self.pu()
        self.goto(a + math.sqrt(a ** 2 - b ** 2), 0)
        self.pd()
        self.showturtle()
        self.lt(90)
    ...

Тогда:

mercury = Planet('blue', 50, 49.9)
earth = Planet('red', 75, 74.9)

Кроме того, класс планеты может отслеживать a и b (нужны лучшие имена!), И тогда функции orbit не потребуется передача значений. Это означает, что класс Planet управляет своими данными и поведением, суть объектно-ориентированного проектирования:

    def __init__(self, a, b):
        ...
        self.a = a
        self.b = b

и

    def orbit(self, t):
        c = math.sqrt(self.a ** 2 - self.b ** 2)
        self.goto(self.a * math.cos(t / 200) + c,
                  self.b * math.sin(t / 200))

Тогда функция таймера орбиты будет просто:

def orbit_planets():
    for t in range(1000):
        mercury.orbit(t)
        earth.orbit(t)

Если пойти дальше, вы можете сохранить планеты в списке:

planets = [mercury, earth]

def orbit_planets():
    for t in range(1000):
        for planet in planets:
            planet.orbit(t)
...