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

Python超人-宇宙模拟器

上级 e23afbfa
...@@ -2,24 +2,33 @@ ...@@ -2,24 +2,33 @@
# title :三体二向箔场景模拟 # title :三体二向箔场景模拟
# description :三体二向箔场景模拟 # description :三体二向箔场景模拟
# author :Python超人 # author :Python超人
# date :2023-10-27 # date :2024-01-20
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.9 # python_version :3.9
# ============================================================================== # ==============================================================================
import time
from ursina import camera, application, lerp
from ursina import camera, application, lerp, Vec3
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.celestial_data_service import get_init_pos_vels, init_bodies_pos_vels from common.celestial_data_service import init_bodies_reality_pos_vels, conv_to_astropy_time, \
from common.consts import SECONDS_PER_WEEK, AU set_solar_system_celestial_position, init_bodies_pos_vels
from common.image_utils import resize_image from common.consts import SECONDS_PER_YEAR, AU
from common.func import calculate_distance
from bodies import Earth
from objs import QuadObj, CircleObj, Obj from objs import QuadObj, CircleObj, Obj
from sim_scenes.func import camera_look_at, two_bodies_colliding, camera_move_control, get_run_speed_factor from sim_scenes.func import create_text_panel, camera_look_at, get_run_speed_factor, \
camera_move_update, camera_move_to_target_update, camera_move_control, two_bodies_colliding
from sim_scenes.func import ursina_run, create_sphere_sky from sim_scenes.func import ursina_run, create_sphere_sky
from sim_scenes.solar_system.halley_comet_lib import HalleyCometSimBase, HalleyCometParams, \
create_halley_comet, create_orbit_line
from sim_scenes.universe_sim_scenes import UniverseSimScenes from sim_scenes.universe_sim_scenes import UniverseSimScenes
from simulators.ursina.ursina_event import UrsinaEvent
from simulators.func import ext_fun_for_method from simulators.func import ext_fun_for_method
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.entities.entity_utils import get_value_direction_vectors
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_label
import time
class TwoWayFoilSim(UniverseSimScenes): class TwoWayFoilSim(UniverseSimScenes):
...@@ -27,33 +36,36 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -27,33 +36,36 @@ class TwoWayFoilSim(UniverseSimScenes):
三体二向箔场景模拟 三体二向箔场景模拟
""" """
def __init__(self):
self.current_stage = self.stage_01
def build_solar_system(self): def build_solar_system(self):
# region 构建太阳系 # region 构建太阳系
self.sun, self.mercury, self.venus, self.earth, self.mars, self.jupiter, \ show_trail = True
self.saturn, self.uranus, self.neptune, self.pluto = \
Sun(size_scale=0.8e2, texture="sun_light.jpg"), \ self.sun = Sun(size_scale=0.6e2, show_trail=show_trail,
Mercury(size_scale=2e3, distance_scale=1.5), \ # color=(255, 250, 245),
Venus(size_scale=2e3, distance_scale=1.5), \ # texture="",
Earth(size_scale=2e3, distance_scale=1.5, rotate_angle=0), \ texture="sun_light.jpg"
Mars(size_scale=2e3, distance_scale=1.4), \ )
Jupiter(size_scale=0.3e3, distance_scale=0.72), \ self.mercury = Mercury(size_scale=2e3, distance_scale=1.5, show_trail=show_trail)
Saturn(size_scale=0.3e3, distance_scale=0.52), \ self.venus = Venus(size_scale=2e3, distance_scale=1.5, show_trail=show_trail)
Uranus(size_scale=0.8e3, distance_scale=0.36), \ self.earth = Earth(size_scale=2e3, distance_scale=1.5, rotate_angle=0, show_trail=show_trail)
Neptune(size_scale=0.8e3, distance_scale=0.27), \ self.mars = Mars(size_scale=2e3, distance_scale=1.4, show_trail=show_trail)
Pluto(size_scale=10e3, distance_scale=0.23) self.jupiter = Jupiter(size_scale=0.3e3, distance_scale=0.72, show_trail=show_trail)
self.saturn = Saturn(size_scale=0.3e3, distance_scale=0.52, show_trail=show_trail)
self.uranus = Uranus(size_scale=0.8e3, distance_scale=0.33, show_trail=show_trail)
self.neptune = Neptune(size_scale=0.8e3, distance_scale=0.25, show_trail=show_trail)
self.pluto = Pluto(size_scale=1e4, distance_scale=0.23, show_trail=show_trail)
self.bodies = [ self.bodies = [
self.sun, self.mercury, self.venus, self.earth, self.mars, self.jupiter, self.sun, # 太阳
self.saturn, self.uranus, self.neptune, self.pluto self.mercury, # 水星
self.venus, # 金星
self.earth, # 地球
self.mars, # 火星
self.jupiter, # 木星
self.saturn, # 土星
self.uranus, # 天王星
self.neptune, # 海王星
self.pluto, # 冥王星
] ]
# endregion
# self.sun.glows = (2, 1.005, 0.01)
# # glows = (glow_num:10, glow_scale:1.03 glow_alpha:0.1~1)
# self.sun.glows = (0, 1.005, 0.1, 160)
self.sun.glows = (2, 1.005, 0.01)
self.two_way_foil_dt_factor = 1 self.two_way_foil_dt_factor = 1
self.sun.two_way_foil_dt = 0.003 * self.two_way_foil_dt_factor self.sun.two_way_foil_dt = 0.003 * self.two_way_foil_dt_factor
...@@ -62,6 +74,37 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -62,6 +74,37 @@ class TwoWayFoilSim(UniverseSimScenes):
init_bodies_pos_vels(self.bodies) init_bodies_pos_vels(self.bodies)
def build(self):
"""
构建太阳系系统以及哈雷彗星
@return:
"""
self.build_solar_system()
self.build_two_way_foil()
def init_settings(self):
"""
初始化设置
@return:
"""
from ursina import color
# 创建天空
create_sphere_sky(scale=50000, rotation_x=200, rotation_y=None, rotation_z=45)
# UrsinaConfig.trail_type = "curve_line"
# UrsinaConfig.trail_length = 300
UrsinaConfig.trail_type = "line"
# UrsinaConfig.trail_length = 152 # 尾巴数量刚刚好
UrsinaConfig.trail_length = 130
UrsinaConfig.trail_thickness_factor = 3
# UrsinaConfig.trail_length = 180
UrsinaConfig.trail_factor = 3
# camera.clip_plane_near = 0.1
camera.clip_plane_far = 51000
# camera.fov = 60
self.current_stage = self.stage_01
def build_two_way_foil(self): def build_two_way_foil(self):
""" """
创建二向箔(一个原始的方形二向箔,一个不断扩展的圆形二向箔) 创建二向箔(一个原始的方形二向箔,一个不断扩展的圆形二向箔)
...@@ -70,10 +113,10 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -70,10 +113,10 @@ class TwoWayFoilSim(UniverseSimScenes):
# 原始的方形二向箔 # 原始的方形二向箔
self.two_way_foil = QuadObj(texture='two_way_foil.png', self.two_way_foil = QuadObj(texture='two_way_foil.png',
# size_scale=4e7, # size_scale=4e7,
size_scale=1e7, size_scale=1e6,
init_velocity=[0, -50, 60], init_velocity=[0, -50, 60],
init_position=[0, 5 * AU, -6 * AU]) \ init_position=[0, 5 * AU, -6 * AU]) \
.set_light_disable(True).set_ignore_gravity(True) .set_light_disable(True) # .set_ignore_gravity(False)
# 不断扩展的圆形二向箔 # 不断扩展的圆形二向箔
self.two_way_foil_circle = CircleObj(texture="two_way_foil_circle.png", self.two_way_foil_circle = CircleObj(texture="two_way_foil_circle.png",
size_scale=self.two_way_foil.size_scale * 2, size_scale=self.two_way_foil.size_scale * 2,
...@@ -83,70 +126,51 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -83,70 +126,51 @@ class TwoWayFoilSim(UniverseSimScenes):
self.bodies.append(self.two_way_foil) self.bodies.append(self.two_way_foil)
self.bodies.append(self.two_way_foil_circle) self.bodies.append(self.two_way_foil_circle)
def build(self): def s_f(self, value=1):
self.build_solar_system() if value == 0:
self.build_two_way_foil() return 0
return get_run_speed_factor() * value
def on_ready(self): def camera_move(self, time_data):
""" """
事件绑定后,模拟器运行前会触发 摄像机移动控制
@param dt:
@return: @return:
""" """
# 创建天空 # 摄像机移动控制数据
# camera.clip_plane_near = 0.1 camera_move_infos = [
camera.clip_plane_far = 1000000 # 条件:年份
create_sphere_sky(scale=200000) # 移动的信息:
application.time_scale = 5 # 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳)
# 圆形二向箔初始化(一开始不显示) # 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下
self.two_way_foil_circle.planet.rotation_x = 90 (0, {"f": 5.2}),
self.two_way_foil_circle.planet.enabled = False # (1983, {"to": {"ct_id": 1, "t": 10}}),
(10, {}),
def change_two_way_foil(): (12, {"f": 0.2}),
# 长方形膜状物,长八点五厘米,宽五点二厘米,比一张信用卡略大一些,极薄,看不出任何厚度。 (15, {"f": 0.3}),
# 封装状态下晶莹剔透、无色透明。待机模式下由于封装力场逐渐蒸发,会发出白光,使其表面呈纯白色,看上去就是一张纸条 (18, {"f": 0.4}),
self.two_way_foil.planet.scale_x = 8.5 # (30, {"f": 0.5}),
self.two_way_foil.planet.scale_y = 5.2 # (40, {"f": 0.6}),
(160, {"b": 2}),
glow_circle = self.sun.planet.glow_circle (1988, {"y": -3, "z": -12}),
fixed_star_ratio = glow_circle.scale_x / self.sun.planet.scale_x (1989, {"z": -8, "f": -5}),
(1993, {"z": -8, "f": -3}),
def glow_circle_update(): (1995, {"z": -8}),
glow_circle.enabled = self.sun.planet.enabled (2000, {"z": -8, "y": -0.2}),
glow_circle.position = self.sun.planet.position (2013, {}),
glow_circle.scale_x = fixed_star_ratio * self.sun.planet.scale_y (2048, {"f": 3}),
if glow_circle.scale_x < 5: (2062, {"y": -3}),
glow_circle.update = lambda :None (2063, {"y": -10, "z": 2}),
glow_circle.enabled = False (2181, {}),
glow_circle.scale_z = fixed_star_ratio * self.sun.planet.scale_x # (2082, {"exit": True})
# glow_circle.scale_z = fixed_star_ratio * fixed_star.scale_z ]
glow_circle.look_at(camera)
glow_circle.update = glow_circle_update
ext_fun_for_method(self.two_way_foil.planet, after_run_fun=change_two_way_foil) def cond_cb(ps):
return ps["next_cond"] > time_data.total_days >= ps["cond"]
def gen_pixcel_image(self, planet): camera_move_control(camera_move_infos,
""" cond_cb=cond_cb,
将纹理图改为像素图片 value_conv=self.s_f, smooth=1)
@param planet:
@return:
"""
import os
if planet.texture is None:
return
in_img = str(planet.texture.path)
if "_pixcel" in in_img:
return
out_img = os.path.split(in_img)
out_file = out_img[1].split('.')
out_file = f'{out_file[0]}_pixcel.{out_file[1]}'
out_img = os.path.abspath(os.path.join(out_img[0], "temp", out_file))
if not os.path.exists(out_img):
resize_image(in_img, out_img, 50, 25)
from ursina import Texture
planet.texture = Texture(out_img)
return out_img
def flatten_animation(self, body): def flatten_animation(self, body):
""" """
...@@ -273,6 +297,35 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -273,6 +297,35 @@ class TwoWayFoilSim(UniverseSimScenes):
# 圆形二向箔不断旋转的效果 # 圆形二向箔不断旋转的效果
self.two_way_foil_circle.planet.rotation_z += 0.4 self.two_way_foil_circle.planet.rotation_z += 0.4
def on_ready(self):
"""
事件绑定后,模拟器运行前会触发
@return:
"""
# 初始化设置
self.init_settings()
# self.set_window_size((int(1920 * r), int(1080 * r)), False)
# 最大分辨率的高度-1,保证不全屏
# self.set_window_size((1920, 1079), False)
application.time_scale = 0.00001
# 显示网格以及坐标线
# self.show_grid_axises()
self.two_way_foil.planet.alpha = 0.95
# 圆形二向箔初始化(一开始不显示)
self.two_way_foil_circle.planet.rotation_x = 90
self.two_way_foil_circle.planet.enabled = False
self.two_way_foil.scale_factor = 0.6
def change_two_way_foil():
# 长方形膜状物,长八点五厘米,宽五点二厘米,比一张信用卡略大一些,极薄,看不出任何厚度。
# 封装状态下晶莹剔透、无色透明。待机模式下由于封装力场逐渐蒸发,会发出白光,使其表面呈纯白色,看上去就是一张纸条
self.two_way_foil.planet.scale_x = 8.5 * self.two_way_foil.scale_factor
self.two_way_foil.planet.scale_y = 5.2 * self.two_way_foil.scale_factor
# self.two_way_foil.scale_factor -= 1e-4
ext_fun_for_method(self.two_way_foil.planet, after_run_fun=change_two_way_foil)
def on_timer_changed(self, time_data): def on_timer_changed(self, time_data):
""" """
...@@ -281,75 +334,38 @@ class TwoWayFoilSim(UniverseSimScenes): ...@@ -281,75 +334,38 @@ class TwoWayFoilSim(UniverseSimScenes):
""" """
# 原始方形二向箔飞行的翻转效果 # 原始方形二向箔飞行的翻转效果
if self.two_way_foil.planet.enabled: if self.two_way_foil.planet.enabled:
self.two_way_foil.planet.rotation_x += 0.1 self.two_way_foil.planet.rotation_x += 0.01
self.two_way_foil.planet.rotation_y += 1 self.two_way_foil.planet.rotation_y += 0.5
# # 摄像机始终看向二向箔 # dt = time_data.get_datetime(self.start_time)
# camera_look_at(self.two_way_foil) # # 摄像机看向哈雷彗星
camera_look_at(self.two_way_foil, rotation_z=0)
target = self.get_target()
if target is not None: # camera.look_at_2d(self.halley_comet.planet.position, axis='y')
if target is self.sun:
# 摄像机始终看向二向箔 time_total_hours = time_data.total_hours
camera_look_at(self.two_way_foil)
else: # if not hasattr(self, "last_total_hours"):
# 摄像机始终看向二向箔 # self.last_total_hours = time_total_hours
camera_look_at(self.two_way_foil) # self.update_halley_comet_info(dt)
camera.position += camera.forward*10 # print("time_total_hours", time_total_hours)
# # 摄像机移动每10小时更新一次
# self.interval_run(fun=self.camera_move, fun_args=[dt],
# total_times=time_total_hours,
# interval=20)
self.camera_move(time_data) self.camera_move(time_data)
# camera.position = \
# lerp(camera.position, target.planet.position, 0.001)
self.current_stage() self.current_stage()
def s_f(self, value=1):
if value == 0:
return 0
return get_run_speed_factor() * value
def camera_move(self, time_data): if __name__ == '__main__':
"""
摄像机移动控制
@param dt:
@return:
""" """
# 摄像机移动控制数据
camera_move_infos = [
# 条件:年份
# 移动的信息:
# 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳)
# 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下
(1, {"l": 2}),
(10, {"f": 50}),
# (40, {"f": 80}),
# (1983, {"to": {"ct_id": 1, "t": 10}}),
# (2, {"x": 2, "y": -2, "z": -15}),
# (3, {"y": -6, "z": -12}),
# (4, {"y": -3, "z": -12}),
# (5, {"z": -8, "f": -5}),
# (6, {"z": -8, "f": -3}),
# (7, {"z": -8}),
# (8, {"z": -8, "y": -0.2}),
# (9, {}),
# (100, {"f": 10}),
# (200, {"f": 10}),
# (500, {"f": 10}),
# (2062, {"y": -3}),
# (2063, {"y": -10, "z": 2}),
(2181, {}),
# (2082, {"exit": True})
]
camera_move_control(camera_move_infos, """
cond_cb=lambda ps: ps["next_cond"] > time_data.total_days >= ps["cond"],
value_conv=self.s_f, smooth=None)
params = TwoWayFoilSim()
if __name__ == '__main__': sim = TwoWayFoilSim(params)
"""
三体二向箔场景模拟
"""
sim = TwoWayFoilSim()
sim.build() sim.build()
# 订阅事件后,上面2个函数功能才会起作用 # 订阅事件后,上面2个函数功能才会起作用
# 运行中,每时每刻都会触发 on_timer_changed # 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed)
...@@ -359,13 +375,18 @@ if __name__ == '__main__': ...@@ -359,13 +375,18 @@ if __name__ == '__main__':
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
ursina_run(sim.bodies, ursina_run(sim.bodies,
SECONDS_PER_WEEK, SECONDS_PER_YEAR / 48 * get_run_speed_factor(),
position=(0, 2 * AU, -11 * AU), # position=(0, 2 * AU, -11 * AU),
# position=(0, 5 * AU, -5 * AU), # position=(0, 0.5 * AU, -5 * AU),
# position=(2 * AU, -5 * AU, -20 * AU),
position=(2 * AU, 2 * AU, -10 * AU),
cosmic_bg='', cosmic_bg='',
bg_music='sounds/no_glory.mp3', # show_trail=True,
# bg_music='sounds/no_glory.mp3',
show_camera_info=False, show_camera_info=False,
# video_recoder=True,
show_control_info=False, show_control_info=False,
timer_enabled=True, timer_enabled=True,
show_timer=True, show_timer=True,
show_grid=False) show_grid=False
)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册