Python 更改海龟图形的操作

Python 更改海龟图形的操作,python,python-3.x,simulation,turtle-graphics,Python,Python 3.x,Simulation,Turtle Graphics,首先,我对编程非常陌生,在这里我吃不完。无论如何 我正在尝试用python作为模型构建太阳系/轨道模拟 这是我的完整代码: # Import math and turtle import math from turtle import * import turtle # Gravitational Constant G = 6.67428e-11 # Scale: 1 pixel = 1 astronomical unit # 1 astronomical unit = 1 AU = 14959

首先,我对编程非常陌生,在这里我吃不完。无论如何

我正在尝试用python作为模型构建太阳系/轨道模拟

这是我的完整代码:

# Import math and turtle
import math
from turtle import *
import turtle
# Gravitational Constant
G = 6.67428e-11
# Scale: 1 pixel = 1 astronomical unit
# 1 astronomical unit = 1 AU = 149597900 km
AU = (149.6e6 * 1000)  # 149.6 million km in meters
Scale = 250 / AU
wn = turtle.Screen()
wn = turtle.bgcolor('black')


class body(Turtle):

    # Subclass of turtle representing a body
    # Additional attributes:
    # mass in kg
    # vx, vy: x, y velocities in m/sc
    # px, py: x, y positions in m
    # Set background to black
    # Turtle.bgcolor('black')
    name = 'body'
    mass = None
    vx = vy = 0.0
    px = py = 0.0

    def attraction(self, other):

        # (body): (fx, fy)
        # returns the force exerted on this body by the other body.
        # Report and error if the other object is the same as this one.

        if self is other:
            raise ValueError("Attraction of object %r to itself requested" % self.name)

        # Compute the distance of the other body:

        sx, sy = self.px, self.py
        ox, oy = other.px, other.py
        dx = (ox - sx)
        dy = (oy - sy)
        d = math.sqrt(dx**2 + dy**2)

        # Report an Error if the distance is 0
        # ZeroDivisionError would happen later otherwise
        if d == 0:
            raise ValueError("Collision between objects %r and %r" % (self.name, other.name))

        # Compute the force of attraction

        f = G * self.mass * other.mass / (d**2)

        # Compute the direction of the force
        theta = math.atan2(dy, dx)
        fx = math.cos(theta) * f
        fy = math.sin(theta) * f
        return fx, fy


def updateInfo(step, bodies):

    # (int, [body])
    # Displays infomation about status of simulation.

    print('Step #{}'.format(step))
    for body in bodies:
        s = '{:<8} Pos.={:>6.2f} Vel.={:>10.3f}'.format(body.name, body.px/AU, body.py/AU, body.vy)
        print(s)
    print()


def loop(bodies):
    # (body)
    # Never returns; loop through the simulation and updates the positions of given bodies

    timestep = 24*3600  # One Day

    for body in bodies:
        body.penup()
        body.hideturtle()

    step = 1
    while True:
        updateInfo(step, bodies)
        step += 1

        force = {}
        for body in bodies:

            # Adds all the forces exerted on a body
            totalFx = totalFy = 0.0
            for other in bodies:
                # Don't calculate attraction to itself
                if body is other:
                    continue
                fx, fy = body.attraction(other)
                totalFx += fx
                totalFy += fy

            # Record the total force exerted
            force[body] = (totalFx, totalFy)

        # Update velocities based on the force.
        for body in bodies:
            fx, fy = force[body]
            body.vx += fx / body.mass * timestep
            body.vy += fy / body.mass * timestep

            # Update positions
            body.px += body.vx * timestep
            body.py += body.vy * timestep
            body.goto(body.px*Scale, body.py*Scale)
            body.dot(5)


def main():
    sun = body()
    sun.name = 'Sun'
    sun.mass = 1.98892 * 10**30
    sun.pencolor('yellow')

    earth = body()
    earth.name = 'Earth'
    earth.mass = 5.9742 * 10**24
    earth.px = -1*AU
    earth.vy = 29.783 * 1000
    earth.pencolor('blue')

    venus = body()
    venus.name = 'Venus'
    venus.mass = 4.8685 * 10**24
    venus.px = 0.723 * AU
    venus.vy = -35.02 * 1000
    venus.pencolor('orange')

    loop([sun, earth, venus])


if __name__ == '__main__':
    main()
#导入数学和乌龟
输入数学
从海龟进口*
进口海龟
#引力常数
G=6.67428e-11
#比例:1像素=1天文单位
#1天文单位=1 AU=149597900公里
AU=(149.6e6*1000)#1.496亿公里(米)
刻度=250/AU
wn=tutle.Screen()
wn=turtle.bgcolor('black')
团体(海龟):
#代表身体的海龟的亚纲
#其他属性:
#质量(kg)
#vx,vy:x,y速度,单位为m/sc
#px,py:x,y位置,单位为m
#将背景设置为黑色
#Turtle.bgcolor('black'))
名称='body'
质量=无
vx=vy=0.0
px=py=0.0
def吸引力(自身、其他):
#(正文):(外汇,财政年度)
#返回另一个实体施加在该实体上的力。
#如果另一个对象与此对象相同,则报告和错误。
如果self是他者:
raise VALUERROR(“请求将对象%r吸引到自身”%self.name)
#计算另一个实体的距离:
sx,sy=self.px,self.py
ox,oy=other.px,other.py
dx=(ox-sx)
dy=(oy-sy)
d=数学sqrt(dx**2+dy**2)
#如果距离为0,则报告错误
#否则,错误将在稍后发生
如果d==0:
raise VALUERROR(“对象%r和%r”%(self.name,other.name)之间的冲突”)
#计算吸引力
f=G*自身质量*其他质量/(d**2)
#计算力的方向
θ=math.atan2(dy,dx)
fx=数学cos(θ)*f
fy=数学sin(θ)*f
外汇收益,财政年度
def updateInfo(步骤,正文):
#(国际,[正文])
#显示有关模拟状态的信息。
打印('Step{}'。格式(Step))
对于身体中的身体:
格式(body.name,body.px/AU,body.py/AU,body.vy)
印刷品
打印()
def回路(主体):
#(正文)
#永不回头;循环模拟并更新给定实体的位置
时间步长=24*3600#一天
对于身体中的身体:
body.penup()
body.hideturtle()
步骤=1
尽管如此:
更新信息(步骤、正文)
步骤+=1
力={}
对于身体中的身体:
#添加施加在实体上的所有力
totalFx=totalFy=0.0
其他机构:
#不要计算对自己的吸引力
如果主体是其他主体:
持续
fx,fy=身体吸引力(其他)
totalFx+=fx
总fy+=fy
#记录施加的总力
力[体]=(totalFx,totalFy)
#基于力更新速度。
对于身体中的身体:
fx,fy=力[体]
body.vx+=fx/body.mass*timestep
body.vy+=fy/body.mass*timestep
#更新职位
body.px+=body.vx*timestep
body.py+=body.vy*timestep
body.goto(body.px*比例,body.py*比例)
正文.dot(5)
def main():
太阳=身体()
sun.name='sun'
太阳质量=1.98892*10**30
太阳色(“黄色”)
地球=身体()
earth.name='earth'
地球质量=5.9742*10**24
earth.px=-1*AU
earth.vy=29.783*1000
地球。铅笔颜色(“蓝色”)
维纳斯=身体()
venus.name='venus'
金星质量=4.8685*10**24
venus.px=0.723*AU
venus.vy=-35.02*1000
维纳斯。铅笔颜色(“橙色”)
环([太阳、地球、金星])
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

我为我的窗口添加了一行
import-turtle
,因为我想将窗口颜色更改为黑色。我知道这两种进口风格之间的主要区别,以及为什么有些人喜欢其中一种而不是另一种(或者为什么其中一种不好)。我想改变类的结构,这样我就可以对模拟的图形有更多的控制权,同时也可以远离
from x import*
方法。欢迎任何意见

我的选择是使用导入:

from turtle import Screen, Turtle
通过阻塞功能接口来强制面向对象接口。但我会更进一步:

    fx, fy = force[body]
    body.vx += fx / body.mass * timestep
    body.vy += fy / body.mass * timestep

    # Update positions
    body.px += body.vx * timestep
    body.py += body.vy * timestep
海龟可以使用向量(
Vec2D
),所以我们不需要对x和y值进行单独的操作

for body in bodies:
    body.penup()
    body.hideturtle()
这可以是
主体
类初始值设定项的一部分

body.goto(body.px*Scale, body.py*Scale)
我们可以预先缩放海龟的坐标系,避免在主循环中进行缩放操作

while True:
不是在像turtle这样的事件驱动世界中——而是使用
ontimer()
。以下返工实现了上述建议,以说明如何解决此问题:

# Import math and turtle
import math
from turtle import Screen, Turtle, Vec2D

# Gravitational Constant
G = 6.67428e-11
# Scale: 1 pixel = 1 astronomical unit
# 1 astronomical unit = 1 AU = 149597900 km
AU = 149.6e6 * 1000  # 149.6 million km in meters
TIME_STEP = 24 * 3600  # One day
FORMAT = "{:<8} Pos.={:>6.2f} Vel.={:>10.3f}"

CURSOR_SIZE = 20

class Body(Turtle):
    ''' Subclass of turtle representing a body. '''

    # Additional attributes:
    # mass in kg
    # velocity in m/sc
    # position in m

    name = 'body'
    mass = None
    velocity = Vec2D(0.0, 0.0)
    Position = Vec2D(0.0, 0.0)  # Position to avoid conflict with turtle's position() method

    def __init__(self, dot_size=5):
        super().__init__(shape='circle')

        self.shapesize(dot_size / CURSOR_SIZE)

        self.penup()

    def attraction(self, other):
        ''' Return the force exerted on this body by the other body. '''

        # Report an error if the other object is the same as this one.
        if self is other:
            raise ValueError("Attraction of object {} to itself requested".format(self.name))

        # Compute the distance of the other body:
        dx, dy = other.Position - self.Position
        distance = math.sqrt(dx**2 + dy**2)

        # Report an Error if the distance is 0
        # ZeroDivisionError would happen later otherwise
        if distance == 0:
            raise ValueError("Collision between objects {} and {}".format(self.name, other.name))

        # Compute the force of attraction
        force = G * self.mass * other.mass / distance**2

        # Compute the direction of the force
        theta = math.atan2(dy, dx)
        direction = Vec2D(math.cos(theta), math.sin(theta))

        return direction * force

def updateInfo(step: int, bodies: list):
    ''' Display information about status of simulation. '''

    print('Step #{}'.format(step))

    for body in bodies:
        print(FORMAT.format(body.name, abs(body.Position * (1 / AU)), abs(body.velocity)))

    print()

def single_step(bodies, step=1):
    ''' Step through the simulation and updates the positions of given bodies. '''

    updateInfo(step, bodies)

    for body in bodies:
        # Adds all the forces exerted on a body
        totalForce = Vec2D(0.0, 0.0)

        for other in bodies:
            # Don't calculate attraction to itself
            if body is not other:
                totalForce += body.attraction(other)

        # Update velocities based on the force.
        body.velocity += totalForce * (1 / body.mass) * TIME_STEP

        # Update position
        body.Position += body.velocity * TIME_STEP
        body.setposition(body.Position)

    screen.update()
    screen.ontimer(lambda: single_step(bodies, step + 1))

if __name__ == '__main__':
    screen = Screen()
    screen.bgcolor('black')
    screen.setworldcoordinates(-2 * AU, -2 * AU, 2 * AU, 2 * AU)
    screen.tracer(False)

    sun = Body(10)
    sun.name = 'Sun'
    sun.mass = 1.98892 * 10**30
    sun.color('yellow')

    earth = Body()
    earth.name = 'Earth'
    earth.mass = 5.9742 * 10**24
    earth.Position = Vec2D(-AU, 0.0)
    earth.velocity = Vec2D(0.0, 29.783 * 1000)
    earth.color('blue')

    venus = Body()
    venus.name = 'Venus'
    venus.mass = 4.8685 * 10**24
    venus.Position = Vec2D(0.723 * AU, 0.0)
    venus.velocity = Vec2D(0.0, -35.02 * 1000)
    venus.color('orange')

    single_step([sun, earth, venus])

    screen.mainloop()
#导入数学和乌龟
输入数学
从turtle导入屏幕,turtle,Vec2D
#引力常数
G=6.67428e-11
#比例:1像素=1天文单位
#1天文单位=1 AU=149597900公里
AU=149.6e6*1000#14960万公里(米)
时间步长=24*3600#一天
FORMAT=“{:6.2f}级别={:>10.3f}”
光标大小=20
团体(海龟):
“代表身体的海龟的亚类”
#其他属性:
#质量(kg)
#速度单位:m/sc
#以m表示的位置
名称='body'
质量=无
速度=Vec2D(0.0,0.0)
Position=Vec2D(0.0,0.0)#避免与海龟Position()方法冲突的位置
定义初始值(自身,点大小=5):
超级()
self.shapesize(点大小/光标大小)
self.penup()
def吸引力(自身、其他):
“返回另一个物体施加在这个物体上的力”
#如果另一个对象与此对象相同,则报告错误。
如果self是他者:
提高价值错误(“obje的吸引力