2017-01-22 80 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]]] 

然後你會被要求記錄函數的這種行爲,因爲否則調用者不會看到它。