提交 4d74c8da 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 52cdfdfa
# -*- 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, distance
from bodies import *
from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, get_body_posvel, \
get_reality_orbit_points
from common.consts import SECONDS_PER_DAY, AU
from common.func import calculate_distance
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.entities.world_grid import WorldGrid
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
from simulators.ursina_simulator import UrsinaSimulator
import numpy as np
import math
class CenterPointMovingSimLive(EarthSeasonsSimBase):
def __init__(self):
super(CenterPointMovingSimLive, self).__init__(sun_transparent=False,
exit_at_total_days=37000,
delay_run=False,
look_at_earth=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 = 5.5e1
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=1.5e3)
self.neptune = Neptune(size_scale=1.5e3)
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 = []
font = "fonts/DroidSansFallback.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.show_trail = False
self.bodies = self.planets
def create_orbit_line(self, center_body, body, start_time, alpha=0.2):
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, thickness=4)
return orbit_line
def create_orbit_lines(self):
"""
创建太阳系天体的真实轨迹(太阳和哈雷彗星除外)
@return:
"""
self.orbit_lines = []
for body in self.planets:
if body is self.sun:
continue
if isinstance(body, Earth):
alpha = 0.5
else:
alpha = 0.2
start_time = conv_to_astropy_time(self.start_time)
orbit_line = self.create_orbit_line(self.sun, body, start_time, alpha=0.8)
if orbit_line is not None:
self.orbit_lines.append(orbit_line)
return self.orbit_lines
def count_days(self, key, time_data, days):
key = "k_" + str(key)
days_counter_key = f"{key}_days_counter"
days_counter_init_val_key = f"{key}_days_counter_init_val"
if not hasattr(self, days_counter_key):
setattr(self, days_counter_key, 0)
setattr(self, days_counter_init_val_key, time_data.total_days)
else:
d = time_data.total_days - getattr(self, days_counter_init_val_key)
setattr(self, days_counter_key, d)
rd = getattr(self, days_counter_key)
if rd >= days:
delattr(self, days_counter_key)
delattr(self, days_counter_init_val_key)
return True
return False
def get_center_pos(self, dt, time_data):
ec = UrsinaSimulator.EditorCamera
d_sun = self.get_distance_sun()
if not hasattr(self, "moving_factor"):
self.moving_factor = 1e-6
self.phase_num = 1
# elif time_data.total_days > 1500 and self.moving_factor < 1:
elif (d_sun < 7 or self.phase_num == 2) and self.moving_factor < 1:
self.moving_factor += 0.01 * UrsinaConfig.run_speed_factor
if self.phase_num == 1:
for b in self.bodies:
from simulators.ursina.entities.entity_utils import clear_trails
clear_trails(b.planet.main_entity)
UrsinaConfig.trail_type = "line"
# UrsinaConfig.trail_length = 91
self.phase_num = 2
if self.moving_factor > 1:
self.moving_factor = 1
if self.phase_num == 2:
for b in self.bodies:
from simulators.ursina.entities.entity_utils import clear_trails
clear_trails(b.planet.main_entity)
UrsinaConfig.trail_type = "curve_line"
UrsinaConfig.trail_length = 500
self.phase_num = 3
e_posvel = get_body_posvel(self.earth, dt)
s_posvel = get_body_posvel(self.sun, dt)
e_position = [e_posvel[0].x.value * AU, e_posvel[0].z.value * AU, e_posvel[0].y.value * AU]
s_position = [s_posvel[0].x.value * AU, s_posvel[0].z.value * AU, s_posvel[0].y.value * AU]
center_pos = np.array(e_position) * self.moving_factor
return center_pos
def on_ready(self):
super(CenterPointMovingSimLive, self).on_ready()
self.sky.rotation_y = 20
self.sky.rotation_x = -290
self.sky.rotation_z = -95
UrsinaConfig.trail_type = "line"
# UrsinaConfig.trail_length = 91
UrsinaConfig.trail_type = "curve_line"
UrsinaConfig.trail_length = 180
# UrsinaConfig.trail_length = 1000
UrsinaConfig.trail_thickness_factor = 4
UrsinaConfig.trail_alpha = 0.8
UrsinaConfig.trail_factor = 4
for body in self.bodies:
body.planet.trail_scale = 0.5
self.moon.planet.trail_scale = 0.5
# WorldGrid().draw_axises(100)
camera.clip_plane_near = 1
camera.look_at(Vec3(0, 0, 0))
destroy(self.earth_clouds.planet)
destroy(self.earth_cn.planet)
self.earth.planet.name_text.enabled = False
self.moon.planet.rotation_y = 180
self.show_title()
# camera.fov = 140
window.borderless = True
window.exit_button = False
# self.window_size()
self.orbit_lines = self.create_orbit_lines()
# def window_size(self):
# # window.fullscreen = True
# # window.position = (1920, 0)
# # self.set_window_size()
# # # # 设置窗口的宽度和高度
# # window.size = (2340, 1079)
# # window.position = (0, 0)
# self.set_window_size((2376, 1080),fullscreen=True)
def hide_orbit_lines(self):
for orbit_line in self.orbit_lines:
destroy(orbit_line)
def on_timer_changed(self, time_data: TimeData):
super(CenterPointMovingSimLive, 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)
_dt = (time_data.dt / 28788)
# print("total_days:", time_data.total_days)
if time_data.total_days > 2800:
exit()
ec = UrsinaSimulator.EditorCamera
if self.phase_num == 1:
ec.world_position += ec.up * 2 * _dt * UrsinaConfig.run_speed_factor # 前进
ec.world_position += ec.back * 1 * _dt * UrsinaConfig.run_speed_factor # 下
elif self.phase_num == 2:
self.hide_orbit_lines()
elif self.phase_num == 3:
if self.count_days(self.phase_num, time_data, 370):
self.phase_num = 4
elif self.phase_num == 4:
ec.world_position -= ec.up * 2* _dt * UrsinaConfig.run_speed_factor # 后退
ec.world_position -= ec.back * 1.4* _dt * UrsinaConfig.run_speed_factor # 下(快一点)
ec.world_position += ec.right * 0.8 * _dt* UrsinaConfig.run_speed_factor # 左
d_sun = self.get_distance_sun()
# print("d_sun:", d_sun)
if d_sun > 48:
self.phase_num = 5
# elif self.phase_num == 5:
# ec.world_position -= ec.back * 1.4* _dt * UrsinaConfig.run_speed_factor # 下
# ec.world_position += ec.right * 0.7* _dt * UrsinaConfig.run_speed_factor # 左
# pos = camera.world_position
# if pos[2] > 2000:
# self.phase_num = 6
# print("pos:", pos)
# if d_sun > 4500:
# ec.target_z -= 0.01
# self.camera_around()
def get_distance_sun(self):
d_sun = distance(camera.world_position, self.sun.planet.world_position)
return round(d_sun / UrsinaConfig.SCALE_FACTOR / AU, 4)
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, time_data)
set_solar_system_celestial_position(self.planets, t, True, recalc_moon_pos_scale=60, center_pos=center_pos)
def exit_handle(self):
UrsinaEvent.on_reset()
return True
def show_title(self):
return
aspect_ratio = window.aspect_ratio
position, origin = (-0.5 * aspect_ratio + 0.02, 0.48), (-0.05, 0.1)
text1 = Text(text="地球为中心的轨道是这样", color=color.white, scale=2, position=position, # (-0.98, 0.48),
font=self.font)
def show_clock(self, dt):
"""
显示时钟
@param dt: 时间 datetime
@return:
"""
# if self.clock_position_center:
# position, origin = (0, .25), (0, 0),
# else:
return
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 = CenterPointMovingSimLive()
sim.run(
dt=SECONDS_PER_DAY * 15,
# dt=SECONDS_PER_DAY * 3,
init_position=[0, -60 * AU, 30 * AU],
show_exit_button=False,
show_camera_info=False,
gravity_works=False,
show_trail=True,
show_control_info=False)
......@@ -26,7 +26,7 @@ class EarthSeasonsSimBase(UniverseSimScenes):
look_at_earth=True,
show_china=True,
exit_at_total_days=375,
earth_cn_size_factor=1.001,
earth_cn_size_factor=1.005,
earth_clouds_size_factor=1.01,
show_name=True,
delay_run=True):
......@@ -75,7 +75,7 @@ class EarthSeasonsSimBase(UniverseSimScenes):
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",
earth_cn_texture="earth-huge-cn-flag.png",
with_clouds=True, earth_rotation_speed=0.7,
clouds_rotation_speed=0.78,
earth_cn_size_factor=earth_cn_size_factor,
......@@ -97,6 +97,7 @@ class EarthSeasonsSimBase(UniverseSimScenes):
self.earth_4.planet.alpha = 0.2
self.earth_cn.planet.rotation_y -= 185 # 一开始就正对太阳
self.earth.planet.rotation_y -= 185 # 一开始就正对太阳
self.earth_clouds.planet.rotation_y -= 50 # 一开始就正对太阳
......
......@@ -10,7 +10,7 @@ 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 SECONDS_PER_DAY, AU
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
......@@ -32,6 +32,7 @@ class EarthSeasonsSimLive(EarthSeasonsSimBase):
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 = 3e1
self.earth.size_scale = 2e3
self.earth_clouds.size_scale = self.earth.size_scale
......@@ -254,8 +255,9 @@ if __name__ == '__main__':
sim = EarthSeasonsSimLive()
sim.run(
# dt=SECONDS_PER_DAY * 10,
# dt=SECONDS_PER_DAY * 3,
init_position=[0, 0, -2 * AU],
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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册