2017-01-22 42 views
1

我最近一直在使用这个公式作出轨迹模拟器:Picture of Equation I am usingpygame的轨道模拟问题

这里是我的代码:

import pygame, math 
from pygame.locals import * 
from random import randint 
pygame.init() 
screen = pygame.display.set_mode([500,500]) 
clock = pygame.time.Clock() 

class Planet(): 
    def __init__(self, vel = [1, 1], mass = 100000, pos = [100, 100], pathLength = 100000): 
     self.v = vel 
     self.m = mass 
     self.size = mass/1000000 
     self.pos = pos 
     self.pL = pathLength 
     self.path = [[pos[0], pos[1]]] 

    def update(self): 
     self.pos[0] += self.v[0] 
     self.pos[1] += self.v[1] 
     self.path.append([self.pos[0], self.pos[1]]) 
     if len(self.path) == self.pL: 
      self.path.pop(0) 

class World(): 
    def __init__(self, planetList, iterations, mass = 10000000, gravityConstant = (6 * 10 ** -9)): 
     self.plnt = planetList 
     self.iter = iterations 
     self.mass = mass 
     self.size = int(mass/1000000) 
     self.gC = gravityConstant 
    def draw(self): 
     pygame.draw.circle(screen, [0, 0, 0], [250, 250], self.size) 
     for p in self.plnt: 
      pygame.draw.rect(screen, [0, 0, 0], [p.pos[0], p.pos[1], p.size, p.size]) 
      pygame.draw.lines(screen, [0, 0, 0], False, p.path) 
    def update(self): 
     for i in range(self.iter): 
      for p in self.plnt: 
       d = math.sqrt((p.pos[0] - 250) ** 2 + (p.pos[1] - 250) ** 2) 
       f = (self.gC * self.mass * p.m)/(d ** 2) 
       vect = [((250 - p.pos[0])/d) * f, ((250 - p.pos[1])/d) * f] 
       p.v[0] += vect[0] 
       p.v[1] += vect[1] 
       p.update() 
     self.draw() 


a = Planet([4,0]) 
b = Planet([4, 0]) 
w = World([b], 100) 
while 1: 
    screen.fill([255, 255, 255]) 

    w.update() 

    for event in pygame.event.get(): 
     if event.type == QUIT: 
      pygame.quit() 

    pygame.display.update() 
    clock.tick(60) 

,如果我只是在它按预期工作模拟1个星球,但与此有问题

a = Planet([4,0]) 
b = Planet([4, 0]) 
w = World([a, b], 100) 

行星飞了出去,屏幕和永远继续下去,我不能看到我犯了一个错误。

+0

与您的特定问题无关您的实施并不完全是如何引力的作品。你有一个中心“世界”对“行星”施加重力,而不受自身的影响。而你的“行星”根本不会互相影响。实际上,所有物体都以成对的方式彼此施加重力,并且如果A在B上施加力F,则从A施加在B上的力是-F。所以技术上你需要一个嵌套循环并计算所有成对关系一次(如上所述,相反的方向是多余的)。确保正确选择符号,因为方程式不提供它们。 –

+0

@MartinKrämer是的,这是我想要实现这一点的方法,但是如果在中央机构和其他机构之间施加力量,我可以轻易改变。 – adammoyle

+0

[尝试使用IDE](http://sopython.com/wiki/Python_IDEs)。它将帮助你在编写更好的代码和学习编程方面都有极大的帮助。我个人使用PyCharm,它会通知您默认的可变参数,但其他IDE可能具有类似的功能。 –

回答

2

你是因为声明可变默认参数的古老Python陷阱而倒下的。 :)

要切入正题,所以你可以得到你的代码的工作,拷贝我下面制作成自己的代码替换的:

class Planet(): 
    def __init__(self, vel = [1, 1], mass = 100000, pos = [100, 100], pathLength = 100000): 
     self.v = vel[:] # Added [:] to ensure the list is copied 
     self.m = mass 
     self.size = mass/1000000 
     self.pos = pos[:] # Added [:] here for the same reason 
     self.pL = pathLength 
     self.path = [[pos[0], pos[1]]] 

说明

在Python中,列表是可变 - 您可以修改列表的同一个实例。人们在使用Python时犯的一个常见错误是将可变参数声明为函数签名中的默认值。

的问题是,Python将在该函数定义被处理的时间分配该默认值一旦到参数,然后重用,每个函数被调用时,并呼吁默认参数分配值。

在你Planet类的构造函数,你就声明了两个可变默认参数:

  • vel = [1, 1]
  • pos = [100, 100]

的创建将存储这些列表的引用Planet每个实例,但请注意,因为我上面所说的,每个星球都会分享相同的 vel清单和相同pos清单。这意味着每个实例都会干扰其他人的速度和位置数据。

你可以阅读更多关于这个gotcha here

的替代和这样的处理情况最佳的办法是设置默认值None,然后分配“真正的”默认值,如果调用者不为它提供一个明确的价值:

class Planet(): 
    def __init__(self, vel = None, mass = 100000, pos = None, pathLength = 100000): 
     self.v = vel or [1, 1] 
     self.m = mass 
     self.size = mass/1000000 
     self.pos = pos or [100, 100] 
     self.pL = pathLength 
     self.path = [[self.pos[0], self.pos[1]]] 

然后你会被要求记录函数的这种行为,因为否则调用者不会看到它。