import pygame
import sys
import math
import numpy as np
import random
G = 0.3
class Star:
def __init__(self, star_id, radius, mass):
self.star_id = star_id
self.radius = radius
self.mass = mass
self.position = [random.randrange(width), random.randrange(height)] # 随机初始化位置
self.speed = [int(random.choice([1, -1]) * 6 * np.random.rand(1)), int(random.choice([1, -1]) * 6 * np.random.rand(1))] # 随机初始化速度
def move(self):
self.position[0] += self.speed[0]
self.position[1] += self.speed[1]
# 跑出窗口从另一边回来
self.position[0] -= self.position[0] // width * width
self.position[1] -= self.position[1] // height * height
pygame.draw.circle(screen, (255, 255, 255), self.position, self.radius)
if __name__ == '__main__':
pygame.init()
size = width, height = 1920, 1020
bg = (0, 0, 0)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("天体运动")
stars = [Star(star_id, random.randrange(3, 8), random.randrange(100, 200)) for star_id in range(10)] # 随机生成天体
clock = pygame.time.Clock()
step = 1
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(0)
screen.fill((0, 0, 0))
for i in range(len(stars)):
star = stars[i]
for star2 in stars[(i + 1):]:
distance = math.dist(star.position, star2.position)
if distance < 100:
distance = 100
# 万有引力公式F=GMm/r**2,0.1是为了适当缩小万有引力,否则会出现天体一直在转圈,你可以自己调整数值
f = (G * (star.mass * star2.mass)) / distance ** 2 * 0.1
relative_position = np.subtract(star.position, star2.position)
angle = math.atan2(*relative_position[::-1])
dx = math.cos(angle) * f
dy = math.sin(angle) * f
star.speed = np.subtract(star.speed, [dx, dy])
star2.speed = np.add(star2.speed, [dx, dy])
star.speed = [x - math.copysign(0.001, x) for x in star.speed] # 虽然天体是在做匀速直线运动,但不做衰减的话速度会一直叠加导致过快
star.move()
pygame.display.flip()
初中生,不懂天体运动,找了个github项目作参考
https://github.com/zkytech/Simulation-of-Star-Motion
这个项目是在网页上模拟的,我移植到pygame来,并改了一些重要的地方
有什么bug或者疑惑的请告诉我 |