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

Python超人-宇宙模拟器

上级 70bcc5dc
......@@ -6,11 +6,14 @@
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
import time
from bodies import Sun, Jupiter, Earth, Moon
from common.func import calculate_distance
from objs import RockSnow, Rock, create_rock
from common.consts import SECONDS_PER_MONTH, SECONDS_PER_YEAR, AU
from sim_scenes.func import ursina_run, camera_look_at, two_bodies_colliding, create_text_panel, create_sphere_sky
from sim_scenes.universe_sim_scenes import UniverseSimScenes
from simulators.ursina.entities.body_timer import TimeData, BodyTimer
from simulators.ursina.entities.entity_utils import create_directional_light
from simulators.ursina.ursina_config import UrsinaConfig
......@@ -20,7 +23,7 @@ import math
import numpy as np
class JupiterMoonProtectsEarthSim:
class JupiterMoonProtectsEarthSim(UniverseSimScenes):
def __init__(self, comet_num=20):
"""
......@@ -28,11 +31,13 @@ class JupiterMoonProtectsEarthSim:
@param comet_num: 随机生成 comet_num 个石头
"""
self.earth_moon_d = 30000000 # 因为地球放大 2000 倍,为了较好的效果,地月距离要比实际大才行
self.sun_earth_d = 150000000
self.sun_jupiter_d = 320000000
# 分别保存太阳碰撞次数、木星碰撞次数、地球碰撞次数、月球碰撞次数、木星保护次数、月球保护次数
self.colliding_count = [0, 0, 0, 0, 0, 0]
self.sun = Sun(name="太阳", size_scale=0.8e2) # 太阳放大 80 倍,距离保持不变
self.jupiter = Jupiter(name="木星", size_scale=0.6e3, distance_scale=0.7) # 木星放大 600 倍,距离保持不变
self.earth = Earth(name="地球", size_scale=2.5e3) # 地球放大 2000 倍,距离保持不变
self.sun = Sun(name="太阳", size_scale=0.85e2) # 太阳放大 80 倍,距离保持不变
self.jupiter = Jupiter(name="木星", size_scale=0.45e3, ignore_mass=True) # 木星放大 600 倍,距离保持不变
self.earth = Earth(name="地球", size_scale=2.5e3, ignore_mass=True, ) # 地球放大 2000 倍,距离保持不变
self.moon = Moon(name="月球", size_scale=3.5e3, # 月球球放大 3000 倍,为了较好的效果,地月距离要比实际大
init_position=[self.earth_moon_d, 0, AU],
init_velocity=[0, 0, 0],
......@@ -48,16 +53,19 @@ class JupiterMoonProtectsEarthSim:
self.comets = []
self.comet_radius = calculate_distance(self.jupiter.position, self.sun.position) * 1.5
self.comet_radius = self.sun_jupiter_d * 1.5
# calculate_distance(self.jupiter.position, self.sun.position) # * 1.5
for i in range(comet_num):
# 随机生成 comet_num 个石头
comet = self.create_comet(i, gravity_only_for=[self.sun, self.jupiter, self.earth])
comet = self.create_comet(i, gravity_only_for=[self.sun])
# comet = self.create_comet(i, gravity_only_for=[self.sun, self.jupiter, self.earth])
self.bodies.append(comet)
self.comets.append(comet)
# 显示板信息模板
self.colliding_info = "太阳碰撞:%s次(%s)\n\n木星碰撞:%s次(%s)\n\n地球碰撞:%s次(%s)\n\n月球碰撞:%s次(%s)\n\n木星保护:%s次\n\n月球保护:%s次\n\n"
self.colliding_info = "陨石碰撞(次数)\n\n - 太阳: %s次(%s)\n\n - 木星: %s次(%s)\n\n - 地球: %s次(%s)\n\n - 月球: %s次(%s)" \
"\n\n保护地球(次数)\n\n - 木星: %s次\n\n - 月球: %s次\n\n"
def random_pos_vel(self):
sun_pos = self.sun.position
......@@ -119,8 +127,26 @@ class JupiterMoonProtectsEarthSim:
pz = self.earth_moon_d * np.sin(angle)
self.moon.position = [self.earth.position[0] + px, 0, self.earth.position[2] + pz]
def set_planet_position(self, planet, time_data, month_per_year, d):
# 1个月有29.5天
days_per_month = 29.5 * month_per_year
# 1天多少角度
angle_per_day = 360 / days_per_month
# 当前天数的角度(度)
angle = time_data.total_days * angle_per_day
# 当前天数的角度(弧度)
angle = angle * np.pi / 180
# 计算月亮的坐标(这里没有用到万有引力)
px = d * np.cos(angle)
pz = d * np.sin(angle)
planet.position = [self.sun.position[0] + px, 0, self.sun.position[2] + pz]
def on_timer_changed(self, time_data: TimeData):
self.set_planet_position(self.earth, time_data, 12, self.sun_earth_d)
self.set_planet_position(self.jupiter, time_data, 12 * 11.8622, self.sun_jupiter_d)
self.set_moon_position(time_data)
# 运行中,每时每刻都会触发
for comet in self.comets:
if comet.planet.enabled:
......@@ -187,18 +213,31 @@ class JupiterMoonProtectsEarthSim:
0, "0.0%",
0, 0)
else:
colliding_info = self.colliding_info % (sun_cnt, str(round(sun_cnt * 100 / total_cnt, 2)) + "%",
jupiter_cnt, str(round(jupiter_cnt * 100 / total_cnt, 2)) + "%",
earth_cnt, str(round(earth_cnt * 100 / total_cnt, 2)) + "%",
moon_cnt, str(round(moon_cnt * 100 / total_cnt, 2)) + "%",
colliding_info = self.colliding_info % (sun_cnt, "%.1f" % (sun_cnt * 100 / total_cnt) + "%",
jupiter_cnt, "%.1f" % (jupiter_cnt * 100 / total_cnt) + "%",
earth_cnt, "%.1f" % (earth_cnt * 100 / total_cnt) + "%",
moon_cnt, "%.1f" % (moon_cnt * 100 / total_cnt) + "%",
j_protected_cnt, m_protected_cnt)
ctime = time.time()
if m_protected_cnt >= 8 and j_protected_cnt >= 2:
if not hasattr(self, "m_protected_8_time"):
self.m_protected_8_time = ctime
else:
if ctime - self.m_protected_8_time > 30:
print("满足条件退出")
exit()
if ctime - self.run_begin_time > 600:
print("没有满足条件退出")
exit()
self.text_panel.text = colliding_info
self.camera_move(time_data)
def camera_move(self, time_data):
from ursina import camera
camera.position += camera.left * 0.1
camera.position += camera.left * 0.01
camera_look_at(self.sun)
def on_ready(self):
......@@ -212,11 +251,11 @@ class JupiterMoonProtectsEarthSim:
0, 0)
camera_look_at(self.sun)
self.sky = create_sphere_sky(scale=8000)
# self.sky.rotation_y = 100
# self.sky.rotation_x = 20
self.sky.rotation_y = -180
self.sky.rotation_x = -20
# self.sky.rotation_z = -65
application.time_scale = 3
self.run_begin_time = time.time()
if __name__ == '__main__':
......@@ -230,7 +269,7 @@ if __name__ == '__main__':
# UrsinaConfig.trail_type = "line"
UrsinaConfig.trail_length = 30
sim = JupiterMoonProtectsEarthSim(comet_num=30)
sim = JupiterMoonProtectsEarthSim(comet_num=50)
# 运行前会触发 on_ready
UrsinaEvent.on_ready_subscription(sim.on_ready)
......@@ -240,8 +279,11 @@ if __name__ == '__main__':
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run(sim.bodies, SECONDS_PER_MONTH * 30,
ursina_run(sim.bodies, SECONDS_PER_MONTH / 6,
position=(AU, AU * 5, -AU * 5),
cosmic_bg='',
show_grid=False,
show_timer=True)
# show_exit_button=False,
show_camera_info=False,
show_control_info=False,
timer_enabled=True)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册