From ec08e05ffa58fc4bc55a33fd872303966061f6d5 Mon Sep 17 00:00:00 2001 From: march3 Date: Thu, 28 Mar 2024 12:37:28 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_scenes/featured/earth_seasons_base.py | 50 +++++--- sim_scenes/featured/earth_seasons_live.py | 146 ++++++++++++++++++++++ 2 files changed, 179 insertions(+), 17 deletions(-) create mode 100644 sim_scenes/featured/earth_seasons_live.py diff --git a/sim_scenes/featured/earth_seasons_base.py b/sim_scenes/featured/earth_seasons_base.py index 883e47c..bc15325 100644 --- a/sim_scenes/featured/earth_seasons_base.py +++ b/sim_scenes/featured/earth_seasons_base.py @@ -28,7 +28,8 @@ class EarthSeasonsSimBase(UniverseSimScenes): exit_at_total_days=375, earth_cn_size_factor=1.001, earth_clouds_size_factor=1.01, - show_name=True): + show_name=True, + delay_run=True): if sun_transparent: self.sun = Sun(size_scale=5e1, texture="transparent.png") # 太阳使用透明纹理,不会遮挡摄像机 else: @@ -37,18 +38,12 @@ class EarthSeasonsSimBase(UniverseSimScenes): self.look_at_earth = look_at_earth self.show_china = show_china self.show_name = show_name + self.delay_run = delay_run self.exit_at_total_days = exit_at_total_days # 在 4 个节气的位置创建固定不动的透明地球 - 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_1, self.earth_2, self.earth_3, self.earth_4 = self.create_important_pos_earths() # 运动的地球 - self.earth, self.earth_clouds, self.earth_cn = create_earth(earth_texture="earth-huge.jpg", - earth_cn_texture="earth-huge-cn.png", - with_clouds=True, earth_rotation_speed=0.7, - clouds_rotation_speed=0.78, - earth_cn_size_factor=earth_cn_size_factor, - earth_clouds_size_factor=earth_clouds_size_factor) + self.earth, self.earth_clouds, self.earth_cn = self.create_earth(earth_cn_size_factor, earth_clouds_size_factor) # 地球立春的位置和速度 self.earth.init_position = [-9.1507536e+07, 0.0000000e+00, 1.1907757e+08] @@ -73,6 +68,19 @@ class EarthSeasonsSimBase(UniverseSimScenes): # 中国农历24节气表,数据为 节气名称 和 camera.rotation_y 的角度范围值 self.solar_terms_angles = get_solar_terms_angles() + def create_important_pos_earths(self): + return create_important_pos_earths(texture="earth-huge.jpg", + size_scale=4.9e3, + position_offset=1.0) + + def create_earth(self, earth_cn_size_factor, earth_clouds_size_factor): + return create_earth(earth_texture="earth-huge.jpg", + earth_cn_texture="earth-huge-cn.png", + with_clouds=True, earth_rotation_speed=0.7, + clouds_rotation_speed=0.78, + earth_cn_size_factor=earth_cn_size_factor, + earth_clouds_size_factor=earth_clouds_size_factor) + def on_ready(self): # 将 4 个节气位置的地球进行旋转,让中国面对太阳 self.earth_1.planet.rotation_y += 115 # 春分 @@ -156,9 +164,10 @@ class EarthSeasonsSimBase(UniverseSimScenes): self.wait_days_count = 0 application.paused = False - import threading - application.paused = True - threading.Thread(target=delay_app_start).start() + if self.delay_run: + import threading + application.paused = True + threading.Thread(target=delay_app_start).start() # invoke(lambda: app_start, delay=3.0) def earth_text_display(self, term_name): @@ -174,13 +183,18 @@ class EarthSeasonsSimBase(UniverseSimScenes): else: e.name_text.enabled = True + def exit_handle(self): + exit(0) + def on_timer_changed(self, time_data: TimeData): if self.show_china and self.wait_days_count > 0: self.wait_days_count = self.wait_days - time_data.total_days if time_data.total_days > self.exit_at_total_days: - exit(0) + if self.exit_handle(): + return + if self.look_at_earth: # 摄像机始终看向移动的地球 camera_look_at(self.earth, rotation_z=0) @@ -199,7 +213,7 @@ class EarthSeasonsSimBase(UniverseSimScenes): # print(camera.rotation_y) - def run(self, init_position=(0, 0, 0), speed_factor=1.0): + def run(self, dt=None, init_position=(0, 0, 0), speed_factor=1.0, **kwargs): self.speed_factor = speed_factor # 订阅事件后,上面2个函数功能才会起作用 # 运行前会触发 on_ready @@ -208,13 +222,15 @@ class EarthSeasonsSimBase(UniverseSimScenes): UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) # 设置计时器的最小时间单位为天 BodyTimer().min_unit = BodyTimer.MIN_UNIT_DAYS + if dt is None: + dt = SECONDS_PER_DAY * speed_factor # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- - ursina_run(self.bodies, SECONDS_PER_DAY * speed_factor, + ursina_run(self.bodies, dt, position=init_position, # 摄像机和太阳是相同位置 show_name=self.show_name, show_grid=False, cosmic_bg='', # show_timer=True, - timer_enabled=True) + timer_enabled=True, **kwargs) diff --git a/sim_scenes/featured/earth_seasons_live.py b/sim_scenes/featured/earth_seasons_live.py new file mode 100644 index 0000000..994cc9b --- /dev/null +++ b/sim_scenes/featured/earth_seasons_live.py @@ -0,0 +1,146 @@ +# -*- 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 Sun, Earth, Moon +from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time +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 + + +class EarthSeasonsSimLive(EarthSeasonsSimBase): + def __init__(self): + super(EarthSeasonsSimLive, self).__init__(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.moon = Moon(name="月球", size_scale=5e3, + rotation_speed=0.645 + ) # 月球 + self.bodies.append(self.moon) + + for body in self.bodies: + if isinstance(body, Earth): + body.rotate_angle -= 22 + body.set_resolution(50) + + 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_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() + + 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) + + def set_bodies_position(self, time_data: TimeData): + """ + 设置天体的位置(包含速度和加速度的信息) + @param time_data: + @return: + """ + 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', + } + + dt = conv_to_astropy_time(self.start_time) + bodies = [] + year = int(dt.jyear) + for body in self.bodies: + jieqir = 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) + else: + bodies.append(body) + + t = dt + time_data.total_days + set_solar_system_celestial_position(bodies, t, True, recalc_moon_pos_scale=200) + + 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.05, 0.48), (-0.05, 0.1), + text = Text(text="太阳视角:观察日食月食", color=color.white, scale=2, position=position, # (-0.98, 0.48), + font=font) + + 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, + show_exit_button=False, + show_camera_info=False, + gravity_works=False, + show_control_info=False) -- GitLab