调用pygame库绘图,通过万有引力公式、矢量运算等等,实现模拟天体,不模拟碰撞。数据有点随便,模拟出来效果并不好。

import pygame, sys, random, math, time
pygame.init()
size = width, height = 1440, 900
screen = pygame.display.set_mode(size)
pygame.display.set_caption('天体模拟')
starArr = []
G = 0.009
dt = 0.8
T = time.time()

class star:
  def __init__(self, id, sx, sy, m, vx = 0, vy = 0, color = (255, 255, 255)):
    self.id, self.m, self.sx, self.sy, self.p, self.color = id, m, sx, sy, [], color
    self.vx, self.vy = vx, vy
    self.r = math.ceil(m**0.40)
    if self.r < 2:
      self.r = 2
    if self.r > 14:
      self.r = 14

# m 100~600
starArr.append(star(id = 0, sx = 720, sy = 450, m = 10000, color = (250,20,60)))  # 太阳

starArr.append(star(id = 1, sx = 720, sy = 225, vx = -(G*10000/225)**0.5, m = 50, color = (65,105,225)))  # 地球
starArr.append(star(id = 2, sx = 720, sy = 220, vx = -(G*10)**0.5, vy = 0.1, m = 5, color = (210, 220, 230)))  # 月球

starArr.append(star(id = 3, sx = 720, sy = 112, vx = -(G*10000/338)**0.5, vy = 0.1, m = 100, color = (205,133,63)))  # 木星
starArr.append(star(id = 6, sx = 710, sy = 109, vx = -(G*100/2.24)**0.5, vy = 0.09, m = 1, color = (255,218,185)))  # 木卫1
starArr.append(star(id = 7, sx = 730, sy = 119, vx = -(G*100/2.24)**0.5, vy = -0.009, m = 1, color = (255,215,0)))  # 木卫2
starArr.append(star(id = 8, sx = 717, sy = 104, vx = -(G*100/2.24)**0.5, m = 1, color = (0,206,209)))  # 木卫3

starArr.append(star(id = 4, sx = 720, sy = 562, vx = -(G*10000/112)**0.5, m = 7, color = (100,149,237)))  # 水星

starArr.append(star(id = 5, sx = 720, sy = 750, vx = (G*10000/300)**0.5, m = 48, color = (225,69,0)))  # 火星

def drawStar():
  for star in starArr:
    pygame.draw.circle(
      screen,
      star.color,
      (star.sx, star.sy),
      star.r,
      0
    )

def main():
  screen.fill((0, 0, 0))
  # 随机流星
  global T
  if time.time() - T > 1 and len(starArr) < 30:
    tmp_v = random.random() + 0.5
    starArr.append(
      star(
        id = len(starArr),
        sx = width - random.randint(0, 20),
        sy = random.randint(0, 20),
        m = 2,
        vx = -tmp_v + (random.random() * 0.15),
        vy = tmp_v + (random.random() * 0.15)
      )
    )
    T = time.time()
  for starA in starArr:
    fx, fy = 0, 0
    for starB in starArr:
      if starA.id == starB.id:
        continue
      # startA为自身  下面计算AB距离l 和单位向量 u
      Dx, Dy = starB.sx - starA.sx, starB.sy - starA.sy
      l = ( (Dx)**2 + (Dy)**2 ) ** 0.5
      limitR = starA.r + starB.r
      if l < limitR:
        l = limitR
      u = Dx / l, Dy / l
      F = G * starA.m * starB.m / (l**2)  # 万有引力公式
      u = u[0]*F, u[1]*F  # F合 = u*F
      fx += u[0]
      fy += u[1]
    # 合力累加完毕
    ax = fx / starA.m
    ay = fy / starA.m
    starA.vx += ax * dt
    starA.vy += ay * dt
    starA.sx += starA.vx * dt
    starA.sy += starA.vy * dt
    if abs(starA.sx) > width + starA.r or abs(starA.sy) > height + starA.r:
      starArr.remove(starA)
  drawStar()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    main()
    pygame.display.update()
    time.sleep(0.001)
pygame.quit()  # 退出pygame