# -*- coding:utf-8 -*- # title :地球季节模拟(四季和24节气) # description :地球季节模拟(四季和24节气) # author :Python超人 # date :2023-02-11 # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== from ursina import camera, window, Text, color, Vec3, destroy from bodies import * from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, get_body_posvel from common.consts import * from sim_scenes.featured.earth_seasons_base import EarthSeasonsSimBase from sim_scenes.func import ursina_run, camera_look_at, create_sphere_sky from sim_scenes.science.earth_season_func import create_important_pos_earths, get_solar_terms_angles, create_earth, \ create_important_pos_earths_2 from sim_scenes.universe_sim_scenes import UniverseSimScenes from simulators.ursina.entities.body_timer import TimeData, BodyTimer 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_simulator import UrsinaSimulator import numpy as np import math class EarthSeasonsSimLive(EarthSeasonsSimBase): def __init__(self): super(EarthSeasonsSimLive, self).__init__(sun_transparent=False, exit_at_total_days=3700, delay_run=False, earth_cn_size_factor=1.01, earth_clouds_size_factor=1.015) self.start_time = '2023-12-20 00:00:00' # self.start_time = '2024-04-08 00:00:00' self.sun.size_scale = 6e1 self.earth.size_scale = 2e3 self.earth_clouds.size_scale = self.earth.size_scale self.earth_cn.size_scale = self.earth.size_scale self.moon = Moon(name="月球", size_scale=2e3, rotation_speed=0.645 ) # 月球 self.mercury = Mercury(size_scale=2e3) self.venus = Venus(name="金星", size_scale=2e3) self.mars = Mars(size_scale=2e3) self.jupiter = Jupiter(size_scale=0.6e3) self.saturn = Saturn(size_scale=0.6e3) self.uranus = Uranus(size_scale=2e3) self.neptune = Neptune(size_scale=2e3) self.bodies += [self.moon, self.mercury, self.venus, self.mars, self.jupiter, self.saturn, self.uranus, self.neptune, self.earth_5, self.earth_6, self.earth_7, self.earth_8] self.last_year = None for body in self.bodies: if isinstance(body, Earth): body.show_name = True body.rotate_angle -= 22 body.rotation_speed *= 2.5 body.set_resolution(50) self.season_earths = [self.earth_1, self.earth_2, self.earth_3, self.earth_4, self.earth_5, self.earth_6, self.earth_7, self.earth_8] self.planets = [] names = ["立春", "春分", "立夏", "夏至", "立秋", "秋分", "立冬", "冬至"] from common.china_24_jieqi import JieQi jieqi = JieQi(names) self.jieqis = jieqi.get_years_jieqi(2023, 2025) font = "fonts/DroidSansFallback.ttf" # font = "fonts/新青年体.ttf" from common.func import find_file self.font = find_file(f"{font}", UrsinaConfig.CN_FONT) for body in self.bodies: if body not in self.season_earths: self.planets.append(body) else: # body.texture = "transparent.png" body.size_scale = self.earth.size_scale / 1.1 body.show_trail = False def create_important_pos_earths(self): self.earth_1, self.earth_2, self.earth_3, self.earth_4 = create_important_pos_earths(texture="earth-huge.jpg", size_scale=4.9e3, position_offset=1.0) self.earth_5, self.earth_6, self.earth_7, self.earth_8 = create_important_pos_earths_2(texture="earth-huge.jpg", size_scale=4.9e3, position_offset=1.0) return self.earth_1, self.earth_2, self.earth_3, self.earth_4 def earth_text_display(self, term_name): for e in [self.earth_1, self.earth_2, self.earth_3, self.earth_4, self.earth_5, self.earth_6, self.earth_7, self.earth_8]: # if hasattr(e, "name_text"): # if term_name == e.name: # e.name_text.enabled = False # else: e.name_text.enabled = True def get_center_pos(self, dt): posvel = get_body_posvel(self.earth, dt) position = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU] center_pos = np.array(position) return center_pos def on_ready(self): super(EarthSeasonsSimLive, self).on_ready() for e in self.season_earths: if hasattr(e, "planet"): # e.planet.rotation_y += 15 # 夏至 e.planet.alpha = 0.2 # 将 4 个节气位置的地球进行旋转,让中国面对太阳 # if hasattr(self.earth_1, "planet"): # self.earth_1.planet.rotation_y += 115 # 春分 # self.earth_1.planet.alpha = 0.2 # if hasattr(self.earth_2, "planet"): # self.earth_2.planet.rotation_y += 15 # 夏至 # self.earth_2.planet.alpha = 0.2 # if hasattr(self.earth_3, "planet"): # self.earth_3.planet.rotation_y -= 80 # 秋分 # self.earth_3.planet.alpha = 0.2 # if hasattr(self.earth_4, "planet"): # self.earth_4.planet.rotation_y -= 145 # 冬至 # self.earth_4.planet.alpha = 0.2 UrsinaConfig.trail_type = "line" # UrsinaConfig.trail_length = 91 UrsinaConfig.trail_type = "curve_line" UrsinaConfig.trail_length = 50 # UrsinaConfig.trail_length = 1000 UrsinaConfig.trail_thickness_factor = 2 for body in self.planets: body.planet.trail_scale = 3 body.planet.name_text.scale = 5 destroy(body.planet.name_text.background) body.planet.name_text.color = color.white body.planet.name_text.font = self.font body.planet.name_text.position = Vec3(0, 0.6, 0) # body.planet.name_text.position = Vec3(0, pow(body.planet.main_entity.scale_y, 1 / 12) / 2, 0) # body.planet.name_text def camera_distance_update(name_text): o_scale = name_text.scale_x def update2(): print(name_text.parent.body) return update2 # body.planet.name_text.update = camera_distance_update(body.planet.name_text) self.moon.planet.trail_scale = 1 # camera.orthographic = True camera.clip_plane_near = 1 # camera.clip_plane_far = sky.scale_x * 1.5 destroy(self.earth_clouds.planet) destroy(self.earth_cn.planet) # self.earth_cn.size_scale = self.earth.size_scale for e in self.season_earths: # camera_look_at(self.sun, rotation_z=0) # e.planet.scale = 0.1 # e.planet.alpha = 0.2 if not hasattr(e, "name_text"): continue e.name_text.scale = Vec3(10, 10, 10) e.name_text.font = self.font destroy(e.name_text.background) # self.earth_2.planet.alpha = 0.2 # self.earth_3.planet.alpha = 0.2 # self.earth_4.planet.alpha = 0.2 self.earth.planet.name_text.enabled = False # , self.earth_clouds, self.earth_cn self.earth_1.planet.rotation_y = 115 # 春分 self.earth_2.planet.rotation_y = 15 # 夏至 self.earth_3.planet.rotation_y = -80 # 秋分 self.earth_4.planet.rotation_y = -145 # 冬至 self.moon.planet.rotation_y = 180 self.show_title() # camera.fov = 140 window.borderless = True window.exit_button = False # window.fullscreen = True # window.position = (1920, 0) # # 设置窗口的宽度和高度 # window.size = (2340, 1079) def on_timer_changed(self, time_data: TimeData): super(EarthSeasonsSimLive, self).on_timer_changed(time_data) camera.rotation_z = -8 dt = time_data.get_datetime(self.start_time) self.set_bodies_position(time_data) self.show_clock(dt) self.camera_around() def camera_around(self): ec = UrsinaSimulator.EditorCamera ec.rotation_y -= 0.01 * UrsinaConfig.run_speed_factor # 每帧绕y轴旋转1度 # print(self.earth.planet.world_position) # print(self.earth.planet.position) def set_bodies_position(self, time_data: TimeData): """ 设置天体的位置(包含速度和加速度的信息) @param time_data: @return: """ dt = conv_to_astropy_time(self.start_time) t = dt + time_data.total_days center_pos = self.get_center_pos(t) set_solar_system_celestial_position(self.planets, t, True, recalc_moon_pos_scale=60, center_pos=center_pos) year = int(t.jyear) if self.last_year != year: for body in self.season_earths: jieqir = self.jieqis.get(f"{body.name}-{year}", None) if jieqir is not None: jieqir = conv_to_astropy_time(jieqir) set_solar_system_celestial_position([body], jieqir, False, center_pos=None) body.abs_position = body.position self.last_year = year for body in self.season_earths: body.position = body.abs_position + self.sun.position def exit_handle(self): UrsinaEvent.on_reset() return True def show_title(self): aspect_ratio = window.aspect_ratio position, origin = (-0.5 * aspect_ratio - 0.1, 0.48), (-0.05, 0.1) position2, origin2 = (-0.5 * aspect_ratio - 0.1, 0.40), (-0.05, 0.1) # text1 = Text(text="太阳视角:观察日食月食", color=color.white, scale=2.5, position=position, # (-0.98, 0.48), # font=font) ext1 = Text(text="太阳视角:2024年重要天象", color=color.white, scale=2.5, position=position, # (-0.98, 0.48), font=self.font) text2 = Text(text="(地球自转放慢10倍)", color=color.white, scale=1.5, position=position2, # (-0.98, 0.48), font=self.font) # 2024年重要天象 def show_clock(self, dt): """ 显示时钟 @param dt: 时间 datetime @return: """ # if self.clock_position_center: # position, origin = (0, .25), (0, 0), # else: from ursina import window aspect_ratio = window.aspect_ratio position, origin = (0., 0.45), (0., 0.), 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 __name__ == '__main__': """ 摄像机以太阳的视角看地球(四季和24节气) """ sim = EarthSeasonsSimLive() sim.run( # dt=SECONDS_PER_DAY * 10, dt=SECONDS_PER_DAY * 3, # dt=SECONDS_PER_HOUR, init_position=[0, 0, -3 * AU], show_exit_button=False, show_camera_info=False, gravity_works=False, show_control_info=False)