# -*- coding:utf-8 -*- # title :太阳系行星大小比较 # description :太阳系行星大小比较 # author :Python超人 # date :2023-06-17 # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== import threading from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon from common.consts import SECONDS_PER_HOUR, SECONDS_PER_DAY, AU from sim_scenes.func import ursina_run, create_sphere_sky from simulators.ursina.entities.body_timer import TimeData, AppTimeUtil from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_config import UrsinaConfig # 可以调整整体放大倍数 ,比例会保持不变 FACTOR = 10 # 地球和月球之间的距离常量,距地距离约: 363104 至 405696 km,平均距离 384000 km E_M_DISTANCE = 405696 * FACTOR earth1 = Earth("地球1", size_scale=FACTOR, init_position=[0, 0, 0]) moon = Moon("月球", size_scale=FACTOR, init_position=[E_M_DISTANCE, 0, 0]) earth2 = Earth("地球2", texture="earth2.jpg", size_scale=FACTOR) bodies = [ earth1, moon, Mercury(name="水星", size_scale=FACTOR), Venus(name="金星", size_scale=FACTOR), earth2, Mars(name="火星", size_scale=FACTOR), Jupiter(name="木星", texture='jupiter_hd.jpg', size_scale=FACTOR), Saturn(name="土星", size_scale=FACTOR).show_rings(False), Uranus(name="天王星", size_scale=FACTOR), Neptune(name="海王星", size_scale=FACTOR), Pluto(name="冥王星", size_scale=FACTOR) ] if __name__ == '__main__': # 使用应用的计时器工具 app_time_util = AppTimeUtil() key_point_time_util = AppTimeUtil() last_diameter = earth1.diameter * FACTOR / 2 plant_positions = [] for i, body in enumerate(bodies): body.rotation_speed /= 10 # 星体的旋转速度减小10倍 body.ignore_mass = True body.init_velocity = [0, 0, 0] if i >= 2: # 从第三个星球(水星)开始 plant_positions.append([(body.diameter * FACTOR / 2) + last_diameter, 0, 0]) last_diameter += body.diameter * FACTOR # print(body) import ursina from ursina import camera, time, Vec3, application def on_ready(): # 运行前触发 # 为了较好的立体效果,可以增加太阳光线,光线直射地球(target=earth) create_directional_light(position=(E_M_DISTANCE / 2, E_M_DISTANCE * 20, -E_M_DISTANCE * 100), light_num=3, target=earth1) application.time_scale = 0.001 sky = create_sphere_sky(scale=2000) sky.alpha = 0.5 # sky.rotation_y = -90 sky.rotation_x = 200 # sky.rotation_z = 200 key_points = [(E_M_DISTANCE / 2, 0, -E_M_DISTANCE), (0, 0, -E_M_DISTANCE / 4), (100000, 0, -E_M_DISTANCE / 4), (200000, 0, -E_M_DISTANCE / 4), (300000, 0, -E_M_DISTANCE / 4), (400000, 0, -E_M_DISTANCE / 4), (500000, 0, -E_M_DISTANCE), # 木星 (1800000, 0, -E_M_DISTANCE), # 土星 (3000000, 0, -E_M_DISTANCE), # 天王星 (3800000, 0, -E_M_DISTANCE), # 海王星 (4000000, 0, -E_M_DISTANCE / 6), # 冥王星 (4000000, 0, -E_M_DISTANCE / 3), (3900000, 0, -E_M_DISTANCE / 1.5), (3600000, 0, -E_M_DISTANCE / 1.2), (3000000, 0, -E_M_DISTANCE / 1.1), (E_M_DISTANCE / 2, 0, -E_M_DISTANCE), ] ursina_kps = [Vec3(point) * UrsinaConfig.SCALE_FACTOR for point in key_points] interval = 3 # def move_planet(planet_body, target_pos): # planet_body.planet.origin_update = planet_body.planet.update # # def new_update(): # import numpy as np # current_pos = planet_body.init_position # c_pos = current_pos * UrsinaConfig.SCALE_FACTOR # t_pos = np.array(target_pos) * UrsinaConfig.SCALE_FACTOR # # for _ in range(10): # # current_pos = planet_body.init_position # # new_pos = ursina.lerp(Vec3(current_pos[0], current_pos[1], current_pos[2]), # # Vec3(target_pos[0], target_pos[1], target_pos[2]), 1e9) # # planet_body.init_position = [new_pos[0], new_pos[1], new_pos[2]] # n_pos = ursina.lerp(Vec3(c_pos[0], c_pos[1], c_pos[2]), # Vec3(t_pos[0], t_pos[1], t_pos[2]), 3e-2) # planet_body.planet.origin_update() # new_pos = np.array([n_pos[0], n_pos[1], n_pos[2]]) / UrsinaConfig.SCALE_FACTOR # planet_body.init_position = new_pos # # planet_body.planet.update = new_update # # return warp def on_timer_changed(time_data: TimeData): # camera_time = app_time_util.get_param("camera_time", 2) key_point_index = app_time_util.get_param("key_point_index", 0) body_index = app_time_util.get_param("body_index", 2) # 从第三个星球(水星)开始 if key_point_index + 1 >= len(ursina_kps): # camera.position = ursina_kps[-1] return if body_index < len(bodies): last_time = app_time_util.get_param("last_time", interval + 3) # 间隔3秒出现水星 # 判断是否第一个到达指定的时间 if app_time_util.is_first_arrival(last_time, time_data): # target_position = plant_positions[body_index - 2] def move_planet(planet_body, target_pos): import numpy as np def warp(): # current_pos = planet_body.init_position t_pos = np.array(target_pos) * UrsinaConfig.SCALE_FACTOR for _ in range(200): current_pos = planet_body.init_position c_pos = current_pos * UrsinaConfig.SCALE_FACTOR n_pos = ursina.lerp(Vec3(c_pos[0], c_pos[1], c_pos[2]), Vec3(t_pos[0], t_pos[1], t_pos[2]), 6e-2) new_pos = np.array([n_pos[0], n_pos[1], n_pos[2]]) / UrsinaConfig.SCALE_FACTOR planet_body.init_position = new_pos time.sleep(0.0001) planet_body.init_position = target_pos return warp f = move_planet(bodies[body_index], plant_positions[body_index - 2]) # f() t = threading.Thread(target=f) t.start() # time.sleep(0.1) app_time_util.inc_param("body_index", 1) app_time_util.inc_param("last_time", interval) # 间隔3秒出现下一个行星 print("key_point_index", key_point_index) current_point = ursina_kps[key_point_index] target_point = ursina_kps[key_point_index + 1] camera_time = 2 + key_point_index * interval if time_data.app_time > camera_time: dt = (time_data.app_time - camera_time) / interval if dt <= 1: camera.position = ursina.lerp(current_point, target_point, dt) # print(camera.position) elif key_point_time_util.is_first_arrival(camera_time, time_data): app_time_util.inc_param("key_point_index", 1) # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(on_timer_changed) # 运行前会触发 on_ready UrsinaEvent.on_ready_subscription(on_ready) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(bodies, SECONDS_PER_HOUR * 2, position=key_points[0], cosmic_bg='', show_grid=False, # view_closely=True, timer_enabled=True)