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

Python超人-宇宙模拟器

上级 b6ef713a
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
# title :岩石坠落地球 # title :岩石坠落木星
# description :岩石坠落地球 # description :岩石坠落木星
# author :Python超人 # author :Python超人
# date :2023-04-09 # date :2023-04-09
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Earth, Body from bodies import Jupiter, Body
from objs import RockSnow, Rock, create_rock from objs import RockSnow, Rock, create_rock
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY
from sim_scenes.func import ursina_run, camera_look_at, two_bodies_colliding from sim_scenes.func import ursina_run, camera_look_at, two_bodies_colliding
...@@ -16,47 +16,57 @@ from simulators.ursina.ursina_event import UrsinaEvent ...@@ -16,47 +16,57 @@ from simulators.ursina.ursina_event import UrsinaEvent
if __name__ == '__main__': if __name__ == '__main__':
""" """
岩石坠落地球 岩石坠落木星
""" """
# 地球在中心位置 import random
earth = Earth(init_position=[0, 0, 0], init_velocity=[0, 0, 0],
rotation_speed=0, size_scale=1, texture="earth_hd.jpg")
bodies = [earth] # 木星在中心位置
# 岩石位置和初始速度信息 jupiter = Jupiter(init_position=[0, 0, 0], init_velocity=[0, 0, 0],
infos = [ rotation_speed=0, size_scale=1)
{"position": [0, 0, 10002], "velocity": [4.5, 0, 0]},
{"position": [0, 0, -12000], "velocity": [3.5, 0, 0]}, bodies = [jupiter]
{"position": [0, 8000, 0], "velocity": [4.5, 0, 0]}, rocks = []
{"position": [0, -12002, 0], "velocity": [3.5, 0, 0]}, r = jupiter.raduis
{"position": [0, 18000, 0], "velocity": [3.0, 0, 0]},
{"position": [-20000, 0, 0], "velocity": [0, -2.0, 0]}, for i in range(20):
{"position": [0, 0, 18002], "velocity": [0, 2.5, 0]}, # 随机生成岩石位置和初始速度信息
{"position": [0, 0, -10000], "velocity": [0, 3.3, 0]}, pos = [-r * random.randint(120, 200) / 100,
] -r * random.randint(120, 200) / 1000,
for i, info in enumerate(infos): -r * random.randint(200, 300) / 100]
rock = create_rock(no=i % 7 + 1, name=f'岩石{i + 1}', mass=4.4e10, size_scale=5e2, color=(255, 200, 0), vel = [0, 0, 0]
init_position=info["position"], rock = create_rock(no=i % 7 + 1, name=f'岩石{i + 1}', mass=4.4e10, size_scale=1e3, color=(255, 200, 0),
init_velocity=info["velocity"]) init_position=pos,
info["rock"] = rock gravity_only_for=[jupiter],
init_velocity=vel)
# info["rock"] = rock
bodies.append(rock) bodies.append(rock)
rocks.append(rock)
def on_reset():
for rock in rocks:
rock.set_visible(True)
rock.ignore_mass = False
def on_ready(): def on_ready():
camera_look_at(earth, rotation_z=0) camera_look_at(jupiter, rotation_z=0)
UrsinaConfig.trail_length = 150 UrsinaConfig.trail_length = 150
UrsinaConfig.trail_type = "line" UrsinaConfig.trail_type = "line"
pass
def on_timer_changed(time_data: TimeData): def on_timer_changed(time_data: TimeData):
for obj in bodies: for rock in rocks:
# 循环判断每个抛出物与地球是否相碰撞 if rock.visibled:
if two_bodies_colliding(obj, earth): # 循环判断每个抛出物与木星是否相碰撞
# 如果抛出物与地球相碰撞了,则静止不动(抛出物停止并忽略引力) if two_bodies_colliding(rock, jupiter):
obj.stop_and_ignore_gravity() # 如果岩石与木星相碰撞了,则静止不动(岩石停止并忽略引力)
rock.stop_and_ignore_gravity()
# 岩石爆炸
rock.explode(jupiter)
UrsinaEvent.on_reset_subscription(on_reset)
UrsinaEvent.on_ready_subscription(on_ready) UrsinaEvent.on_ready_subscription(on_ready)
UrsinaEvent.on_timer_changed_subscription(on_timer_changed) UrsinaEvent.on_timer_changed_subscription(on_timer_changed)
...@@ -64,7 +74,7 @@ if __name__ == '__main__': ...@@ -64,7 +74,7 @@ if __name__ == '__main__':
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_HOUR / 6, ursina_run(bodies, SECONDS_PER_HOUR / 6,
position=(30000, 10000, -20000), position=(0, 0, -300000),
show_trail=True, # show_trail=True,
show_timer=True, show_timer=True,
view_closely=0.001) view_closely=0.001)
# https://www.163.com/dy/article/G5F1016F053102ZV.html
# https://www.sciencedirect.com/topics/physics-and-astronomy/lagrangian-points
# 以下是太阳和地球的第一、二、三个拉格朗日点的真实坐标和速度数据:
#
# L1点: 坐标: x = 0.010205 AU, y = 0 AU, z = 0 AU 速度: vx = 0 m/s, vy = 246.593 m/s, vz = 0 m/s
#
# L2点: 坐标: x = -0.010205 AU, y = 0 AU, z = 0 AU 速度: vx = 0 m/s, vy = -246.593 m/s, vz = 0 m/s
#
# L3点: 坐标: x = 0.990445 AU, y = 0 AU, z = 0 AU 速度: vx = 0 m/s, vy = 11.168 m/s, vz = 0 m/s
#
# L4点: 坐标: x = 0.500 AU, y = 0.866025 AU, z = 0 AU 速度: vx = -2446.292 m/s, vy = -1412.901 m/s, vz = 0 m/s
#
# L5点: 坐标: x = 0.500 AU, y = -0.866025 AU, z = 0 AU 速度: vx = -2446.292 m/s, vy = 1412.901 m/s, vz = 0 m/s
#
# 其中,AU表示“天文单位”,即地球与太阳之间的平均距离,约为1.496 x 10^8公里。速度以m/s为单位。
# 这些数据是基于2021年3月的真实数据,并经过了卫星组织、NASA和欧洲航天局等机构的验证。
# AU = 1.496e8
AU = 1
import matplotlib.pyplot as plt
points = [(0.010205 * AU, 0), (-0.010205 * AU, 0),
# (0.990445 * AU, 0),
(0.500 * AU, 0.866025 * AU),
(0.500 * AU, -0.866025 * AU)]
# plt.plot(AU, 0, "r.")
plt.plot(0, 0, "b.")
for x,y in points:
plt.plot(x, y, "g.")
# x = [1, 2, 3, 4]
# y = [2, 4, 2, 6]
# y1 = [e + 1 for e in y]
# y2 = [e + 2 for e in y]
# plt.plot(x, y, "b.") # b:蓝色,.:点
# plt.plot(x, y1, "ro") # r:红色,o:圆圈
# plt.plot(x, y2, "kx") # k:黑色,x:x字符(小叉)
plt.show() # 在窗口显示该图片
#
# import matplotlib.pyplot as plt
#
# # Data from NASA
# L1 = [1.5e6, 0]
# L2 = [-1.5e6, 0]
# L3 = [-1.5e6, 0]
# L4 = [0.5e6, 0.87e6]
# L5 = [0.5e6, -0.87e6]
# sun = [0, 0]
# earth = [0, -1.5e8]
#
# # Create plot and set axis limits
# fig, ax = plt.subplots()
# # ax.set_xlim(-2.5e8, 2.5e8)
# # ax.set_ylim(-2.5e8, 2.5e8)
#
# # Plot positions of Lagrange points, Sun and Earth
# ax.plot(sun[0], sun[1], 'o', markersize=10, color='yellow')
# # ax.plot(earth[0], earth[1], 'o', markersize=5, color='blue')
# ax.plot(L1[0], L1[1], 'x', markersize=10, color='red')
# ax.plot(L2[0], L2[1], 'x', markersize=10, color='green')
# ax.plot(L3[0], L3[1], 'x', markersize=10, color='purple')
# ax.plot(L4[0], L4[1], '+', markersize=10, color='red')
# ax.plot(L5[0], L5[1], '+', markersize=10, color='green')
#
# # Plot labels for Lagrange points, Sun and Earth
# # ax.annotate('Sun', (sun[0]+2e7, sun[1]+2e7))
# # ax.annotate('Earth', (earth[0]+2e7, earth[1]+2e7))
# ax.annotate('L1', (L1[0]+2e7, L1[1]+2e7))
# ax.annotate('L2', (L2[0]+2e7, L2[1]+2e7))
# ax.annotate('L3', (L3[0]+2e7, L3[1]+2e7))
# ax.annotate('L4', (L4[0]+2e7, L4[1]+2e7))
# ax.annotate('L5', (L5[0]+2e7, L5[1]+2e7))
#
# # Set title and show plot
# plt.title('Positions of Lagrange Points L1 to L5, Sun and Earth')
# plt.show()
\ No newline at end of file
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Earth from bodies import Moon, Earth, Body
from objs import create_rock from objs import Football
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_MINUTE from common.consts import SECONDS_PER_HOUR, SECONDS_PER_MINUTE
from sim_scenes.func import ursina_run, get_vector2d_velocity, camera_look_at, two_bodies_colliding from sim_scenes.func import ursina_run, get_vector2d_velocity, camera_look_at, two_bodies_colliding
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
...@@ -25,11 +25,10 @@ def create_ejected_object(velocity, raduis, trail_color, gravity_only_for, angle ...@@ -25,11 +25,10 @@ def create_ejected_object(velocity, raduis, trail_color, gravity_only_for, angle
""" """
# 根据速度、角度获取矢量速度(vx、vy) -> vx² + vy² = velocity² # 根据速度、角度获取矢量速度(vx、vy) -> vx² + vy² = velocity²
vx, vy = get_vector2d_velocity(velocity, angle=angle) vx, vy = get_vector2d_velocity(velocity, angle=angle)
rock = create_rock(name=f'物体速度:{velocity}', mass=500, size_scale=1e3, trail_color=trail_color, football = Football(name=f'物体速度:{velocity}', mass=500, size_scale=1e3, trail_color=trail_color,
init_position=[0, raduis, 0], init_position=[0, raduis, 0],
init_velocity=[vx, vy, 0], init_velocity=[vx, vy, 0], gravity_only_for=[gravity_only_for]) # 仅适用于地球的重力,物体之间重力不要受到影响
gravity_only_for=[gravity_only_for]) # 仅适用于地球的重力,物体之间重力不要受到影响 return football
return rock
if __name__ == '__main__': if __name__ == '__main__':
...@@ -38,8 +37,7 @@ if __name__ == '__main__': ...@@ -38,8 +37,7 @@ if __name__ == '__main__':
""" """
# 地球在中心位置 # 地球在中心位置
earth = Earth(init_position=[0, 0, 0], init_velocity=[0, 0, 0], earth = Earth(init_position=[0, 0, 0], init_velocity=[0, 0, 0],
rotate_angle=0, rotation_speed=0, size_scale=1, rotation_speed=0, texture="earth_hd.jpg")
size_scale=1, texture="earth_hd.jpg")
raduis = earth.raduis + 300 raduis = earth.raduis + 300
# TODO: 4个不同的抛出速度 7.5km/s、8.5km/s、10km/s、11.2km/s(第二宇宙速度) # TODO: 4个不同的抛出速度 7.5km/s、8.5km/s、10km/s、11.2km/s(第二宇宙速度)
# 粉色:velocity = 7.5,飞不出地球太远,就落地 # 粉色:velocity = 7.5,飞不出地球太远,就落地
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# ============================================================================== # ==============================================================================
from sim_scenes.func import ursina_run, create_solar_system_bodies, create_light_ship from sim_scenes.func import ursina_run, create_solar_system_bodies, create_light_ship
from common.consts import LIGHT_SPEED from common.consts import LIGHT_SPEED
from sim_scenes.solar_system.speed_of_light_init import SpeedOfLightInit from sim_scenes.science.speed_of_light_init import SpeedOfLightInit
# TODO: 三种不同的摄像机视角 # TODO: 三种不同的摄像机视角
camera_follow_light = None # 摄像机固定,不会跟随光 camera_follow_light = None # 摄像机固定,不会跟随光
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# 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, Grid, camera, application, color, distance, Audio from ursina import Ursina, window, Entity, Grid, camera, application, color, distance, Audio, Animation
import itertools import itertools
from common.image_utils import find_texture from common.image_utils import find_texture
...@@ -81,7 +81,40 @@ class UrsinaSimulator(Simulator): ...@@ -81,7 +81,40 @@ class UrsinaSimulator(Simulator):
if rotation_z is not None: if rotation_z is not None:
body.planet.rotation_z = rotation_z body.planet.rotation_z = rotation_z
def body_visible(visible):
body.planet.enabled = visible
@property
def body_visibled():
return body.planet.enabled
# Explosion animation
def body_explode(target=None):
# from panda3d.core import GeomUtils
if body.planet.enabled:
body.planet.enabled = False
explosion_file = find_file("images/explosion")
explosion_file = os.path.join(explosion_file, "explosion")
# volume = body.planet.model.volume
volume = pow(body.planet.model.get_bounds().volume, 1 / 3) / 2000
ani = Animation(explosion_file,
position=body.planet.position,
scale=volume * 2, fps=6,
loop=False, autoplay=True)
if target is not None:
if hasattr(target, "planet"):
if hasattr(target.planet, "main_entity"):
ani.look_at(target.planet.main_entity)
else:
ani.look_at(target.planet)
else:
ani.look_at(target)
body.look_at = body_look_at body.look_at = body_look_at
body.set_visible = body_visible
body.explode = body_explode
body.visibled = body_visibled
# def get_bodies_max_distance(self, body_views): # def get_bodies_max_distance(self, body_views):
# max_distance = 0 # max_distance = 0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册