diff --git a/bodies/neptune.py b/bodies/neptune.py index 23647d471f1e9c51f54ac79d516d54b7ebfd67b1..66932bbf87579fdc5c42dd8e6795ec4eaf3059c0 100644 --- a/bodies/neptune.py +++ b/bodies/neptune.py @@ -26,7 +26,7 @@ class Neptune(Body): def __init__(self, name="海王星", mass=1.0241e26, init_position=[0, 0, 30.7 * AU], init_velocity=[-5.43, 0, 0], - texture="neptune.png", size_scale=1.0, distance_scale=1.0, + texture="neptune.jpg", size_scale=1.0, distance_scale=1.0, rotation_speed=22.3463, ignore_mass=False, trail_color=None, show_name=False): params = { "name": name, diff --git a/common/consts.py b/common/consts.py index 01b92b2dd77c3b6f3c1483336d8fa84cbc2d27a7..129353e0519ef6ed0ac4cdee58a527668e33a6fe 100644 --- a/common/consts.py +++ b/common/consts.py @@ -15,6 +15,11 @@ """ MO = 1.9891e30 +""" +1光速=299792.458千米/秒,注意:质量为0才能达到光速 +""" +LIGHT_SPEED = 299792.458 + """ 天文单位 """ diff --git a/sim_scenes/func.py b/sim_scenes/func.py index 32cb2ead4c5048c80168712b4d3e2a1a5ad02a9e..271fac244f535938329524a3743140e504d0b201 100644 --- a/sim_scenes/func.py +++ b/sim_scenes/func.py @@ -11,6 +11,7 @@ from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HALF_DA from common.system import System from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent +from common.consts import LIGHT_SPEED def mayavi_run(bodies, dt=SECONDS_PER_WEEK, @@ -187,15 +188,18 @@ def create_solar_system_bodies(ignore_mass=False, init_velocity=None): return bodies -def create_light(size_scale, init_position): +def create_light_body(size_scale, init_position, speed=LIGHT_SPEED): """ 用天体模拟一个光子 + @param size_scale: 光体的大小 + @param init_position: 光体的初始位置 + @param speed: 光体的速度->1光速=299792.458 千米/秒(km/秒) @return: """ from bodies import Body - return Body(name='光速', mass=0, size_scale=size_scale, color=(255, 255, 0), + return Body(name='光速', mass=0, texture='metal.jpg', size_scale=size_scale, color=(255, 255, 0), init_position=init_position, - init_velocity=[0, 0, 299792.458]).set_light_disable(True) # 1光速=299792.458 千米/秒(km/秒) + init_velocity=[0, 0, speed]).set_light_disable(True) def create_text_panel(width=0.35, height=.5): diff --git a/sim_scenes/solar_system/speed_of_light.py b/sim_scenes/solar_system/speed_of_light.py index cb0fff1cb5f4ff3c52a7c0fe40fa45d5b8e6bde7..542795933860abf32bae8ebf315e4bac6da6b3fa 100644 --- a/sim_scenes/solar_system/speed_of_light.py +++ b/sim_scenes/solar_system/speed_of_light.py @@ -6,102 +6,35 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Sun, Asteroids, Body -from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_YEAR, AU -from sim_scenes.func import ursina_run, create_solar_system_bodies, create_text_panel, create_light -from simulators.ursina.ursina_event import UrsinaEvent -from ursina import camera +from sim_scenes.func import ursina_run, create_solar_system_bodies, create_light_body +from common.consts import LIGHT_SPEED +from sim_scenes.solar_system.speed_of_light_init import SpeedOfLightInit -# 已到达天体列表 -arrived_bodies = [] -text_panel = None -arrived_info = "" +camera_follow_light = None # 摄像机固定,不会跟随光 +camera_follow_light = 'ForwardView' # 摄像机跟随光,方向是向前看 +camera_follow_light = 'SideView' # 摄像机跟随光,方向是侧面看 -CAMERA_FOLLOW_LIGHT = None # 不跟随光 -CAMERA_FOLLOW_LIGHT = 'ForwardView' # 向前看 -CAMERA_FOLLOW_LIGHT = 'SideView' # 侧面看 - - -def on_reset(): - global arrived_info - arrived_bodies.clear() - arrived_info = "[00:00:00] 从 [太阳] 出发\n\n" - if text_panel is not None: - text_panel.text = arrived_info - - -# 订阅重新开始事件 -UrsinaEvent.on_reset_subscription(on_reset) - - -def on_ready(): - global text_panel - text_panel = create_text_panel() - text_panel.text = arrived_info - - if CAMERA_FOLLOW_LIGHT == "SideView": - camera.parent = light_body.planet - camera.rotation_y = -85 - elif CAMERA_FOLLOW_LIGHT == "ForwardView": - light_body.planet.enabled = False - camera.parent = light_body.planet - camera.rotation_y = -15 - - -UrsinaEvent.on_ready_subscription(on_ready) - - -def on_timer_changed(time_text, time_data): - global arrived_info - years, days, hours, minutes, seconds = time_data - for body in bodies: - if body is light_body or isinstance(body, Sun) \ - or body in arrived_bodies or isinstance(body, Asteroids): - # 对于光速天体、太阳、小行星群、“已到达天体列表”中的天体无需计算 - continue - # 计算判断,如果光速天体距离到达了某个天体,就记录到“已到达天体列表”中 - if light_body.position[2] >= body.position[2]: - arrived_bodies.append(body) - if text_panel is not None: - arrived_info += f"[{time_text}]\t到达\t[{body.name}]\n\n" - text_panel.text = arrived_info - print(f"[{time_text}] 到达 [{body.name}]") - - -# 订阅计时器事件(记录已到达天体列表) -UrsinaEvent.on_timer_changed_subscription(on_timer_changed) - -if CAMERA_FOLLOW_LIGHT == "SideView": - # 摄像机位置 = 前-后+、上+下-、左-右+、 - position = (AU, 0, 0) - show_trail = True - light_size_scale = 1e3 - light_init_position = [AU / 3, 0, 0] -elif CAMERA_FOLLOW_LIGHT == "ForwardView": - # 摄像机位置 = 左-右+、上+下-、前+后- - position = (0, AU / 10, -AU) - show_trail = False - light_size_scale = 1e2 - light_init_position = [AU / 12, 0, 0] -else: - # 摄像机位置 = 左-右+、上+下-、前+后- - position = (0, AU, -6 * AU) - show_trail = True - light_size_scale = 2e3 - light_init_position = [AU / 3, 0, 0] +# 实例化一个初始化对象(订阅事件,记录到达每个行星所需要的时间) +init = SpeedOfLightInit(camera_follow_light) # 创建太阳系天体(忽略质量,引力无效,初速度全部为0) bodies = create_solar_system_bodies(ignore_mass=True, init_velocity=[0, 0, 0]) -# 创建一个以光速前进的天体(模拟一个光子,质量为0才能达到光速) -light_body = create_light(light_size_scale, light_init_position) +# 从 init 对象中获取 光体的大小(light_size_scale),光体的位置(light_init_position) +# 创建一个以光速前进的天体(模拟一个光子) speed=1光速=299792.458千米/秒,注意:质量为0才能达到光速,虽然如此,但也可以试试超光速 +light_body = create_light_body(init.light_size_scale, init.light_init_position, speed=LIGHT_SPEED * 1) +# 增加光速天体到天体集合 bodies.append(light_body) +init.bodies = bodies +init.light_body = light_body +init.event_subscription() + # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(bodies, 60, - position=position, - show_trail=show_trail, show_timer=True, + position=init.position, + show_trail=init.show_trail, show_timer=True, # view_closely=True, bg_music="sounds/interstellar.mp3") diff --git a/sim_scenes/solar_system/speed_of_light_init.py b/sim_scenes/solar_system/speed_of_light_init.py new file mode 100644 index 0000000000000000000000000000000000000000..04aa1c70f36638770d004be7b41de98d4e5cf6b5 --- /dev/null +++ b/sim_scenes/solar_system/speed_of_light_init.py @@ -0,0 +1,94 @@ +# -*- coding:utf-8 -*- +# title :在太阳系中以光速运行 +# description :在太阳系中以光速运行 +# author :Python超人 +# date :2023-04-05 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from bodies import Sun, Asteroids, Body +from common.consts import AU +from sim_scenes.func import create_text_panel +from simulators.ursina.ursina_event import UrsinaEvent +from ursina import camera + + +class SpeedOfLightInit: + def __init__(self, camera_follow_light): + """ + @param camera_follow_light: 三种不同的摄像机视角 + None # 摄像机固定,不会跟随光 + ForwardView # 摄像机跟随光,方向是向前看 + SideView # 摄像机跟随光,方向是侧面看 + """ + # 存放记录光体已到达天体列表 + self.arrived_bodies = [] + # 显示消息面板(记录光体已到达天体的时间) + self.text_panel = None + # 显示消息面板的信息(记录光体已到达天体的时间) + self.arrived_info = "" + + self.__camera_follow_light = camera_follow_light + self.light_body = None + self.bodies = None + + if self.__camera_follow_light == "SideView": + # 摄像机位置 = 前-后+、上+下-、左-右+、 + self.position = (AU, 0, 0) + self.show_trail = True + self.light_size_scale = 1e3 + self.light_init_position = [AU / 3, 0, 0] + elif self.__camera_follow_light == "ForwardView": + # 摄像机位置 = 左-右+、上+下-、前+后- + self.position = (0, AU / 10, -AU) + self.show_trail = False + self.light_size_scale = 1e2 + self.light_init_position = [AU / 12, 0, 0] + else: + # 摄像机位置 = 左-右+、上+下-、前+后- + self.position = (0, AU, -6 * AU) + self.show_trail = True + self.light_size_scale = 2e3 + self.light_init_position = [AU / 3, 0, 0] + + # 点击了重置按钮 + def on_reset(self): + self.arrived_bodies.clear() # 重置存放记录光体已到达天体列表 + self.arrived_info = "[00:00:00]\t从 [太阳] 出发\n\n" + if self.text_panel is not None: + self.text_panel.text = self.arrived_info + + def event_subscription(self): + # 订阅重新开始事件 + UrsinaEvent.on_reset_subscription(self.on_reset) + UrsinaEvent.on_ready_subscription(self.on_ready) + # 订阅计时器事件(记录已到达天体列表) + UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) + + def on_ready(self): + self.text_panel = create_text_panel() + self.text_panel.text = self.arrived_info + + if self.__camera_follow_light == "SideView": + camera.parent = self.light_body.planet + camera.rotation_y = -85 + elif self.__camera_follow_light == "ForwardView": + self.light_body.planet.enabled = False + camera.parent = self.light_body.planet + camera.rotation_y = -15 + + def on_timer_changed(self, time_text, time_data): + global arrived_info + years, days, hours, minutes, seconds = time_data + for body in self.bodies: + if body is self.light_body or isinstance(body, Sun) \ + or body in self.arrived_bodies or isinstance(body, Asteroids): + # 对于光速天体、太阳、小行星群、“已到达天体列表”中的天体无需计算 + continue + # 计算判断,如果光速天体距离到达了某个天体,就记录到“已到达天体列表”中 + if self.light_body.position[2] >= body.position[2]: + self.arrived_bodies.append(body) + if self.text_panel is not None: + self.arrived_info += f"[{time_text}]\t到达\t[{body.name}]\n\n" + self.text_panel.text = self.arrived_info + print(f"[{time_text}] 到达 [{body.name}]") diff --git a/simulators/ursina/entities/body_timer.py b/simulators/ursina/entities/body_timer.py index af5763304f2791bf423cf7befe157ccb43b48347..0456bbd60c552aecf3c2de1931c013b364dfa611 100644 --- a/simulators/ursina/entities/body_timer.py +++ b/simulators/ursina/entities/body_timer.py @@ -1,6 +1,6 @@ # -*- coding:utf-8 -*- -# title :计时器天体 -# description :计时器天体 +# title :天体计时器 +# description :天体计时器 # author :Python超人 # date :2023-02-11 # link :https://gitcode.net/pythoncr/ diff --git a/simulators/ursina/entities/sphere_sky.py b/simulators/ursina/entities/sphere_sky.py new file mode 100644 index 0000000000000000000000000000000000000000..e3705f0de647dca44f05a2d3534ab4e16c21f23b --- /dev/null +++ b/simulators/ursina/entities/sphere_sky.py @@ -0,0 +1,20 @@ +# -*- coding:utf-8 -*- +# title :创建一个宇宙网格对象 +# description :创建一个宇宙网格对象 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from ursina import Entity, camera + + +class SphereSky(Entity): + def __init__(self, **kwargs): + super().__init__(name='sky', model='sphere', texture='sky_default', scale=1000, double_sided=True) + self.set_light_off() + for key, value in kwargs.items(): + setattr(self, key, value) + + def update(self): + self.world_position = camera.world_position diff --git a/simulators/ursina/entities/timer.py b/simulators/ursina/entities/timer.py new file mode 100644 index 0000000000000000000000000000000000000000..e68be25fcbe3180ee5c1787c9b36fd6d024999a2 --- /dev/null +++ b/simulators/ursina/entities/timer.py @@ -0,0 +1,37 @@ +# -*- coding:utf-8 -*- +# title :计时器 +# description :计时器 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from ursina import Text, Ursina, application +import datetime + +from simulators.ursina.ursina_config import UrsinaConfig +from simulators.ursina.ursina_event import UrsinaEvent + + +class Timer(Text): + + def __init__(self): + # 创建一个文本对象来显示计时器的时间 + super().__init__(text='00:00', position=(0.65, -0.45), font=UrsinaConfig.CN_FONT) + UrsinaEvent.on_timer_changed_subscription(self.on_timer_changed) + + def on_timer_changed(self, time_text, time_data): + self.text = time_text + + +if __name__ == '__main__': + app = Ursina() + + t = Timer() + + + def update(): + t.update() + + + app.run() diff --git a/simulators/ursina/entities/world_grid.py b/simulators/ursina/entities/world_grid.py new file mode 100644 index 0000000000000000000000000000000000000000..e5f823a7f25f63398143166b24fb8728279c6958 --- /dev/null +++ b/simulators/ursina/entities/world_grid.py @@ -0,0 +1,35 @@ +# -*- coding:utf-8 -*- +# title :创建一个宇宙网格对象 +# description :创建一个宇宙网格对象 +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from ursina import Entity, Grid, color +from simulators.ursina.ursina_mesh import create_arrow_line + + +class WorldGrid(Entity): + """ + 创建一个宇宙网格对象 + """ + + def draw_axises(self): + """ + 画坐标轴 + @return: + """ + + arrow_x, line_x, text_x = create_arrow_line((0, 0, 0), (10, 0, 0), label="X", color=color.red) + arrow_y, line_y, text_y = create_arrow_line((0, 0, 0), (0, 10, 0), label="Y", color=color.green) + arrow_z, line_z, text_z = create_arrow_line((0, 0, 0), (0, 0, 10), label="Z", color=color.yellow) + + def __init__(self): + super().__init__() + s = 120 + grid = Entity(model=Grid(s, s), scale=s * 60, color=color.rgba(255, 255, 255, 20), rotation_x=90, + position=(0, -80, 0)) + grid.set_light_off() + + # self.draw_axises() diff --git a/simulators/ursina_simulator.py b/simulators/ursina_simulator.py index 5ba3eedab1ef753d617b0b1c8b9b7299d1601ad1..77df8fe19bfa4ef205d3d1b710d08dcc0328f702 100644 --- a/simulators/ursina_simulator.py +++ b/simulators/ursina_simulator.py @@ -19,6 +19,8 @@ from simulators.views.ursina_view import UrsinaView from simulators.ursina.ursina_config import UrsinaConfig from simulators.simulator import Simulator from common.system import System +from simulators.ursina.entities.world_grid import WorldGrid +from simulators.ursina.entities.sphere_sky import SphereSky from common.func import find_file import datetime import os @@ -26,44 +28,6 @@ from ursina import EditorCamera from sim_scenes.func import ursina_run -class WorldGrid(Entity): - """ - 创建一个宇宙网格对象 - """ - - def draw_axises(self): - """ - 画坐标轴 - @return: - """ - - arrow_x, line_x, text_x = create_arrow_line((0, 0, 0), (10, 0, 0), label="X", color=color.red) - arrow_y, line_y, text_y = create_arrow_line((0, 0, 0), (0, 10, 0), label="Y", color=color.green) - arrow_z, line_z, text_z = create_arrow_line((0, 0, 0), (0, 0, 10), label="Z", color=color.yellow) - - def __init__(self): - super().__init__() - s = 100 - grid = Entity(model=Grid(s, s), scale=s * 20, color=color.rgba(255, 255, 255, 20), rotation_x=90, - position=(0, -80, 0)) - grid.set_light_off() - - # self.draw_axises() - - -class MySky(Entity): - - def __init__(self, **kwargs): - # from ursina.shaders import unlit_shader - super().__init__(name='sky', model='sphere', texture='sky_default', scale=1000, double_sided=True) - self.set_light_off() - for key, value in kwargs.items(): - setattr(self, key, value) - - def update(self): - self.world_position = camera.world_position - - class UrsinaSimulator(Simulator): """ Ursina官网: https://www.ursinaengine.org/ @@ -181,12 +145,11 @@ class UrsinaSimulator(Simulator): timer = BodyTimer() timer.calc_time(evolve_dt) - - # def create_timer(self): - # from simulators.ursina.entities.timer import Timer - # # 创建一个文本对象来显示计时器的时间 - # self.timer = Timer() - # return self.timer + def create_timer(self): + from simulators.ursina.entities.timer import Timer + # 创建一个文本对象来显示计时器的时间 + self.timer = Timer() + return self.timer def cosmic_background(self, texture='../textures/cosmic2.jpg'): """ @@ -204,7 +167,7 @@ class UrsinaSimulator(Simulator): from ursina import Sky sky = Sky(texture=texture, scale=sky_scale) - # sky = MySky(texture=texture, scale=sky_scale) + # sky = SphereSky(texture=texture, scale=sky_scale) sky.scale = sky_scale # sky.set_shader_input('texture_scale', Vec2(20, 20)) # 一定要够大,如果小于 Sky(texture=texture).scale = 50000,宇宙背景就会出现黑色方洞 @@ -282,8 +245,8 @@ class UrsinaSimulator(Simulator): # ui = UrsinaUI() ctl = ControlUI(ControlHandler(), position=(0.6, 0.5)) - # if show_timer: - # self.create_timer() + if self.show_timer: + self.create_timer() EditorCamera(ignore_paused=True) # 防止打开中文输入法 diff --git a/textures/metal.jpg b/textures/metal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da95e716bd73b7e4e6343ef60969212f9902883b Binary files /dev/null and b/textures/metal.jpg differ