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

Python超人-宇宙模拟器

上级 9809fe3d
...@@ -21,6 +21,17 @@ def conv_to_vec4_color(colour: tuple, alpha=1): ...@@ -21,6 +21,17 @@ def conv_to_vec4_color(colour: tuple, alpha=1):
elif len(colour) == 4: elif len(colour) == 4:
return Vec4(colour[0], colour[1], colour[2], colour[3]) / 255 return Vec4(colour[0], colour[1], colour[2], colour[3]) / 255
raise Exception("colour错误") raise Exception("colour错误")
# if len(color) == 4:
# r, g, b, a = color
# a = color[3]
# elif len(color) == 3:
# r, g, b = color
# a = alpha
# else:
# r, g, b, a = 1.0, 1.0, 1.0, 1.0
# if r>1 or g>1 or b>1 or isinstance(r,int) or isinstance(g,int) or isinstance(b,int):
# r, g, b = r/255, g/255, b/255
# color = ursina_color.rgba(r, g, b, a)
def adjust_brightness(color, target_brightness: float = 0.6): def adjust_brightness(color, target_brightness: float = 0.6):
......
...@@ -6,67 +6,155 @@ ...@@ -6,67 +6,155 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth, Moon from bodies import Sun, Earth, Mercury, Venus
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH
from sim_scenes.func import mayavi_run, ursina_run, camera_look_at, two_bodies_colliding, set_camera_parent from sim_scenes.func import mayavi_run, ursina_run, camera_look_at, two_bodies_colliding, set_camera_parent
from bodies.body import AU from bodies.body import AU
from simulators.ursina.entities.body_timer import BodyTimer, TimeData from simulators.ursina.entities.body_timer import BodyTimer, TimeData
from simulators.ursina.ui.control_ui import ControlUI 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_event import UrsinaEvent
from ursina import application, camera, Vec3 from ursina import application, camera, Vec3
import math import math
from simulators.ursina.ursina_mesh import create_circle_line
from ursina import color
if __name__ == '__main__': mercury_line = None
""" # 42天到达
地球停止公转,多久到达太阳 venus_line = None
地球如果停止公转,多久能掉入太阳?
https://www.zhihu.com/question/310815418
如果地球停止公转,那它需要多久才会掉进太阳? class EarthOrbitStoppedSim:
https://www.guokr.com/article/440341
"""
# 地球的Y方向初始速度 # 地球的Y方向初始速度
EARTH_INIT_VELOCITY = 0 # 0km/s EARTH_INIT_VELOCITY = 0 # 0km/s
sun = Sun(init_position=[0, 0, 0], size_scale=1)
earth = Earth(init_position=[0, 0, -AU],
init_velocity=[0, EARTH_INIT_VELOCITY, 0],
size_scale=1).set_light_disable(True)
bodies = [
sun,
earth
]
def __init__(self):
self.sun = Sun(init_position=[0, 0, 0], size_scale=1)
self.earth = Earth(init_position=[0, 0, -AU],
init_velocity=[0, self.EARTH_INIT_VELOCITY, 0],
size_scale=1).set_light_disable(True)
self.mercury_radius = 0.384 * AU
self.venus_radius = 0.721 * AU
# 水星: [49311300. 0. 28075956.] [ 24.30735 0. -41.926445]
self.mercury = Mercury(name="水星",
# init_position=[0, 0, self.mercury_radius],
# init_position=[0, 0, -self.mercury_radius], # 和地球同一方向
init_position=[49311300., 0, 28075956.],
init_velocity=[-24.307, 0, 41.9264],
size_scale=1).set_light_disable(True)
# 金星: [-98608848. 0. -42909512.] [-13.869937 0. 32.247845]
self.venus = Venus(name="金星",
# init_position=[0, 0, self.venus_radius],
# init_position=[0, 0, -self.venus_radius], # 和地球同一方向
init_position=[-98608848., 0, -42909512.], # 和地球同一方向
init_velocity=[13.869937, 0, -32.247845],
size_scale=1).set_light_disable(True)
def on_ready(): self.bodies = [
self.sun, self.mercury, self.venus, self.earth
]
self.arrived_sun = None
self.arrived_mercury_orbit_line = None
self.arrived_venus_orbit_line = None
def create_orbit_line(self, radius, color):
orbit_line = create_circle_line(parent=self.sun, radius=radius, thickness=5, color=color, alpha=0.3)
orbit_line.rotation_x = 90
orbit_line.enabled = False
return orbit_line
def on_ready(self):
# 运行前触发 # 运行前触发
application.time_scale = 0.00001 application.time_scale = 0.00001
camera.fov = 50 camera.fov = 50
# 创建水星轨道线
self.mercury_orbit_line = self.create_orbit_line(
radius=self.mercury_radius * UrsinaConfig.SCALE_FACTOR,
color=self.mercury.color)
# 创建金星轨道线
self.venus_orbit_line = self.create_orbit_line(
radius=self.venus_radius * UrsinaConfig.SCALE_FACTOR,
color=self.venus.color)
def on_timer_changed(self, time_data: TimeData):
camera_look_at(self.earth, rotation_z=0)
earth_pos = self.earth.planet.world_position
camera.world_position = Vec3(earth_pos[0], earth_pos[1] + 0.01, earth_pos[2] - 0.1)
def on_timer_changed(time_data: TimeData): # 当地球停止公转,如果没有向外的向心力来抵消向内的引力,地球将开始朝着太阳坠落。
# 据美国康奈尔大学的天文学家戴夫 · 罗斯坦(Dave Rothstein)的计算,
# 地球将在65天后与太阳相撞,期间在第41天穿过金星的轨道,在第57天,我们将穿过水星的轨道
camera_look_at(earth, rotation_z=0) # 地球[41天 07时]到达金星轨道
earth_pos = earth.planet.world_position # 地球[57天 01时]到达水星轨道
camera.world_position = Vec3(earth_pos[0], earth_pos[1] + 0.01, earth_pos[2] - 0.1) # 地球[64天 13时]到达太阳表面
if two_bodies_colliding(sun, earth): if two_bodies_colliding(self.sun, self.earth):
ControlUI.current_ui.show_message("地球已到达太阳表面", close_time=-1) self.arrived_sun = True
msg = "地球[%s]到达太阳表面" % time_data.time_text
print(msg)
ControlUI.current_ui.show_message(msg, close_time=-1)
application.pause() application.pause()
if time_data.days in [40, 41]:
self.venus_orbit_line.enabled = True
else:
self.venus_orbit_line.enabled = False
if time_data.days in [56, 57]:
self.mercury_orbit_line.enabled = True
else:
self.mercury_orbit_line.enabled = False
# if time_data.days in [41, 57, 64]:
# UrsinaConfig.run_speed_factor = 0.1
# else:
# UrsinaConfig.run_speed_factor = 1
if abs(self.earth.position[2]) < 0.721 * AU and not self.arrived_venus_orbit_line:
self.arrived_venus_orbit_line = True
msg = "地球[%s]到达金星轨道" % time_data.time_text
print(msg)
print("金星:", self.venus.position, self.venus.velocity)
ControlUI.current_ui.show_message(msg, close_time=5)
if abs(self.earth.position[2]) < 0.384 * AU and not self.arrived_mercury_orbit_line:
self.arrived_mercury_orbit_line = True
msg = "地球[%s]到达水星轨道" % time_data.time_text
print(msg)
print("水星:", self.mercury.position, self.mercury.velocity)
ControlUI.current_ui.show_message(msg, close_time=5)
if __name__ == '__main__':
"""
地球停止公转,多久到达太阳
地球如果停止公转,多久能掉入太阳?
https://www.zhihu.com/question/310815418
如果地球停止公转,那它需要多久才会掉进太阳?
https://www.guokr.com/article/440341
"""
# 设置计时器的最小时间单位为分钟 # 设置计时器的最小时间单位为分钟
BodyTimer().min_unit = BodyTimer.MIN_UNIT_HOURS BodyTimer().min_unit = BodyTimer.MIN_UNIT_HOURS
sim = EarthOrbitStoppedSim()
# 运行前会触发 on_ready # 运行前会触发 on_ready
UrsinaEvent.on_ready_subscription(on_ready) UrsinaEvent.on_ready_subscription(sim.on_ready)
# 订阅事件后,上面的函数功能才会起作用 # 订阅事件后,上面的函数功能才会起作用
# 运行中,每时每刻都会触发 on_timer_changed # 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(on_timer_changed) UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed)
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
# position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程 # position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0.0001 * AU, -0.002 * AU), ursina_run(sim.bodies, SECONDS_PER_DAY, position=(0, 0.0001 * AU, -0.02 * AU),
show_timer=True, show_timer=True,
show_grid=True) show_grid=True)
# ursina_run(bodies, SECONDS_PER_DAY, position=(0, 2*AU, 0),
# show_timer=True,
# show_grid=True)
...@@ -7,11 +7,15 @@ ...@@ -7,11 +7,15 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina # pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import Ursina, window, Entity, Mesh, EditorCamera, color, mouse, Vec2, Vec3, load_texture, Texture, Text from ursina import Ursina, window, Entity, Mesh, EditorCamera, color, mouse, Vec2, Vec3, load_texture, Texture, Text, \
Cylinder
import ursina.color as ursina_color
from math import pi, sin, cos from math import pi, sin, cos
import numpy as np import numpy as np
import math import math
from common.color_utils import conv_to_vec4_color
from simulators.ursina.entities.circle_line import CircleLine
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
...@@ -115,10 +119,19 @@ def create_circle(parent=None, pos=Vec3(0, 0, 0), thickness=1, scale=1, color=co ...@@ -115,10 +119,19 @@ def create_circle(parent=None, pos=Vec3(0, 0, 0), thickness=1, scale=1, color=co
return circle return circle
def create_circle_line(parent=None, pos=Vec3(0, 0, 0), thickness=1, scale=1, color=color.white, alpha=1): def create_circle_line(parent=None, radius=1, position=None, segments=100, thickness=0.1, color=color.white, alpha=1):
circle = Entity(parent=parent, model="circle", thickness=thickness, scale=scale, position=pos, if isinstance(color, tuple) or isinstance(color, list):
color=color, alpha=alpha) color = conv_to_vec4_color(color)
return circle if alpha < 1:
color[3] = alpha
circle_line = CircleLine(position=position, radius=radius, segments=segments, thickness=thickness, color=color,
alpha=alpha)
if parent is not None:
if hasattr(parent, "planet"):
parent = parent.planet
circle_line.parent = parent
return circle_line
def create_arrow_line(from_pos, to_pos, parent=None, label=None, def create_arrow_line(from_pos, to_pos, parent=None, label=None,
...@@ -395,7 +408,9 @@ if __name__ == '__main__': ...@@ -395,7 +408,9 @@ if __name__ == '__main__':
# arrow = Entity(model=create_arrow(), color=color.yellow) # arrow = Entity(model=create_arrow(), color=color.yellow)
# arrow.set_light_off() # arrow.set_light_off()
arrow, line, text = create_arrow_line((0, 0, 0), (10, 0, 0)) # arrow, line, text = create_arrow_line((0, 0, 0), (10, 0, 0))
create_circle_line()
EditorCamera() EditorCamera()
app.run() app.run()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册