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

Python超人-宇宙模拟器

上级 1a6b7807
......@@ -7,7 +7,7 @@
# python_version :3.8
# ==============================================================================
import random
import sys
from bodies import Earth, Moon
from common.consts import SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH
from sim_scenes.func import ursina_run, camera_look_at
......@@ -17,6 +17,10 @@ from simulators.ursina.ursina_event import UrsinaEvent
def sim_show():
"""
使用模拟器(慢)
@return:
"""
bodies = []
num = 2
r = 30000
......@@ -39,54 +43,80 @@ def sim_show():
def ursina_show():
"""
直接使用 ursina 模拟,无需考虑万有引力(性能高)
@return:
"""
from ursina import Ursina, Entity, color, EditorCamera, camera
app = Ursina()
# 黑色背景的宇宙背景
SphereSky(texture='../../textures/bg_black.png')
# 控制地球的数量,这里的 num 不代表数量
# 地球数量 = num_x * num_y * num_z
num = 5
num_x = num * 2
num_y = num
num_z = num * 2
# 控制运行的速度
run_speed = 0.1
# 控制地球之间的距离
r = 10
def create_sphere(x, y, z):
sphere = Entity(model="sphere", texture='../../textures/earth2.jpg',
def create_earth(x, y, z):
"""
在指定的三维坐标上创建地球
@param x:
@param y:
@param z:
@return:
"""
earth = Entity(model="sphere", texture='../../textures/earth2.jpg',
x=x * r * 2, y=y * r, z=z * r * 2, scale=3)
sphere.name = "%s:%s:%s" % (x, y, z)
earth.name = "%s:%s:%s" % (x, y, z)
def update():
def inner(s, b):
if not hasattr(s, "initial_y"):
s.rotation_y -= 1
# print(s.name, s.rotation_y)
# 随机生成一个地球自转的初始量
s.initial_y = random.randint(20, 200) / 100 * run_speed
# 地球进行自转
s.rotation_y -= s.initial_y
return inner(sphere, y)
return inner(earth, y)
sphere.update = update
earth.update = update
for x in range(-num_x, num_x):
for y in range(-num_y, num_y):
for z in range(-num_z, num_z):
create_sphere(x, y, z)
create_earth(x, y, z)
ed = EditorCamera()
camera.fov = 80
ed.position = [0, 0, r/2]
import sys
# 控制摄像机三个维度的移动方向,值为 1 和 -1
camera.x_d = 1
camera.y_d = 1
camera.z_d = 1
def camera_update():
camera.world_rotation_y += 0.05
camera.world_rotation_z += 0.01
# camera.x += ((random.randint(100, 300) - 100) / 3000) * camera.x_d
camera.y += ((random.randint(100, 300) - 100) / 5000) * camera.y_d
# camera.z += ((random.randint(100, 300) - 100) / 3000) * camera.z_d
# 更新摄像机位置和角度
# 控制摄像机旋转(以y、z轴进行旋转)
camera.world_rotation_y += 0.005
camera.world_rotation_z += 0.001
# 控制摄像机来回移动(x为左右移动,y为上下移动)
camera.x += ((random.randint(100, 300) - 100) / 2500 * run_speed) * camera.x_d
camera.y += ((random.randint(100, 300) - 100) / 5000 * run_speed) * camera.y_d
# camera.z += ((random.randint(100, 300) - 100) / 3000 * run_speed) * camera.z_d
range_val = 5
# if camera.x > range_val:
# camera.x_d = -1
# elif camera.x < -range_val:
# camera.x_d = 1
if camera.x > range_val:
camera.x_d = -1
elif camera.x < -range_val:
camera.x_d = 1
if camera.y > range_val:
camera.y_d = -1
elif camera.y < -range_val:
......
# -*- coding:utf-8 -*-
# title :地月场景模拟(观看月相变化的过程)
# description :地月场景模拟(观看月相变化的过程)
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
from bodies import Sun, Earth, Moon
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, set_camera_parent
from bodies.body import AU
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
import numpy as np
if __name__ == '__main__':
"""
地月场景模拟
"""
# # 地球的Y方向初始速度
# EARTH_INIT_VELOCITY = 0 # 0km/s
# sun = Sun(init_position=[0, 0, AU], size_scale=2e1) # 太阳放大 20 倍
# # 忽略质量的引力
# sun.ignore_mass = True
#
# # 观看月相变化的过程:分别是 新月、蛾眉月、上弦月、盈凸、满月、亏凸、下弦月、残月
# # 参考:images/moon/月相变化过程.jpeg
# # TODO: 月球在摄像机的前方(从 “新月” 开始)
# moon_pos, moon_vel = [0, 0, 384400], [-(EARTH_INIT_VELOCITY + 1.03), 0, 0]
# # TODO: 月球在摄像机的右方(从 “下弦月” 开始),将会从右方出现
# # moon_pos, moon_vel = [384400, 0, 0], [-EARTH_INIT_VELOCITY, 0, 1.03]
# # TODO: 月球在摄像机的左方(从 “上弦月” 开始)
# # moon_pos, moon_vel = [-384400, 0, 0], [EARTH_INIT_VELOCITY, 0, -1.03]
# moon = Moon(init_position=moon_pos, # 距地距离约: 363104 至 405696 km
# init_velocity=moon_vel,
# size_scale=2e1) # 月球放大 20 倍,距离保持不变
# bodies = [
# sun,
# Earth(init_position=[0, 0, 0],
# init_velocity=[0, EARTH_INIT_VELOCITY, 0],
# size_scale=1e1), # 地球放大 10 倍,距离保持不变
# moon
# ]
sun = Sun(name="太阳", size_scale=1e2) # 太阳放大 100 倍,距离保持不变
earth = Earth(name="地球", size_scale=1.8e3) # 地球放大 1800 倍,距离保持不变
earth_moon_d = 20000000 # 因为地球放大 1800 倍,为了较好的效果,地月距离要比实际大才行
moon = Moon(name="月球", size_scale=3e3, # 月球球放大 3000 倍,为了较好的效果,地月距离要比实际大
init_position=[earth_moon_d, 0, AU],
init_velocity=[0, 0, 0],
ignore_mass=True,
rotation_speed=0.4065,
# gravity_only_for_earth=True
)# .set_light_disable(True)
bodies = [
sun, earth, moon
]
def on_timer_changed(time_data: TimeData):
# 显示轨迹,并设置轨迹长度
UrsinaConfig.show_trail = True
UrsinaConfig.trail_length = 500
# 设置运行速度(加速10倍)
UrsinaConfig.run_speed_factor = 10
# 1个月有29.5天
days_per_month = 29.5
# 1天多少角度
angle_per_day = 360 / days_per_month
# 当前天数的角度(度)
angle = time_data.total_days * angle_per_day
# 当前天数的角度(弧度)
angle = angle * np.pi / 180
# 计算月亮的坐标(这里没有用到万有引力)
px = earth_moon_d * np.cos(angle)
pz = earth_moon_d * np.sin(angle)
moon.position = [earth.position[0] + px, 0, earth.position[2] + pz]
def on_ready():
camera_look_at(sun)
# 订阅事件后,上面2个函数功能才会起作用
# 运行前会触发 on_ready
UrsinaEvent.on_ready_subscription(on_ready)
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(on_timer_changed)
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
# position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 4 * AU, 0), show_timer=True)
......@@ -20,7 +20,7 @@ import math
if __name__ == '__main__':
# 目前认为 太阳系 的宜居带范围是从距离太阳0.95个天文单位 (约1.42亿千米)到 2.4个天文单位(约3.59亿千米)的范围为宜居带,
# 其宽度约为2.17亿千米, 按照这个标准,太阳系的宜居带中只有三个大型天体,分别是地球、 月球 以及火星(1.52天文单位)。
sun = Sun(name="太阳", size_scale=0.5e2) # 太阳放大 80 倍,距离保持不变
sun = Sun(name="太阳", size_scale=0.5e2) # 太阳放大 50 倍,距离保持不变
earth = Earth(name="地球", size_scale=1.5e3) # 地球放大 1500 倍,距离保持不变
earth_moon_d = 20000000 # 因为地球放大 1500 倍,为了较好的效果,地月距离要比实际大才行
moon = Moon(name="月球", size_scale=1.5e3,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册