# -*- 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 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 SECONDS_PER_DAY, AU 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 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 class EarthSeasonsSimLive(EarthSeasonsSimBase): def __init__(self): super(EarthSeasonsSimLive, self).__init__(sun_transparent=False, exit_at_total_days=370, 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.sun.size_scale = 3e1 self.moon = Moon(name="月球", size_scale=5e3, rotation_speed=0.645 ) # 月球 self.mercury = Mercury(size_scale=5e3) self.venus = Venus(name="金星", size_scale=5e3) self.mars = Mars(size_scale=5e3) self.jupiter = Jupiter(size_scale=1e3) self.saturn = Saturn(size_scale=1e3) self.uranus = Uranus(size_scale=4e3) self.neptune = Neptune(size_scale=4e3) self.bodies += [self.moon, self.mercury, self.venus, self.mars, self.jupiter, self.saturn, self.uranus, self.neptune] self.last_year = None for body in self.bodies: if isinstance(body, Earth): body.show_name = False 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.planets = [] self.jieqis = { "春分-2023": '2023-03-21 00:00:00', "夏至-2023": '2023-06-21 00:00:00', "秋分-2023": '2023-09-23 00:00:00', "冬至-2023": '2023-12-22 00:00:00', "春分-2024": '2024-03-20 00:00:00', "夏至-2024": '2024-06-21 00:00:00', "秋分-2024": '2024-09-22 00:00:00', "冬至-2024": '2024-12-21 00:00:00', "春分-2025": '2025-03-20 00:00:00', "夏至-2025": '2025-06-21 00:00:00', "秋分-2025": '2025-09-23 00:00:00', "冬至-2025": '2024-12-21 00:00:00', } for body in self.bodies: if body not in self.season_earths: self.planets.append(body) def earth_text_display(self, term_name): for e in [self.earth_1, self.earth_2, self.earth_3, self.earth_4]: # 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() # camera_look_at(self.sun, rotation_z=0) self.earth_1.planet.alpha = 0.2 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) ec = UrsinaSimulator.EditorCamera # ec.target_z -= 0.05 # camera.position += camera.left * 0.0001 def set_bodies_position(self, time_data: TimeData): """ 设置天体的位置(包含速度和加速度的信息) @param time_data: @return: """ dt = conv_to_astropy_time(self.start_time) center_pos = self.get_center_pos(dt) year = int(dt.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=center_pos) self.last_year = year t = dt + time_data.total_days set_solar_system_celestial_position(self.planets, t, True, recalc_moon_pos_scale=180, center_pos=center_pos) def exit_handle(self): UrsinaEvent.on_reset() return True def show_title(self): font = "fonts/DroidSansFallback.ttf" from common.func import find_file font = find_file(f"{font}", UrsinaConfig.CN_FONT) 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=font) text2 = Text(text="(地球自转放慢10倍)", color=color.white, scale=1.5, position=position2, # (-0.98, 0.48), font=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, init_position=[0, 0, -2 * AU], show_exit_button=False, show_camera_info=False, gravity_works=False, show_control_info=False)