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

Python超人-宇宙模拟器

上级 09cb9f75
...@@ -16,6 +16,7 @@ from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MON ...@@ -16,6 +16,7 @@ from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MON
from sim_scenes.func import ursina_run, camera_look_at, create_text_panel, create_sphere_sky from sim_scenes.func import ursina_run, camera_look_at, create_text_panel, create_sphere_sky
from sim_scenes.universe_sim_scenes import UniverseSimScenes from sim_scenes.universe_sim_scenes import UniverseSimScenes
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.entities.circle_line import CircleLine
from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.entities.entity_utils import create_directional_light
from simulators.ursina.ui.control_ui import ControlUI from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
...@@ -73,6 +74,8 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -73,6 +74,8 @@ class SunEarthMoonSim(UniverseSimScenes):
if len(self.bodies) == 4: if len(self.bodies) == 4:
self.bodies = self.bodies[0:3] self.bodies = self.bodies[0:3]
# self.create_circle(time_data)
def on_timer_changed(self, time_data): def on_timer_changed(self, time_data):
""" """
...@@ -161,8 +164,9 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -161,8 +164,9 @@ class SunEarthMoonSim(UniverseSimScenes):
self.create_orbit_line(self.sun, self.earth, self.start_time, alpha=1) self.create_orbit_line(self.sun, self.earth, self.start_time, alpha=1)
# self.create_orbit_line(self.sun, self.moon, self.start_time, alpha=0.5) # self.create_orbit_line(self.sun, self.moon, self.start_time, alpha=0.5)
orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1) # TODO: 月球轨道
orbit_line.rotation_x = 40 moon_orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1)
moon_orbit_line.rotation_x = 40
# for body in self.bodies[1:]: # for body in self.bodies[1:]:
# if isinstance(body, Earth): # if isinstance(body, Earth):
...@@ -173,6 +177,32 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -173,6 +177,32 @@ class SunEarthMoonSim(UniverseSimScenes):
# if orbit_line is not None: # if orbit_line is not None:
# self.orbit_lines.append(orbit_line) # self.orbit_lines.append(orbit_line)
def create_circle(self, time_data):
from ursina import Vec3
month = int(time_data.total_days / 29.5+0.5)
if month == 0:
return
month_name = "month_" + str(month)
if hasattr(self, month_name):
return
setattr(self, month_name, True)
print(month_name)
pos = self.earth.position
pos = Vec3(pos[0] * UrsinaConfig.SCALE_FACTOR,
pos[2] * UrsinaConfig.SCALE_FACTOR,
pos[1] * UrsinaConfig.SCALE_FACTOR)
# pos = Vec3(pos[0],pos[2],pos[1])
# pos = Vec3(pos[1], pos[2], pos[0])
# pos = Vec3(pos[2], pos[1], pos[0])
# pos = Vec3(pos[2], pos[0], pos[1])
# pos = Vec3(pos[1], pos[0], pos[2])
pos = pos / 2
circle_line = CircleLine(position=pos, radius=18.7, segments=30,
thickness=1, # color=self.moon.trail_color,
alpha=1)
circle_line.rotation_x = 65
circle_line.set_light_off(True)
def init_settings(self): def init_settings(self):
""" """
初始化设置 初始化设置
...@@ -180,10 +210,11 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -180,10 +210,11 @@ class SunEarthMoonSim(UniverseSimScenes):
""" """
from ursina import color from ursina import color
# 创建天空 # 创建天空
create_sphere_sky(scale=5000) # create_sphere_sky(scale=5000)
# UrsinaConfig.trail_type = "curve_line" # UrsinaConfig.trail_type = "curve_line"
UrsinaConfig.trail_type = "line" UrsinaConfig.trail_type = "line"
UrsinaConfig.trail_length = 860 UrsinaConfig.trail_length = 860
UrsinaConfig.trail_length = 40
UrsinaConfig.trail_thickness_factor = 2 UrsinaConfig.trail_thickness_factor = 2
UrsinaConfig.run_speed_factor = 20 UrsinaConfig.run_speed_factor = 20
...@@ -230,7 +261,7 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -230,7 +261,7 @@ class SunEarthMoonSim(UniverseSimScenes):
# font_scale=2, # font_scale=2,
# font_color=(0, 255, 0), # font_color=(0, 255, 0),
# close_time=-1) # close_time=-1)
if hasattr(self, "text_panel"):
self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \ self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \
"天数:" + str(round(total_days, 2)) + "\n\n" + \ "天数:" + str(round(total_days, 2)) + "\n\n" + \
"月数:" + str(round(total_days / 29.5, 2)) "月数:" + str(round(total_days / 29.5, 2))
...@@ -269,7 +300,8 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -269,7 +300,8 @@ class SunEarthMoonSim(UniverseSimScenes):
self.create_orbit_lines() self.create_orbit_lines()
# 创建信息显示面板 # 创建信息显示面板
# self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5) # self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5)
self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3)
# self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3)
def run(self, start_time='2023-01-01 00:00:00'): def run(self, start_time='2023-01-01 00:00:00'):
self.build_bodies() self.build_bodies()
...@@ -289,7 +321,7 @@ class SunEarthMoonSim(UniverseSimScenes): ...@@ -289,7 +321,7 @@ class SunEarthMoonSim(UniverseSimScenes):
ursina_run(self.bodies, ursina_run(self.bodies,
SECONDS_PER_DAY / 24, SECONDS_PER_DAY / 24,
# position=(0, 3.5 * AU, -AU), # 顶上 # position=(0, 3.5 * AU, -AU), # 顶上
position=(0, 1 * AU, -3.5*AU), position=(0, 1 * AU, -3.5 * AU),
gravity_works=False, gravity_works=False,
cosmic_bg='', cosmic_bg='',
show_trail=True, show_trail=True,
......
# -*- coding:utf-8 -*-
# title :太阳地球月球场景模拟
# description :太阳地球月球场景模拟(月球始终一面朝向地球、月球对地球的扰动)
# author :Python超人
# date :2024-03-14
# link :https://gitcode.net/pythoncr/
# python_version :3.9
# ==============================================================================
from bodies import Sun, Earth, Moon
from common.celestial_data_service import init_bodies_reality_pos_vels, set_solar_system_celestial_position, \
get_reality_orbit_points
from objs import CoreValagaClas, SciFiBomber, WaterDrop
from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH
from sim_scenes.func import ursina_run, camera_look_at, create_text_panel, create_sphere_sky
from sim_scenes.universe_sim_scenes import UniverseSimScenes
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.entities.circle_line import CircleLine
from simulators.ursina.entities.entity_utils import create_directional_light
from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ursina_mesh import create_orbit_by_points, create_circle_line
class SunEarthMoonSim(UniverseSimScenes):
def __init__(self):
self.sun = None
self.moon = None
self.earth = None
self.earth_start = None
self.bodies = None
self.orbit_lines = []
self.run_finished = False
# 地球自转一圈是23小时56分4秒,公转一圈是365天6小时9分9秒 365.25
self.earth_revolution_days = 365.25 + (9 * 60 + 9) / 60 / 60 / 24
def build_bodies(self):
# region 构建太阳系
self.sun = Sun(size_scale=6e1, texture="sun_light.jpg")
self.moon = Moon(size_scale=22e2)
self.earth = Earth(size_scale=10e2, show_trail=False)
self.earth_start = Earth(size_scale=9.5e2, show_trail=False, rotation_speed=0)
self.camera_look = CoreValagaClas(name="摄像机镜头", mass=1e30, color=(111, 140, 255),
init_position=[0, 0, 0],
# init_position=[0, 3.3 * AU, -AU],
init_velocity=[0, 0, 0],
size_scale=1e4).set_ignore_gravity(True)
self.camera_target = CoreValagaClas(name="摄像机目的", mass=1e30, color=(111, 140, 255),
# init_position=[0, 0, 0],
init_position=[0, 3.3 * AU, -AU],
init_velocity=[0, 0, 0],
size_scale=1e4).set_ignore_gravity(True)
self.bodies = [self.sun, self.earth, self.moon, self.earth_start,
# self.camera_look,
# self.camera_target
]
for body in self.bodies:
body.init_velocity = [0, 0, 0]
def set_bodies_position(self, time_data: TimeData):
"""
设置天体的位置(包含速度和加速度的信息)
@param time_data:
@return:
"""
t = self.start_time + time_data.total_days
set_solar_system_celestial_position(self.bodies, t, True)
if len(self.bodies) == 4:
self.bodies = self.bodies[0:3]
self.create_circle(time_data)
def on_timer_changed(self, time_data):
"""
@param time_data:
@return:
"""
if self.run_finished:
# self.earth.planet.rotation_y = self.earth.planet.last_rotation_y
# self.moon.planet.rotation_y = self.moon.planet.last_rotation_y
# self.sun.planet.rotation_y = self.sun.planet.last_rotation_y
return
from ursina import distance
if time_data.total_days >= self.earth_revolution_days:
self.run_finished = True
# self.earth.planet.rotation_speed = 0
# self.moon.planet.rotation_speed = 0
# self.sun.planet.rotation_speed = 0
#
# self.earth.planet.last_rotation_y = self.earth.planet.rotation_y
# self.moon.planet.last_rotation_y = self.moon.planet.rotation_y
# self.sun.planet.last_rotation_y = self.sun.planet.rotation_y
UrsinaConfig.run_speed_factor = 0.00001 * 24
self.update_text_panel(time_data)
return
dt = time_data.get_datetime(self.start_time)
# if dt.year == self.current_year + 1:
# TODO: 调试用
if dt.month < 12:
UrsinaConfig.run_speed_factor = 50 * 24
elif UrsinaConfig.run_speed_factor > 20 * 24:
UrsinaConfig.run_speed_factor = 20 * 24
# TODO: 调试用
if dt.month >= 12 and dt.day >= 31:
if dt.hour > 20:
UrsinaConfig.run_speed_factor -= 0.00001 * 24
if UrsinaConfig.run_speed_factor < 0.00001 * 24:
UrsinaConfig.run_speed_factor = 0.00001 * 24
else:
UrsinaConfig.run_speed_factor -= 0.00001 * 24
elif dt.month >= 12 and dt.day >= 28 and UrsinaConfig.run_speed_factor >= 1.1 * 24:
UrsinaConfig.run_speed_factor -= 0.65 * 24
# elif dt.month >= 12 :#and dt.day > 20:
# UrsinaConfig.run_speed_factor -= 1
UrsinaConfig.run_speed_factor = round(UrsinaConfig.run_speed_factor, 2)
self.set_bodies_position(time_data)
self.update_text_panel(time_data)
# if dt.month >= 12:
# dd = distance(self.earth.position, self.earth_start.position)
# # 225000388
# if dd < 1000000:
# self.run_finished = True
# self.earth.planet.rotation_speed = 0
# return
def create_orbit_line(self, center_body, body, start_time, alpha=0.2):
import math
if not hasattr(body, "orbital_days"):
return None
orbital_days = int(math.ceil(body.orbital_days))
points = get_reality_orbit_points(type(body).__name__.lower(),
start_time=start_time,
days=orbital_days,
segments=100)
# print(points)
orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color,
alpha=alpha)
return orbit_line
def create_orbit_lines(self):
"""
创建太阳系天体的真实轨迹(太阳和哈雷彗星除外)
@return:
"""
# self.moon.orbital_days=27.5
self.create_orbit_line(self.sun, self.earth, self.start_time, alpha=1)
# self.create_orbit_line(self.sun, self.moon, self.start_time, alpha=0.5)
# TODO: 月球轨道
# moon_orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1)
# moon_orbit_line.rotation_x = 40
# for body in self.bodies[1:]:
# if isinstance(body, Earth):
# alpha = 0.5
# else:
# alpha = 0.2
# orbit_line = self.create_orbit_line(self.sun, body, self.start_time, alpha=alpha)
# if orbit_line is not None:
# self.orbit_lines.append(orbit_line)
def create_circle(self, time_data):
from ursina import Vec3
month = int(time_data.total_days / 29.5+0.5)
if month == 0:
return
month_name = "month_" + str(month)
if hasattr(self, month_name):
return
setattr(self, month_name, True)
print(month_name)
pos = self.earth.position
pos = Vec3(pos[0] * UrsinaConfig.SCALE_FACTOR,
pos[2] * UrsinaConfig.SCALE_FACTOR,
pos[1] * UrsinaConfig.SCALE_FACTOR)
# pos = Vec3(pos[0],pos[2],pos[1])
# pos = Vec3(pos[1], pos[2], pos[0])
# pos = Vec3(pos[2], pos[1], pos[0])
# pos = Vec3(pos[2], pos[0], pos[1])
# pos = Vec3(pos[1], pos[0], pos[2])
pos = pos / 2
circle_line = CircleLine(position=pos, radius=18.7, segments=30,
thickness=1, # color=self.moon.trail_color,
alpha=1)
circle_line.rotation_x = 65
circle_line.set_light_off(True)
def init_settings(self):
"""
初始化设置
@return:
"""
from ursina import color
# 创建天空
# create_sphere_sky(scale=5000)
# UrsinaConfig.trail_type = "curve_line"
UrsinaConfig.trail_type = "line"
UrsinaConfig.trail_length = 860
UrsinaConfig.trail_length = 40
UrsinaConfig.trail_thickness_factor = 2
UrsinaConfig.run_speed_factor = 20
# camera.clip_plane_near = 0.1
# camera.clip_plane_far = 51000
# camera.fov = 60
# self.sun.planet.color = color.white
# application.time_scale = 0.01
# 摄像机移动 update
# camera_move_update()
# camera_move_to_target_update()
def show_clock(self, time_data):
"""
显示时钟
@param dt: 时间 datetime
@return:
"""
# if self.clock_position_center:
# position, origin = (0, .25), (0, 0),
# else:
from ursina import window
total_days = round(time_data.total_days, 2)
if total_days > self.earth_revolution_days:
total_days = self.earth_revolution_days
seconds = self.earth_revolution_days * 24 * 60 * 60
time_data = TimeData(seconds, "seconds", seconds)
dt = time_data.get_datetime(self.start_time)
# 月球围绕地球转一圈的时间,即月球真正的公转周期是一个恒星月,时间是27.5天 。
# 而我们一般用从地球上看,月球完成一次朔望更替为一个月,叫一个朔望月,时间是29.5天。
aspect_ratio = window.aspect_ratio
position, origin = (0.5 * aspect_ratio - 0.15, -0.45), (-0.05, 0.1),
# ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d'),
# position=position,
# origin=origin,
# # font="verdana.ttf",
# font="fonts/Digital-7Mono.TTF",
# font_scale=2,
# font_color=(0, 255, 0),
# close_time=-1)
if hasattr(self, "text_panel"):
self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \
"天数:" + str(round(total_days, 2)) + "\n\n" + \
"月数:" + str(round(total_days / 29.5, 2))
# "运行速度:" + str(UrsinaConfig.run_speed_factor) + "\n" + \
# "天数:" + str(round(total_days, 3))
def update_text_panel(self, time_data):
"""
更新文字信息面板
@param d_sun:
@return:
"""
# panel_text = "时间" #"\n\n当前速度:%s km/s" % "{:.3f}".format(velocity).rjust(6, "0")
#
# self.text_panel.text = panel_text
self.show_clock(time_data)
def on_ready(self):
"""
事件绑定后,模拟器运行前会触发
@return:
"""
# 初始化设置
self.init_settings()
self.earth_start.planet.alpha = 0.5
# self.set_window_size((int(1920 * r), int(1080 * r)), False)
# 最大分辨率的高度-1,保证不全屏
# self.set_window_size((1920, 1079), False)
# self.set_window_size((1920 , 1080 ), False)
camera_look_at(self.sun)
# 显示网格以及坐标线
# self.show_grid_axises(scale_factor=8)
# 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外)
self.create_orbit_lines()
# 创建信息显示面板
# self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5)
# self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3)
def run(self, start_time='2023-01-01 00:00:00'):
self.build_bodies()
from astropy.time import Time
from datetime import datetime
self.current_year = int(start_time[0:4])
start_time = Time(datetime.strptime(start_time + '+0800', '%Y-%m-%d %H:%M:%S%z'),
format='datetime')
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed)
# 运行前会触发 on_ready
UrsinaEvent.on_ready_subscription(self.on_ready)
# init_bodies_reality_pos_vels(self.bodies, start_time)
self.start_time = start_time
ursina_run(self.bodies,
SECONDS_PER_DAY / 24,
# position=(0, 3.5 * AU, -AU), # 顶上
position=(0, 1 * AU, -3.5 * AU),
gravity_works=False,
cosmic_bg='',
show_trail=True,
# bg_music='sounds/no_glory.mp3',
show_camera_info=False,
# video_recoder=True,
show_control_info=False,
timer_enabled=True,
show_grid=False
)
if __name__ == '__main__':
sim = SunEarthMoonSim()
sim.run()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册