# -*- coding:utf-8 -*- # title :遨游太阳系 # description :遨游太阳系 # author :Python超人 # date :2024-03-04 # link :https://gitcode.net/pythoncr/ # python_version :3.9 # ============================================================================== from ursina import camera, application, lerp, Vec3 from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto from common.celestial_data_service import init_bodies_reality_pos_vels, conv_to_astropy_time, \ set_solar_system_celestial_position, init_bodies_pos_vels, get_init_pos_vels_2 from common.consts import SECONDS_PER_YEAR, SECONDS_PER_MINUTE, SECONDS_PER_HOUR, AU from common.func import calculate_distance from bodies import Earth from objs import QuadObj, CircleObj, Obj, CoreValagaClas 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.solar_system.halley_comet_lib import HalleyCometSimBase, HalleyCometParams, \ create_halley_comet, create_orbit_line from sim_scenes.universe_sim_scenes import UniverseSimScenes 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 SolarSystemExplorer(UniverseSimScenes): """ 遨游太阳系 """ def build_solar_system(self): # region 构建太阳系 show_trail = False self.SIZE_FACTOR = 0.1 # 0.01 # self.init_pos = [2 * AU, 2 * AU, 5 * AU] # self.init_pos = [1.8 * AU, 1.8 * AU, 4.5 * AU] self.init_pos = [1.8 * AU, 1.8 * AU, 4.5 * AU] self.sun = Sun(size_scale=2e2 * self.SIZE_FACTOR, show_trail=show_trail, # color=(255, 250, 245), # texture="", texture="sun_light.jpg" ) self.sun.glows = (24, 1.008, 0.04) self.sun.set_resolution(200) self.mercury = Mercury(size_scale=2e3 * self.SIZE_FACTOR, distance_scale=1.6, show_trail=show_trail) self.venus = Venus(size_scale=2e3 * self.SIZE_FACTOR, distance_scale=1.5, show_trail=show_trail) self.earth = Earth(size_scale=2e3 * self.SIZE_FACTOR, distance_scale=1.5, rotate_angle=0, show_trail=show_trail) self.mars = Mars(size_scale=2e3 * self.SIZE_FACTOR, distance_scale=1.4, show_trail=show_trail) self.jupiter = Jupiter(size_scale=0.3e3 * self.SIZE_FACTOR, distance_scale=0.7, show_trail=show_trail) self.saturn = Saturn(size_scale=0.3e3 * self.SIZE_FACTOR, distance_scale=0.52, show_trail=show_trail) self.uranus = Uranus(size_scale=0.8e3 * self.SIZE_FACTOR, distance_scale=0.34, show_trail=show_trail) self.neptune = Neptune(size_scale=0.8e3 * self.SIZE_FACTOR, distance_scale=0.25, show_trail=show_trail) self.pluto = Pluto(size_scale=1e4 * self.SIZE_FACTOR, distance_scale=0.23, show_trail=show_trail) D = AU / 10 self.camera_target = CoreValagaClas(name="摄像机镜头", mass=1e30, color=(111, 140, 255), # init_position=[0, 0, 0], init_position=self.init_pos, init_velocity=[0, 0, 0], texture='transparent.png', size_scale=1e3 * self.SIZE_FACTOR).set_ignore_gravity(True) # self.bodies = [ # self.sun, # 太阳 # self.mercury, # 水星 # self.venus, # 金星 # self.earth, # 地球 # self.mars, # 火星 # self.jupiter, # 木星 # self.saturn, # 土星 # self.uranus, # 天王星 # self.neptune, # 海王星 # self.pluto, # 冥王星 # self.camera_target # ] self.bodies = [ self.camera_target, self.saturn, # 土星 self.mars, # 火星 self.earth, # 地球 self.mercury, # 水星 self.sun, # 太阳 self.venus, # 金星 self.jupiter, # 木星 self.uranus, # 天王星 self.neptune, # 海王星 # self.pluto, # 冥王星 ] self.sun.target_offset = [1, 1, 1.1] self.mercury.target_offset = [1, 1, 1.002] self.venus.target_offset = [1, 1, 1] self.earth.target_offset = [1, 1, 1] self.mars.target_offset = [1, 1, 1] self.jupiter.target_offset = [1, 1, 1] self.saturn.target_offset = [1, 1, 1] self.uranus.target_offset = [1, 1, 1] self.neptune.target_offset = [1, 1, 1] self.pluto.target_offset = [1, 1, 1] self.sun.dd_factor = 1.5 self.mercury.dd_factor = 5 self.venus.dd_factor = 1.5 self.earth.dd_factor = 1.5 self.mars.dd_factor = 1.5 self.jupiter.dd_factor = 1.5 self.saturn.dd_factor = 1.5 self.uranus.dd_factor = 1.5 self.neptune.dd_factor = 1.5 self.pluto.dd_factor = 1.5 self.init_pos_vels() # init_bodies_pos_vels(self.bodies, init_pos_vels_fun=self.get_init_pos_vels) def init_pos_vels(self): from astropy.time import Time from datetime import datetime start_time = Time(datetime.strptime('2149-02-01 12:00:00+0800', '%Y-%m-%d %H:%M:%S%z'), format='datetime') # set_solar_system_celestial_position(self.bodies, start_time, True) init_bodies_reality_pos_vels(self.bodies, start_time) def get_init_pos_vels(self): init_pos_vels = {} init_pos_vels['sun'] = {} init_pos_vels['sun']['pos'] = [-23.205570220947266, 0.0, 494.46502685546875] init_pos_vels['sun']['vel'] = [-3.617262336774729e-05, 0.0, 0.000522326270584017] init_pos_vels['mercury'] = {} init_pos_vels['mercury']['pos'] = [-56858320.0, 0.0, -237695.5] init_pos_vels['mercury']['vel'] = [0.5191680788993835, 0.0, -48.36161804199219] init_pos_vels['venus'] = {} init_pos_vels['venus']['pos'] = [-61601512.0, 0.0, 88374768.0] init_pos_vels['venus']['vel'] = [-28.69715118408203, 0.0, -20.112533569335938] init_pos_vels['earth'] = {} init_pos_vels['earth']['pos'] = [-54543052.0, 0.0, 139275888.0] init_pos_vels['earth']['vel'] = [-27.743507385253906, 0.0, -10.863121032714844] init_pos_vels['mars'] = {} init_pos_vels['mars']['pos'] = [-44924356.0, 0.0, 222884576.0] init_pos_vels['mars']['vel'] = [-23.654102325439453, 0.0, -4.7799787521362305] init_pos_vels['asteroids'] = {} init_pos_vels['asteroids']['pos'] = [0.0, 0.0, 0.0] init_pos_vels['asteroids']['vel'] = [0.0, 0.0, 0.0] init_pos_vels['jupiter'] = {} init_pos_vels['jupiter']['pos'] = [-24472074.0, 0.0, 776025472.0] init_pos_vels['jupiter']['vel'] = [-13.053510665893555, 0.0, -0.4124884009361267] init_pos_vels['saturn'] = {} init_pos_vels['saturn']['pos'] = [-18066134.0, 0.0, 1421063552.0] init_pos_vels['saturn']['vel'] = [-9.6392240524292, 0.0, -0.12374488264322281] init_pos_vels['uranus'] = {} init_pos_vels['uranus']['pos'] = [-12762774.0, 0.0, 2872276736.0] init_pos_vels['uranus']['vel'] = [-6.809953689575195, 0.0, -0.030240831896662712] init_pos_vels['neptune'] = {} init_pos_vels['neptune']['pos'] = [-10176475.0, 0.0, 4592654848.0] init_pos_vels['neptune']['vel'] = [-5.429999828338623, 0.0, -0.011822682805359364] init_pos_vels['pluto'] = {} init_pos_vels['pluto']['pos'] = [-8808451.0, 0.0, 5916595712.0] init_pos_vels['pluto']['vel'] = [-4.699999809265137, 0.0, -0.007128323893994093] return init_pos_vels def build(self): """ 构建太阳系系统以及哈雷彗星 @return: """ self.build_solar_system() def init_settings(self): """ 初始化设置 @return: """ from ursina import color # 创建天空 create_sphere_sky(texture="bg_pan2.jpg", 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 application.time_scale = 0.0001 # camera.fov = 60 # self.current_stage = self.stage_01 def s_f(self, value=1): if value == 0: return 0 return get_run_speed_factor() * value def camera_move(self, time_data): """ 摄像机移动控制 @param dt: @return: """ # 摄像机移动控制数据 camera_move_infos = [ # 条件:年份 # 移动的信息: # 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳) # 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下 (0, {"f": 5.758}), # (1983, {"to": {"ct_id": 1, "t": 10}}), (11, {"f": 1.8}), (14, {"f": 2}), (18, {"f": 2}), (25, {"f": 1}), (28, {"f": 0.2}), # (30, {"f": 0.5}), # (40, {"f": 0.6}), (33, {"b": 2}), (50, {"f": 0.2}), (65, {"f": 2}), (69, {"f": 3}), (70, {"f": 4}), (75, {"f": 5}), (90, {"f": 3}), (200, {}), # (2000, {"exit": True}), # (1989, {"z": -8, "f": -5}), # (1993, {"z": -8, "f": -3}), # (1995, {"z": -8}), # (2000, {"z": -8, "y": -0.2}), # (2013, {}), # (2048, {"f": 3}), # (2062, {"y": -3}), # (2063, {"y": -10, "z": 2}), # (2181, {}), # (2082, {"exit": True}) (250, {"exit": True}), ] if time_data.total_days > 120: # self.two_way_foil_circle.planet.enabled = False self.two_way_foil.scale_factor = 0.5 if 100 > time_data.total_days > 28: self.two_way_foil.scale_factor -= 1.5e-3 def cond_cb(ps): return ps["next_cond"] > time_data.total_days >= ps["cond"] camera_move_control(camera_move_infos, cond_cb=cond_cb, value_conv=self.s_f, smooth=1) def get_target(self): for body in self.bodies[1:]: if hasattr(body, "is_arrived"): continue return body return None def last_target(self): return self.sun 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 camera.speed = 4e2 self.camera_target.planet.update = lambda: None # 显示网格以及坐标线 # self.show_grid_axises(scale_factor=50) target = self.get_target() camera_look_at(self.saturn, rotation_z=0) def go_target(self): from ursina import distance target = self.get_target() if target is None: return target_scale = target.planet.scale_x target_offset = target.target_offset target_pos = target.planet.position + \ Vec3(target_scale * (target_offset[0] - 1), target_scale * (1 / 10) * target_offset[1], target_scale * (target_offset[2] - 1)) self.camera_target.planet.look_at(target_pos) dd = distance(self.camera_target.planet.position, target_pos) if not hasattr(target, "distance"): target.distance = dd self.camera_target.planet.position = lerp(self.camera_target.planet.position, target_pos, camera.speed * time.dt * target.distance) camera_target_pos = self.camera_target.planet.position dd2 = distance(camera.position, camera_target_pos) camera.position = lerp(camera.position, camera_target_pos, camera.speed * 1 * time.dt * target.distance) if dd < target_scale * target.dd_factor and dd2 < target_scale * target.dd_factor: if target is not None: target.is_arrived = True camera_look_at(self.camera_target, rotation_z=0) # print(camera.position) print(target.name, target_scale, dd, self.camera_target.planet.position) # print(dd) def on_timer_changed(self, time_data): """ @param time_data: @return: """ # return self.go_target() # self.camera_move(time_data) # self.current_stage() if __name__ == '__main__': """ """ # params = TwoWayFoilSim() sim = SolarSystemExplorer() # window_size = (1920, 1079) # UniverseSimScenes.set_window_size(window_size, False) sim.build() # 订阅事件后,上面2个函数功能才会起作用 # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) # 运行前会触发 on_ready UrsinaEvent.on_ready_subscription(sim.on_ready) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(sim.bodies, # SECONDS_PER_YEAR / 48 * get_run_speed_factor(), SECONDS_PER_MINUTE, # position=(0, 2 * AU, -11 * AU), # position=(0, 0.5 * AU, -5 * AU), # position=(2 * AU, -5 * AU, -20 * AU), position=sim.init_pos, cosmic_bg='', # show_trail=True, # bg_music='sounds/no_glory.mp3', show_camera_info=False, # video_recoder=True, show_control_info=False, # save_cube_map=True, timer_enabled=True, # show_timer=True, show_grid=False )