From ad595883e0faa17011c36c69f56501235df9e77c Mon Sep 17 00:00:00 2001 From: march3 Date: Sat, 16 Mar 2024 11:26:00 +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/sci_pop/sun_earth_moon.py | 50 +++- sim_scenes/sci_pop/sun_earth_moon_1.py | 339 +++++++++++++++++++++++++ 2 files changed, 380 insertions(+), 9 deletions(-) create mode 100644 sim_scenes/sci_pop/sun_earth_moon_1.py diff --git a/sim_scenes/sci_pop/sun_earth_moon.py b/sim_scenes/sci_pop/sun_earth_moon.py index b041abf..ad31567 100644 --- a/sim_scenes/sci_pop/sun_earth_moon.py +++ b/sim_scenes/sci_pop/sun_earth_moon.py @@ -16,6 +16,7 @@ from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MON from sim_scenes.func import ursina_run, camera_look_at, create_text_panel, create_sphere_sky from sim_scenes.universe_sim_scenes import UniverseSimScenes from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.entities.circle_line import CircleLine from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.ui.control_ui import ControlUI from simulators.ursina.ursina_config import UrsinaConfig @@ -73,6 +74,8 @@ class SunEarthMoonSim(UniverseSimScenes): if len(self.bodies) == 4: self.bodies = self.bodies[0:3] + # self.create_circle(time_data) + def on_timer_changed(self, time_data): """ @@ -161,8 +164,9 @@ class SunEarthMoonSim(UniverseSimScenes): self.create_orbit_line(self.sun, self.earth, self.start_time, alpha=1) # self.create_orbit_line(self.sun, self.moon, self.start_time, alpha=0.5) - orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1) - orbit_line.rotation_x = 40 + # TODO: 月球轨道 + moon_orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1) + moon_orbit_line.rotation_x = 40 # for body in self.bodies[1:]: # if isinstance(body, Earth): @@ -173,6 +177,32 @@ class SunEarthMoonSim(UniverseSimScenes): # if orbit_line is not None: # self.orbit_lines.append(orbit_line) + def create_circle(self, time_data): + from ursina import Vec3 + month = int(time_data.total_days / 29.5+0.5) + if month == 0: + return + month_name = "month_" + str(month) + if hasattr(self, month_name): + return + setattr(self, month_name, True) + print(month_name) + pos = self.earth.position + pos = Vec3(pos[0] * UrsinaConfig.SCALE_FACTOR, + pos[2] * UrsinaConfig.SCALE_FACTOR, + pos[1] * UrsinaConfig.SCALE_FACTOR) + # pos = Vec3(pos[0],pos[2],pos[1]) + # pos = Vec3(pos[1], pos[2], pos[0]) + # pos = Vec3(pos[2], pos[1], pos[0]) + # pos = Vec3(pos[2], pos[0], pos[1]) + # pos = Vec3(pos[1], pos[0], pos[2]) + pos = pos / 2 + circle_line = CircleLine(position=pos, radius=18.7, segments=30, + thickness=1, # color=self.moon.trail_color, + alpha=1) + circle_line.rotation_x = 65 + circle_line.set_light_off(True) + def init_settings(self): """ 初始化设置 @@ -180,10 +210,11 @@ class SunEarthMoonSim(UniverseSimScenes): """ from ursina import color # 创建天空 - create_sphere_sky(scale=5000) + # create_sphere_sky(scale=5000) # UrsinaConfig.trail_type = "curve_line" UrsinaConfig.trail_type = "line" UrsinaConfig.trail_length = 860 + UrsinaConfig.trail_length = 40 UrsinaConfig.trail_thickness_factor = 2 UrsinaConfig.run_speed_factor = 20 @@ -230,10 +261,10 @@ class SunEarthMoonSim(UniverseSimScenes): # font_scale=2, # font_color=(0, 255, 0), # close_time=-1) - - self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \ - "天数:" + str(round(total_days, 2)) + "\n\n" + \ - "月数:" + str(round(total_days / 29.5, 2)) + if hasattr(self, "text_panel"): + self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \ + "天数:" + str(round(total_days, 2)) + "\n\n" + \ + "月数:" + str(round(total_days / 29.5, 2)) # "运行速度:" + str(UrsinaConfig.run_speed_factor) + "\n" + \ # "天数:" + str(round(total_days, 3)) @@ -269,7 +300,8 @@ class SunEarthMoonSim(UniverseSimScenes): self.create_orbit_lines() # 创建信息显示面板 # self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5) - self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3) + + # self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3) def run(self, start_time='2023-01-01 00:00:00'): self.build_bodies() @@ -289,7 +321,7 @@ class SunEarthMoonSim(UniverseSimScenes): ursina_run(self.bodies, SECONDS_PER_DAY / 24, # position=(0, 3.5 * AU, -AU), # 顶上 - position=(0, 1 * AU, -3.5*AU), + position=(0, 1 * AU, -3.5 * AU), gravity_works=False, cosmic_bg='', show_trail=True, diff --git a/sim_scenes/sci_pop/sun_earth_moon_1.py b/sim_scenes/sci_pop/sun_earth_moon_1.py new file mode 100644 index 0000000..1007c91 --- /dev/null +++ b/sim_scenes/sci_pop/sun_earth_moon_1.py @@ -0,0 +1,339 @@ +# -*- coding:utf-8 -*- +# title :太阳地球月球场景模拟 +# description :太阳地球月球场景模拟(月球始终一面朝向地球、月球对地球的扰动) +# author :Python超人 +# date :2024-03-14 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== + + +from bodies import Sun, Earth, Moon +from common.celestial_data_service import init_bodies_reality_pos_vels, set_solar_system_celestial_position, \ + get_reality_orbit_points +from objs import CoreValagaClas, SciFiBomber, WaterDrop +from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH +from sim_scenes.func import ursina_run, camera_look_at, create_text_panel, create_sphere_sky +from sim_scenes.universe_sim_scenes import UniverseSimScenes +from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.entities.circle_line import CircleLine +from simulators.ursina.entities.entity_utils import create_directional_light +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_orbit_by_points, create_circle_line + + +class SunEarthMoonSim(UniverseSimScenes): + def __init__(self): + self.sun = None + self.moon = None + self.earth = None + self.earth_start = None + self.bodies = None + self.orbit_lines = [] + self.run_finished = False + # 地球自转一圈是23小时56分4秒,公转一圈是365天6小时9分9秒 365.25 + self.earth_revolution_days = 365.25 + (9 * 60 + 9) / 60 / 60 / 24 + + def build_bodies(self): + # region 构建太阳系 + self.sun = Sun(size_scale=6e1, texture="sun_light.jpg") + self.moon = Moon(size_scale=22e2) + self.earth = Earth(size_scale=10e2, show_trail=False) + self.earth_start = Earth(size_scale=9.5e2, show_trail=False, rotation_speed=0) + + self.camera_look = CoreValagaClas(name="摄像机镜头", mass=1e30, color=(111, 140, 255), + init_position=[0, 0, 0], + # init_position=[0, 3.3 * AU, -AU], + init_velocity=[0, 0, 0], + size_scale=1e4).set_ignore_gravity(True) + + self.camera_target = CoreValagaClas(name="摄像机目的", mass=1e30, color=(111, 140, 255), + # init_position=[0, 0, 0], + init_position=[0, 3.3 * AU, -AU], + init_velocity=[0, 0, 0], + size_scale=1e4).set_ignore_gravity(True) + + self.bodies = [self.sun, self.earth, self.moon, self.earth_start, + # self.camera_look, + # self.camera_target + ] + + for body in self.bodies: + body.init_velocity = [0, 0, 0] + + def set_bodies_position(self, time_data: TimeData): + """ + 设置天体的位置(包含速度和加速度的信息) + @param time_data: + @return: + """ + t = self.start_time + time_data.total_days + set_solar_system_celestial_position(self.bodies, t, True) + if len(self.bodies) == 4: + self.bodies = self.bodies[0:3] + + self.create_circle(time_data) + + def on_timer_changed(self, time_data): + """ + + @param time_data: + @return: + """ + if self.run_finished: + # self.earth.planet.rotation_y = self.earth.planet.last_rotation_y + # self.moon.planet.rotation_y = self.moon.planet.last_rotation_y + # self.sun.planet.rotation_y = self.sun.planet.last_rotation_y + return + + from ursina import distance + if time_data.total_days >= self.earth_revolution_days: + self.run_finished = True + # self.earth.planet.rotation_speed = 0 + # self.moon.planet.rotation_speed = 0 + # self.sun.planet.rotation_speed = 0 + # + # self.earth.planet.last_rotation_y = self.earth.planet.rotation_y + # self.moon.planet.last_rotation_y = self.moon.planet.rotation_y + # self.sun.planet.last_rotation_y = self.sun.planet.rotation_y + + UrsinaConfig.run_speed_factor = 0.00001 * 24 + self.update_text_panel(time_data) + return + + dt = time_data.get_datetime(self.start_time) + # if dt.year == self.current_year + 1: + + # TODO: 调试用 + if dt.month < 12: + UrsinaConfig.run_speed_factor = 50 * 24 + elif UrsinaConfig.run_speed_factor > 20 * 24: + UrsinaConfig.run_speed_factor = 20 * 24 + # TODO: 调试用 + + if dt.month >= 12 and dt.day >= 31: + if dt.hour > 20: + UrsinaConfig.run_speed_factor -= 0.00001 * 24 + if UrsinaConfig.run_speed_factor < 0.00001 * 24: + UrsinaConfig.run_speed_factor = 0.00001 * 24 + else: + UrsinaConfig.run_speed_factor -= 0.00001 * 24 + + elif dt.month >= 12 and dt.day >= 28 and UrsinaConfig.run_speed_factor >= 1.1 * 24: + UrsinaConfig.run_speed_factor -= 0.65 * 24 + + # elif dt.month >= 12 :#and dt.day > 20: + # UrsinaConfig.run_speed_factor -= 1 + + UrsinaConfig.run_speed_factor = round(UrsinaConfig.run_speed_factor, 2) + + self.set_bodies_position(time_data) + + self.update_text_panel(time_data) + + # if dt.month >= 12: + # dd = distance(self.earth.position, self.earth_start.position) + # # 225000388 + # if dd < 1000000: + # self.run_finished = True + # self.earth.planet.rotation_speed = 0 + # return + + def create_orbit_line(self, center_body, body, start_time, alpha=0.2): + import math + if not hasattr(body, "orbital_days"): + return None + orbital_days = int(math.ceil(body.orbital_days)) + points = get_reality_orbit_points(type(body).__name__.lower(), + start_time=start_time, + days=orbital_days, + segments=100) + # print(points) + orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color, + alpha=alpha) + return orbit_line + + def create_orbit_lines(self): + """ + 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外) + @return: + """ + # self.moon.orbital_days=27.5 + self.create_orbit_line(self.sun, self.earth, self.start_time, alpha=1) + # self.create_orbit_line(self.sun, self.moon, self.start_time, alpha=0.5) + + # TODO: 月球轨道 + # moon_orbit_line = create_circle_line(parent=self.earth.planet.main_entity, radius=10, thickness=2, color=self.moon.trail_color, alpha=1) + # moon_orbit_line.rotation_x = 40 + + # for body in self.bodies[1:]: + # if isinstance(body, Earth): + # alpha = 0.5 + # else: + # alpha = 0.2 + # orbit_line = self.create_orbit_line(self.sun, body, self.start_time, alpha=alpha) + # if orbit_line is not None: + # self.orbit_lines.append(orbit_line) + + def create_circle(self, time_data): + from ursina import Vec3 + month = int(time_data.total_days / 29.5+0.5) + if month == 0: + return + month_name = "month_" + str(month) + if hasattr(self, month_name): + return + setattr(self, month_name, True) + print(month_name) + pos = self.earth.position + pos = Vec3(pos[0] * UrsinaConfig.SCALE_FACTOR, + pos[2] * UrsinaConfig.SCALE_FACTOR, + pos[1] * UrsinaConfig.SCALE_FACTOR) + # pos = Vec3(pos[0],pos[2],pos[1]) + # pos = Vec3(pos[1], pos[2], pos[0]) + # pos = Vec3(pos[2], pos[1], pos[0]) + # pos = Vec3(pos[2], pos[0], pos[1]) + # pos = Vec3(pos[1], pos[0], pos[2]) + pos = pos / 2 + circle_line = CircleLine(position=pos, radius=18.7, segments=30, + thickness=1, # color=self.moon.trail_color, + alpha=1) + circle_line.rotation_x = 65 + circle_line.set_light_off(True) + + def init_settings(self): + """ + 初始化设置 + @return: + """ + from ursina import color + # 创建天空 + # create_sphere_sky(scale=5000) + # UrsinaConfig.trail_type = "curve_line" + UrsinaConfig.trail_type = "line" + UrsinaConfig.trail_length = 860 + UrsinaConfig.trail_length = 40 + + UrsinaConfig.trail_thickness_factor = 2 + UrsinaConfig.run_speed_factor = 20 + + # camera.clip_plane_near = 0.1 + # camera.clip_plane_far = 51000 + # camera.fov = 60 + + # self.sun.planet.color = color.white + + # application.time_scale = 0.01 + # 摄像机移动 update + # camera_move_update() + # camera_move_to_target_update() + + def show_clock(self, time_data): + """ + 显示时钟 + @param dt: 时间 datetime + @return: + """ + # if self.clock_position_center: + # position, origin = (0, .25), (0, 0), + # else: + from ursina import window + + total_days = round(time_data.total_days, 2) + if total_days > self.earth_revolution_days: + total_days = self.earth_revolution_days + seconds = self.earth_revolution_days * 24 * 60 * 60 + time_data = TimeData(seconds, "seconds", seconds) + + dt = time_data.get_datetime(self.start_time) + # 月球围绕地球转一圈的时间,即月球真正的公转周期是一个恒星月,时间是27.5天 。 + # 而我们一般用从地球上看,月球完成一次朔望更替为一个月,叫一个朔望月,时间是29.5天。 + + aspect_ratio = window.aspect_ratio + position, origin = (0.5 * aspect_ratio - 0.15, -0.45), (-0.05, 0.1), + # 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 hasattr(self, "text_panel"): + self.text_panel.text = "\n日期时间:\n" + dt.strftime('%Y-%m-%d %H:%M') + "\n\n" + \ + "天数:" + str(round(total_days, 2)) + "\n\n" + \ + "月数:" + str(round(total_days / 29.5, 2)) + # "运行速度:" + str(UrsinaConfig.run_speed_factor) + "\n" + \ + # "天数:" + str(round(total_days, 3)) + + def update_text_panel(self, time_data): + """ + 更新文字信息面板 + @param d_sun: + @return: + """ + + # panel_text = "时间" #"\n\n当前速度:%s km/s" % "{:.3f}".format(velocity).rjust(6, "0") + # + # self.text_panel.text = panel_text + self.show_clock(time_data) + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 初始化设置 + self.init_settings() + self.earth_start.planet.alpha = 0.5 + # self.set_window_size((int(1920 * r), int(1080 * r)), False) + # 最大分辨率的高度-1,保证不全屏 + # self.set_window_size((1920, 1079), False) + # self.set_window_size((1920 , 1080 ), False) + camera_look_at(self.sun) + # 显示网格以及坐标线 + # self.show_grid_axises(scale_factor=8) + + # 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外) + self.create_orbit_lines() + # 创建信息显示面板 + # self.text_panel = create_text_panel(font="fonts/sanjixiaozhuanti.ttf", font_scale=1.5) + + # self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3) + + def run(self, start_time='2023-01-01 00:00:00'): + self.build_bodies() + from astropy.time import Time + from datetime import datetime + self.current_year = int(start_time[0:4]) + start_time = Time(datetime.strptime(start_time + '+0800', '%Y-%m-%d %H:%M:%S%z'), + format='datetime') + + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(self.on_ready) + + # init_bodies_reality_pos_vels(self.bodies, start_time) + self.start_time = start_time + ursina_run(self.bodies, + SECONDS_PER_DAY / 24, + # position=(0, 3.5 * AU, -AU), # 顶上 + position=(0, 1 * AU, -3.5 * AU), + gravity_works=False, + cosmic_bg='', + show_trail=True, + # bg_music='sounds/no_glory.mp3', + show_camera_info=False, + # video_recoder=True, + show_control_info=False, + timer_enabled=True, + show_grid=False + ) + + +if __name__ == '__main__': + sim = SunEarthMoonSim() + sim.run() -- GitLab