提交 cf015430 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 8e3df1c6
...@@ -10,98 +10,19 @@ from bodies import Moon, Earth, Body ...@@ -10,98 +10,19 @@ from bodies import Moon, Earth, Body
from objs import Satellite, Satellite2 from objs import Satellite, Satellite2
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH
from sim_scenes.func import mayavi_run, ursina_run, camera_look_at from sim_scenes.func import mayavi_run, ursina_run, camera_look_at
import math
import random
# def calculate_satellite_velocity(earth: Earth, altitude):
# """
#
# @param earth_raduis:
# @param altitude:
# @return:
# """
# # 地球引力常数
# G = 6.67430e-11
# # 地球质量
# M = earth.mass # 5.97e24
# # 地球半径
# R = earth.raduis + altitude
# # 地球表面的线速度
# v_surface = math.sqrt(G * M / R)
# # 地球卫星轨道速度
# v_satellite = math.sqrt(G * M / (R + altitude))
# return v_satellite - v_surface
import random
import random
import math
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_event import UrsinaEvent
# def get_satellite_position_velocity(earth_mass, earth_position, earth_radius, altitude):
# # 万有引力常数
# G = 6.6743 * 10 ** (-11)
# # 地球质量
# M = earth_mass
# # 地球半径+海拔高度
# R = earth_radius + altitude
#
# # 随机生成卫星的位置,确保在球面上
# phi = random.uniform(0, 2 * math.pi)
# costheta = random.uniform(-1, 1)
# u = random.uniform(0, 1)
#
# theta = math.acos(costheta)
# r = R * (u ** (1 / 3))
#
# x = r * math.sin(theta) * math.cos(phi)
# y = r * math.sin(theta) * math.sin(phi)
# z = r * math.cos(theta)
#
# # 计算速度的方向
# # 位置矢量
# r_vec = [x, y, z]
# # 速度方向和位置矢量垂直,采用向量叉积的性质
# v_dir = [-y, x, 0]
# # 归一化
# v_dir_norm = [v / math.sqrt(x ** 2 + y ** 2) for v in v_dir]
#
# # 计算速度大小
# v = math.sqrt(G * M / R)
#
# # 计算速度矢量
# v_vec = [v * dir for dir in v_dir_norm]
#
# # 计算卫星的位置和速度
# position = [earth_position[0] + x, earth_position[1] + y, earth_position[2] + z]
# velocity = v_vec
#
# return tuple(position), [0, 0, 0]
#
#
# def generate_satellite_coordinates(earth_radius, altitude):
# theta = random.uniform(0, 2 * math.pi) # 在0~2π内随机生成一个角度
# phi = random.uniform(0, math.pi) # 在0~π内随机生成一个角度
# r = earth_radius + altitude # 地球半径+海拔高度
# x = r * math.sin(phi) * math.cos(theta) # 计算x坐标
# y = r * math.sin(phi) * math.sin(theta) # 计算y坐标
# z = r * math.cos(phi) # 计算z坐标
#
# return [x, y, z]
if __name__ == '__main__': if __name__ == '__main__':
""" """
地球、6个月球 地球和卫星模拟
""" """
# 地球在中心位置 # 地球在中心位置
earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0]) earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0])
# 北斗卫星高度为2.13-2.15万千米。GPS卫星平均轨道高度2.02万千米。
bodies = [earth] bodies = [earth]
# 卫星位置和初始速度信息
satellite_infos = [ satellite_infos = [
{"position": [0, 0, 10002], "velocity": [6.3, 0, 0]}, {"position": [0, 0, 10002], "velocity": [6.3, 0, 0]},
{"position": [0, 0, -12000], "velocity": [5.75, 0, 0]}, {"position": [0, 0, -12000], "velocity": [5.75, 0, 0]},
...@@ -111,9 +32,6 @@ if __name__ == '__main__': ...@@ -111,9 +32,6 @@ if __name__ == '__main__':
{"position": [0, 0, -10000], "velocity": [0, 6.3, 0]}, {"position": [0, 0, -10000], "velocity": [0, 6.3, 0]},
] ]
for i, info in enumerate(satellite_infos): for i, info in enumerate(satellite_infos):
# altitude = random.randint(4000, 10000)
# position, velocity = get_satellite_position_velocity(earth.mass, earth.init_position, earth.raduis, altitude)
satellite = Satellite(name=f'卫星{i + 1}', mass=4.4e10, size_scale=2e2, color=(255, 200, 0), satellite = Satellite(name=f'卫星{i + 1}', mass=4.4e10, size_scale=2e2, color=(255, 200, 0),
init_position=info["position"], init_position=info["position"],
init_velocity=info["velocity"]) init_velocity=info["velocity"])
...@@ -127,6 +45,7 @@ if __name__ == '__main__': ...@@ -127,6 +45,7 @@ if __name__ == '__main__':
UrsinaConfig.trail_type = "line" UrsinaConfig.trail_type = "line"
pass pass
def on_timer_changed(time_data: TimeData): def on_timer_changed(time_data: TimeData):
for info in satellite_infos: for info in satellite_infos:
info["satellite"].planet.look_at(earth.planet) info["satellite"].planet.look_at(earth.planet)
......
...@@ -6,13 +6,10 @@ ...@@ -6,13 +6,10 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Moon, Earth, Body from bodies import Earth, Body
from objs import RockSnow, Rock, create_rock from objs import RockSnow, Rock, create_rock
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY
from sim_scenes.func import mayavi_run, ursina_run, camera_look_at, two_bodies_colliding from sim_scenes.func import ursina_run, camera_look_at, two_bodies_colliding
import math
import random
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_event import UrsinaEvent
...@@ -22,18 +19,20 @@ if __name__ == '__main__': ...@@ -22,18 +19,20 @@ if __name__ == '__main__':
岩石坠落地球 岩石坠落地球
""" """
# 地球在中心位置 # 地球在中心位置
earth = Earth(init_position=[0, 0, 0], size_scale=1, texture="earth_hd.jpg", init_velocity=[0, 0, 0]) earth = Earth(init_position=[0, 0, 0], init_velocity=[0, 0, 0],
rotation_speed=0, size_scale=1, texture="earth_hd.jpg")
bodies = [earth] bodies = [earth]
# 岩石位置和初始速度信息
infos = [ infos = [
{"position": [0, 0, 10002], "velocity": [2.3, 0, 0]}, {"position": [0, 0, 10002], "velocity": [4.5, 0, 0]},
{"position": [0, 0, -12000], "velocity": [1.75, 0, 0]}, {"position": [0, 0, -12000], "velocity": [3.5, 0, 0]},
{"position": [0, 8000, 0], "velocity": [1.05, 0, 0]}, {"position": [0, 8000, 0], "velocity": [4.5, 0, 0]},
{"position": [0, -12002, 0], "velocity": [1.75, 0, 0]}, {"position": [0, -12002, 0], "velocity": [3.5, 0, 0]},
{"position": [0, 18000, 0], "velocity": [1.05, 0, 0]}, {"position": [0, 18000, 0], "velocity": [3.0, 0, 0]},
{"position": [0, -22002, 0], "velocity": [1.75, 0, 0]}, {"position": [-20000, 0, 0], "velocity": [0, -2.0, 0]},
{"position": [0, 0, 8002], "velocity": [0, 1.05, 0]}, {"position": [0, 0, 18002], "velocity": [0, 2.5, 0]},
{"position": [0, 0, -10000], "velocity": [0, 1.3, 0]}, {"position": [0, 0, -10000], "velocity": [0, 3.3, 0]},
] ]
for i, info in enumerate(infos): for i, info in enumerate(infos):
rock = create_rock(no=i % 7 + 1, name=f'岩石{i + 1}', mass=4.4e10, size_scale=5e2, color=(255, 200, 0), rock = create_rock(no=i % 7 + 1, name=f'岩石{i + 1}', mass=4.4e10, size_scale=5e2, color=(255, 200, 0),
......
...@@ -59,17 +59,29 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK, ...@@ -59,17 +59,29 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
mlab.show() mlab.show()
def camera_look_at(body, rotation_x=None, rotation_y=None, rotation_z=None): def set_camera_parent(target):
from ursina import camera
if hasattr(target, "planet"):
camera.parent = target.planet.main_entity
else:
camera.parent = target
def camera_look_at(target, rotation_x=None, rotation_y=None, rotation_z=None):
""" """
让摄像机看向指定天体 让摄像机看向指定天体
@param body: 天体 @param target: 天体
@param rotation_x: x轴旋转角度(None表示不旋转) @param rotation_x: x轴旋转角度(None表示不旋转)
@param rotation_y: y轴旋转角度(None表示不旋转) @param rotation_y: y轴旋转角度(None表示不旋转)
@param rotation_z: z轴旋转角度(None表示不旋转) @param rotation_z: z轴旋转角度(None表示不旋转)
@return: @return:
""" """
from ursina import camera from ursina import camera
camera.look_at(body.planet) if hasattr(target, "planet"):
camera.look_at(target.planet.main_entity)
else:
camera.look_at(target)
if rotation_x is not None: if rotation_x is not None:
camera.rotation_x = rotation_x camera.rotation_x = rotation_x
if rotation_y is not None: if rotation_y is not None:
...@@ -199,7 +211,7 @@ def create_solar_system_bodies(ignore_mass=False, init_velocity=None): ...@@ -199,7 +211,7 @@ def create_solar_system_bodies(ignore_mass=False, init_velocity=None):
Jupiter(name="木星", size_scale=0.3e3), # 木星放大 300 倍,距离保持不变 Jupiter(name="木星", size_scale=0.3e3), # 木星放大 300 倍,距离保持不变
Saturn(name="土星", size_scale=0.3e3), # 土星放大 300 倍,距离保持不变 Saturn(name="土星", size_scale=0.3e3), # 土星放大 300 倍,距离保持不变
Uranus(name="天王星", size_scale=0.4e3), # 天王星放大 400 倍,距离保持不变 Uranus(name="天王星", size_scale=0.4e3), # 天王星放大 400 倍,距离保持不变
Neptune(name="海王星", size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 Neptune(name="海王星", size_scale=1e3), # 海王星放大 800 倍,距离保持不变
Pluto(name="冥王星", size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) Pluto(name="冥王星", size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除)
] ]
......
...@@ -43,8 +43,8 @@ class SpeedOfLightInit: ...@@ -43,8 +43,8 @@ class SpeedOfLightInit:
self.camera_position = (AU / 5, 0, 0) self.camera_position = (AU / 5, 0, 0)
self.show_trail = True self.show_trail = True
self.light_size_scale = 2e6 self.light_size_scale = 2e6
self.light_init_position = [AU, 0, 0] self.light_init_position = [AU, AU / 20, 0]
self.auto_control_speed = True # self.auto_control_speed = True
elif self.__camera_follow_light in ["SideViewActualSize"]: elif self.__camera_follow_light in ["SideViewActualSize"]:
# 摄像机位置 = 前-后+、上+下-、左-右+、 # 摄像机位置 = 前-后+、上+下-、左-右+、
# self.camera_position = (0, AU, 0) # self.camera_position = (0, AU, 0)
...@@ -58,8 +58,8 @@ class SpeedOfLightInit: ...@@ -58,8 +58,8 @@ class SpeedOfLightInit:
self.camera_position = (0, -AU / 25, -AU / 50) self.camera_position = (0, -AU / 25, -AU / 50)
self.show_trail = True self.show_trail = True
self.light_size_scale = 2e6 self.light_size_scale = 2e6
self.light_init_position = [AU / 12, 0, 0] self.light_init_position = [AU / 8, AU / 10, 0]
# self.auto_control_speed = True self.auto_control_speed = True
else: else:
# 摄像机位置 = 左-右+、上+下-、前+后- # 摄像机位置 = 左-右+、上+下-、前+后-
self.camera_position = (0, AU, -6 * AU) self.camera_position = (0, AU, -6 * AU)
...@@ -155,7 +155,7 @@ class SpeedOfLightInit: ...@@ -155,7 +155,7 @@ class SpeedOfLightInit:
camera.rotation_z = -90 camera.rotation_z = -90
camera.rotation_y = -85 camera.rotation_y = -85
elif self.__camera_follow_light in ["ForwardView"]: elif self.__camera_follow_light in ["ForwardView"]:
camera.rotation_x = -75 camera.rotation_x = -72
elif self.__camera_follow_light in ["SideViewActualSize"]: elif self.__camera_follow_light in ["SideViewActualSize"]:
self.light_ship.planet.rotation_x = 0 self.light_ship.planet.rotation_x = 0
# camera.rotation_z = -90 # camera.rotation_z = -90
...@@ -196,22 +196,22 @@ class SpeedOfLightInit: ...@@ -196,22 +196,22 @@ class SpeedOfLightInit:
run_speed_maps = [ run_speed_maps = [
{"au": 0., "secs": 1}, {"au": 0., "secs": 1},
{"au": 0.008, "secs": 1}, {"au": 0.008, "secs": 1},
{"au": "?", "secs": SECONDS_PER_MINUTE * 10}, {"au": "?", "secs": SECONDS_PER_MINUTE * 5},
{"au": 0.386, "secs": 1}, {"au": 0.386, "secs": 1},
{"au": 0.3865, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU {"au": 0.3865, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 10}, {"au": "?", "secs": SECONDS_PER_MINUTE * 5},
{"au": 0.721, "secs": 1}, {"au": 0.721, "secs": 1},
{"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU {"au": 0.724, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 10}, {"au": "?", "secs": SECONDS_PER_MINUTE * 5},
{"au": 1.0, "secs": 1}, {"au": 1.0, "secs": 1},
{"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU {"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 10}, {"au": "?", "secs": SECONDS_PER_MINUTE * 5},
{"au": 1.52, "secs": 1}, {"au": 1.52, "secs": 1},
{"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU {"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 30}, {"au": "?", "secs": SECONDS_PER_MINUTE * 25},
{"au": 5.19, "secs": 1}, {"au": 5.19, "secs": 1},
{"au": 5.20, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU {"au": 5.20, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 30}, {"au": "?", "secs": SECONDS_PER_MINUTE * 25},
{"au": 9.5, "secs": 1}, {"au": 9.5, "secs": 1},
{"au": 9.51, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU {"au": 9.51, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU
{"au": "?", "secs": SECONDS_PER_MINUTE * 30}, {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
......
...@@ -8,15 +8,17 @@ ...@@ -8,15 +8,17 @@
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth from bodies import Sun, Mercury, Venus, Earth
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HOUR, AU from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HOUR, AU
from sim_scenes.func import mayavi_run, ursina_run, camera_look_at from sim_scenes.func import ursina_run, set_camera_parent
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_event import UrsinaEvent
if __name__ == '__main__': if __name__ == '__main__':
# 水星、金星凌日 # 水星、金星凌日
# 以地球的视角看水星、金星凌日
earth = Earth( earth = Earth(
name="地球", name="地球",
rotation_speed=0, rotate_angle=0, # 不倾斜
rotation_speed=0, # 不旋转
texture="transparent.png" # 地球纹理透明,不会挡住摄像机视线 texture="transparent.png" # 地球纹理透明,不会挡住摄像机视线
) )
sun = Sun(name="太阳", size_scale=5e1) # 太阳放大 50 倍 sun = Sun(name="太阳", size_scale=5e1) # 太阳放大 50 倍
...@@ -40,7 +42,7 @@ if __name__ == '__main__': ...@@ -40,7 +42,7 @@ if __name__ == '__main__':
def on_ready(): def on_ready():
from ursina import camera from ursina import camera
# 摄像机跟随地球(模拟在地球上看到的效果) # 摄像机跟随地球(模拟在地球上看到的效果)
camera.parent = earth.planet set_camera_parent(earth)
if hasattr(camera, "sky"): if hasattr(camera, "sky"):
# 摄像机跟随地球后,需要对深空背景进行调整,否则看到的是黑色背景 # 摄像机跟随地球后,需要对深空背景进行调整,否则看到的是黑色背景
...@@ -52,8 +54,7 @@ if __name__ == '__main__': ...@@ -52,8 +54,7 @@ if __name__ == '__main__':
def on_timer_changed(time_data: TimeData): def on_timer_changed(time_data: TimeData):
# 时时刻刻的让地球看向太阳(摄像机跟随地球看向太阳) # 时时刻刻的让地球看向太阳(摄像机跟随地球看向太阳)
earth.planet.look_at(sun.planet) earth.look_at(sun, rotation_z=0)
earth.planet.rotation_z = 0
UrsinaEvent.on_ready_subscription(on_ready) UrsinaEvent.on_ready_subscription(on_ready)
......
...@@ -53,6 +53,7 @@ class UrsinaSimulator(Simulator): ...@@ -53,6 +53,7 @@ class UrsinaSimulator(Simulator):
for i, view in enumerate(self.body_views): for i, view in enumerate(self.body_views):
# pos = tuple(body.position) # pos = tuple(body.position)
# ursina_view = UrsinaView(body) # ursina_view = UrsinaView(body)
self.bind_event(view.body)
view.update() view.update()
self.ursina_views.append(view) self.ursina_views.append(view)
# planets.append(newPlanet) # planets.append(newPlanet)
...@@ -60,6 +61,28 @@ class UrsinaSimulator(Simulator): ...@@ -60,6 +61,28 @@ class UrsinaSimulator(Simulator):
self.adjust_system_motion_params() self.adjust_system_motion_params()
UrsinaEvent.on_searching_bodies_subscription(type(self).__name__, self.on_searching_bodies) UrsinaEvent.on_searching_bodies_subscription(type(self).__name__, self.on_searching_bodies)
def bind_event(self, body):
def body_look_at(target, rotation_x=None, rotation_y=None, rotation_z=None):
"""
让 body 看向 target 目标天体
@param target: 目标天体
@param rotation_x: x轴旋转角度(None表示不旋转)
@param rotation_y: y轴旋转角度(None表示不旋转)
@param rotation_z: z轴旋转角度(None表示不旋转)
@return:
"""
if hasattr(target, "planet") and hasattr(body, "planet"):
body.planet.main_entity.look_at(target.planet.main_entity)
if rotation_x is not None:
body.planet.rotation_x = rotation_x
if rotation_y is not None:
body.planet.rotation_y = rotation_y
if rotation_z is not None:
body.planet.rotation_z = rotation_z
body.look_at = body_look_at
# def get_bodies_max_distance(self, body_views): # def get_bodies_max_distance(self, body_views):
# max_distance = 0 # max_distance = 0
# for b1 in body_views: # for b1 in body_views:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册