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

Python超人-宇宙模拟器

上级 ce0fe1bb
# -*- 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, Jupiter, Saturn
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
from bodies.body import AU
if __name__ == '__main__':
"""
模拟流浪地球经过木星、土星加速
"""
bodies = [
Jupiter(size_scale=1e2, init_position=[0, AU / 4, 0], init_velocity=[0, 0, 0]), # 木星放大 100 倍
Saturn(size_scale=1e2, init_position=[AU/1.5, 1.5 * AU, 0], init_velocity=[0, 0, 0]), # 土星放大 100 倍
Earth(size_scale=3e2, # 地球放大 300 倍
init_position=[0, 0, 0], #
# init_velocity=[0, 33, -1],
init_velocity=[-1, 10, 0], # 朝向木星的速度为 38km/s,-1 km/s 是为了防止地球正面对着木星冲去
# init_velocity=[0, 50, -1],
),
]
# 使用 mayavi 查看的运行效果
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run(bodies, SECONDS_PER_MONTH, position=(0, AU / 2, -2 * AU), show_trail=True, view_closely=True)
# -*- coding:utf-8 -*-
# title :ursina天体Planet
# description :ursina天体Planet
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import Entity, camera, color, Vec2, Vec3, Vec4, Text, load_texture, destroy, PointLight
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
from common.color_utils import adjust_brightness, conv_to_vec4_color, get_inverse_color
from common.func import find_file
from simulators.views.body_view import BodyView
from simulators.views.ursina_mesh import create_sphere, create_torus
import numpy as np
import math
class Planet(Entity):
def on_reset(self):
# 删除拖尾
self.clear_trails()
self.body_view.body.reset()
def __init__(self, body_view: BodyView):
self.body_view = body_view
self.rotation_speed = self.body_view.body.rotation_speed
self.rotMode = 'x' # random.choice(["x", "y", "z"])
self.name = body_view.name
pos = body_view.position * body_view.body.distance_scale * UrsinaConfig.SCALE_FACTOR
scale = body_view.body.diameter * body_view.body.size_scale * UrsinaConfig.SCALE_FACTOR
self.init_scale = scale
if hasattr(body_view, "texture"):
texture = load_texture(body_view.texture)
# color.white
self.plant_color = color.white
else:
texture = None
b_color = self.body_view.color
if len(b_color) == 3:
b_color = (b_color[0], b_color[1], b_color[2], 1.0)
self.plant_color = color.rgba(*b_color)
if hasattr(self.body_view.body, "torus_stars"):
# 创建一个星环小天体群(主要模拟小行星群,非一个天体)
model = create_torus(0.83, 1.05, 64, 1)
rotation = (90, 0, 0)
else:
# 创建一个天体
subdivisions = 32
if self.body_view.body.resolution is not None:
subdivisions = self.body_view.body.resolution
model = create_sphere(0.5, subdivisions)
rotation = (0, 0, 0)
UrsinaEvent.on_reset_subscription(self.on_reset)
super().__init__(
# model="sphere",
model=model,
scale=scale,
texture=texture,
color=self.plant_color,
position=pos,
rotation=rotation,
double_sided=True
)
if hasattr(self.body_view.body, "torus_stars"):
# 星环小天体群(主要模拟小行星群,非一个天体)
self.set_light_off()
self.double_sided = True
else:
# 一个天体
# 拖尾球体的初始化
self.trail_init()
if self.body_view.body.is_fixed_star:
# 如果是恒星,开启恒星的发光的效果、并作为灯光源
self.create_fixed_star_lights()
elif self.body_view.body.light_disable:
# 如果是非恒星,并且禁用灯光
self.set_light_off()
if self.body_view.body.show_name:
self.create_name_text()
def create_name_text(self):
b_color = self.body_view.color
self.name_text = Text(self.body_view.body.name, scale=1, billboard=True, parent=self,
font=UrsinaConfig.CN_FONT, background=True,
origin=(0, 0))
self.name_text.background.color = color.rgba(b_color[0], b_color[1], b_color[2], 0.3)
# self.name_text.scale = self.scale
inverse_color = get_inverse_color(b_color)
self.name_text.color = color.rgba(inverse_color[0], inverse_color[1], inverse_color[2], 1)
def trail_init(self):
"""
拖尾球体的初始化
:return:
"""
# 存放拖尾球体
self.trails = {}
# 根据天体的颜色获取拖尾的颜色
trail_color = conv_to_vec4_color(self.body_view.body.trail_color)
trail_color = adjust_brightness(trail_color, 0.4)
self.trail_color = color.rgba(trail_color[0], trail_color[1], trail_color[2], 0.6)
# 拖尾球体的大小为该天体的 1/5
self.trail_scale = self.scale_x / 5
if self.trail_scale < 1:
# 如果太小,则
pass
def distance_between_two_points(self, point_a: Vec3, point_b: Vec3) -> float:
# 计算两点在 x、y、z 三个坐标轴上的差值
diff_x = point_a.x - point_b.x
diff_y = point_a.y - point_b.y
diff_z = point_a.z - point_b.z
# 计算两点之间的距离
distance = math.sqrt(diff_x ** 2 + diff_y ** 2 + diff_z ** 2)
return distance
def create_trails(self):
"""
创建拖尾
:return:
"""
# 当前天体的位置
try:
pos = self.position
except Exception as e:
print(self.body_view.body)
self.destroy_all()
return
trails_keys = self.trails.keys()
# 如果有拖尾
if len(trails_keys) > 0:
# 获取最后一个拖尾的位置
last_key = list(trails_keys)[-1]
last_pos = self.trails[last_key]
# 获取拖尾与当前天体的位置
last_pos_distance = self.distance_between_two_points(pos, last_pos)
self_pos_distance = self.distance_between_two_points(pos, self.position)
# # 如果拖尾在天体的内部也不要生成
# if self_pos_distance < self.scale_x + (self.trail_scale / 2):
# pass
# 如果位置比较近,就不创建拖尾了,保证拖尾间隔一定的距离
if last_pos_distance < self.trail_scale * 1.2: # 间隔距离不小于1.2倍的拖尾球体
return
# 创建拖尾球体,并作为字典的key,存放拖尾球体的位置
self.trails[self.create_trail(pos)] = pos
# 计算拖尾球体超过的数量
trail_overflow_count = len(self.trails) - UrsinaConfig.trail_length
if trail_overflow_count > 0:
# 如果拖尾球体超过的数量,就删除之前的拖尾球体
for entity, pos in self.trails.items():
destroy(entity)
trail_overflow_count -= 1
if trail_overflow_count <= 0:
break
def create_trail(self, pos):
"""
在天体当前的位置创建一个拖尾球体
:param pos:
:return:
"""
# sphere = create_sphere(1,6) diamond sphere
trail = Entity(model='sphere', color=self.trail_color, scale=self.trail_scale, position=pos)
trail.set_light_off()
# trail.set_color_off()
# trail.set_color_scale_off()
# trail.enabled = False
return trail
def turn(self):
if hasattr(self.body_view.body, "torus_stars"):
# 星环小天体群(主要模拟小行星群,非一个天体)不受 body_size_factor 影响
self.scale = self.init_scale
else:
self.scale = self.init_scale * UrsinaConfig.body_size_factor
pos = self.body_view.position * UrsinaConfig.SCALE_FACTOR
if self.body_view.body.parent is None:
self.x = -pos[1]
self.y = pos[2]
self.z = pos[0]
else:
self.follow_parent()
dt = 0
if hasattr(self.body_view.body, "dt"):
dt = self.body_view.body.dt
if self.rotation_speed is None or dt == 0:
self.rotspeed = 0
# 旋转速度和大小成反比(未使用真实数据)
# self.rotspeed = 30000 / self.body_view.raduis # random.uniform(1.0, 2.0)
else:
# 是通过月球保持一面面对地球,调整得到
self.rotspeed = self.rotation_speed * (dt / 3600) / 2.4 * \
UrsinaConfig.ROTATION_SPEED_FACTOR * UrsinaConfig.body_spin_factor
# rotation_speed 度/小时 dt 秒 = (dt / 3600)小时
# if self.rotation_y < 0:
# self.rotation_y += 360
try:
# 天体旋转
self.rotation_y -= self.rotspeed
except Exception as e:
print(self.body_view.body)
self.destroy_all()
return
# 如果有行星环
if hasattr(self, "ring"):
# 如果有行星环,则不让行星环跟随行星转动
self.ring.rotation = -Vec3(self.rotation_x - self.ring_rotation_x,
self.rotation_y,
self.rotation_z)
if UrsinaConfig.show_trail:
# 有时候第一个位置不正确,所以判断一下有历史记录后在创建
if len(self.body_view.body.his_position()) > 1:
self.create_trails()
else:
self.clear_trails()
if hasattr(self, "name_text"):
d = (camera.world_position - self.name_text.world_position).length()
if d < pow(self.scale_x, 1.02) * 1.2:
self.name_text.visible = False
else:
self.name_text.visible = True
# print(d, self.name_text.text, self.scale_x ,self.scale_x*1.23)
# # 计算相机和实体之间的距离
# distance = (camera.world_position - self.world_position).length()
# # 根据距离设置文本缩放比例
# self.name_text.scale = distance / 10
def follow_parent(self):
if not hasattr(self, "f_parent"):
if not hasattr(self.body_view, "bodies_system"):
return
sys = self.body_view.bodies_system
for b in sys.bodies:
if self.body_view.body.parent == b:
self.f_parent = b
break
pos = self.f_parent.position * UrsinaConfig.SCALE_FACTOR
self.x = -pos[1]
self.y = pos[2]
self.z = pos[0]
def create_fixed_star_lights(self):
"""
创建恒星的发光的效果、并作为灯光源
:param entity:
:return:
"""
# 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
self.set_light_off()
# lights = []
# # 创建多个新的 Entity 对象,作为光晕的容器
# _color = color.rgba(1.0, 0.6, 0.2, 1)
if hasattr(self.body_view.body, "glows"):
# glows = (glow_num:10, glow_scale:1.03 glow_alpha:0.1~1)
glows = self.body_view.body.glows
if glows is not None:
if isinstance(glows, tuple):
if len(glows) == 3:
glow_num, glow_scale, glow_alpha = glows
elif len(glows) == 2:
glow_num, glow_scale = glows
glow_alpha = None
else:
glow_num = glows
glow_scale = 1.02
glow_alpha = None
if glow_num > 0:
glow_alphas = [0, 0.5, 0.4, 0.3, 0.2, 0.1]
if glow_alpha is None:
if glow_num < len(glow_alphas) - 1:
glow_alpha = glow_alphas[glow_num]
else:
glow_alpha = glow_alphas[-1]
# _color = color.white
_color = self.body_view.body.color
_color = color.rgba(_color[0] / 255, _color[1] / 255, _color[2] / 255, 1)
for i in range(glow_num):
glow_entity = Entity(parent=self, model='sphere', color=_color,
scale=math.pow(glow_scale, i + 1), alpha=glow_alpha)
if hasattr(self.body_view.body, "light_on"):
if self.body_view.body.light_on:
for i in range(2):
# 创建 PointLight 对象,作为恒星的灯光源
light = PointLight(parent=self, intensity=10, range=10, color=color.white)
def create_rings(self):
"""
创建行星环(使用土星贴图)
:return:
"""
rings_texture = 'textures/saturnRings.jpg'
rings_texture = find_file(rings_texture)
# 行星环偏移角度
# self.ring_rotation_x = 80
# 创建行星环
# self.ring = Entity(parent=self.planet, model='circle', texture=rings_texture, scale=3.5,
# rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
# 行星环偏移角度
self.ring_rotation_x = 80
# 创建行星环
torus = create_torus(0.7, 1.2, 64)
self.ring = Entity(parent=self, model=torus, texture=rings_texture, scale=1,
rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
# 设置行星环不受灯光影响,否则看不清行星环
self.ring.set_light_off()
def clear_trails(self):
if not hasattr(self, "trails"):
return
# 删除拖尾
for entity, pos in self.trails.items():
destroy(entity)
self.trails.clear()
def destroy_all(self):
# 从天体系统中移除自己(TODO:暂时还不能移除)
# self.body_view.bodies_system.bodies.remove(self.body_view.body)
# 删除拖尾
self.clear_trails()
# 如果有行星环,则删除行星环
if hasattr(self, "ring"):
destroy(self.ring)
self.body_view.body.appeared = False
self.body_view.appeared = False
# 最后删除自己
destroy(self)
# -*- coding:utf-8 -*-
# title :UrsinaPlayer
# description :UrsinaPlayer
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import camera, color, mouse, Vec2, Vec3, Vec4, Text
from ursina.prefabs.first_person_controller import FirstPersonController
from simulators.ursina.ursina_config import UrsinaConfig
import numpy as np
class UrsinaPlayer(FirstPersonController):
"""
"""
# body_rotation_speed_control = 1.0
def __init__(self, position, view_azimuth=0, targets=None):
super().__init__()
# camera.fov = 2000 # 100
# camera.rotation_y = 90
self.planets = None
if targets is not None:
self.planets = []
# targets = [view.planet.parent for view in targets]
# targets_parent = Entity()
for view in targets:
# view.planet.parent = targets_parent
self.planets.append(view.planet)
# self.camera_adj(planets)
# # planets.append(view.planet)
#
# camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20)))
pos = np.array(position) * UrsinaConfig.SCALE_FACTOR
self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机位置设置为 x=0、y=1、z=0 的位置
camera.position = Vec3(pos[0], pos[1], pos[2])
# self.x = 90
# self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度
# self.rotation = Vec3(45, 90, 0)
# camera.look_at(Vec3(0, 0, 0))
# camera.world_rotation = Vec3(0, 190, 190)
# camera.enabled = True
# self.gravity = 0
# self.vspeed = 400
# self.speed = 1000
# self.mouse_sensitivity = Vec2(160, 160)
# self.on_enable()
# self.rotation_speed = 80
self.on_disable() # 防止鼠标被窗口锁定
# def input(self, key):
# if key == "escape":
# if mouse.locked:
# self.on_disable()
# else:
# sys.exit()
# return super().input(key)
...@@ -224,7 +224,8 @@ class ControlHandler(EventHandler): ...@@ -224,7 +224,8 @@ class ControlHandler(EventHandler):
elif key == 'space': elif key == 'space':
self.ui.enabled = not self.ui.enabled self.ui.enabled = not self.ui.enabled
elif key == 'left mouse down': elif key == 'left mouse down':
print(key) # print(key)
pass
elif key == 'y': # 寻找天体 elif key == 'y': # 寻找天体
if hasattr(self, "search_bodies_button_list"): if hasattr(self, "search_bodies_button_list"):
if self.search_bodies_button_list.enabled: if self.search_bodies_button_list.enabled:
......
...@@ -16,7 +16,8 @@ from simulators.ursina.ursina_event import UrsinaEvent ...@@ -16,7 +16,8 @@ from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ui.control_ui import ControlUI from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ui.control_handler import ControlHandler from simulators.ursina.ui.control_handler import ControlHandler
from simulators.views.ursina_view import UrsinaView, UrsinaPlayer from simulators.views.ursina_view import UrsinaView
from simulators.ursina.entities.ursina_player import UrsinaPlayer
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
from simulators.simulator import Simulator from simulators.simulator import Simulator
from common.system import System from common.system import System
......
...@@ -7,416 +7,13 @@ ...@@ -7,416 +7,13 @@
# 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, SmoothFollow, Texture, clamp, time, \
camera, color, mouse, Vec2, Vec3, Vec4, Text, \
load_texture, held_keys, destroy, PointLight
from ursina.prefabs.first_person_controller import FirstPersonController
import sys
from bodies import Body from bodies import Body
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
from common.color_utils import adjust_brightness, conv_to_vec4_color, get_inverse_color
from common.func import find_file
from simulators.views.body_view import BodyView from simulators.views.body_view import BodyView
from simulators.views.ursina_mesh import create_sphere, create_torus from simulators.ursina.entities.planet import Planet
import numpy as np import numpy as np
import math import math
class UrsinaPlayer(FirstPersonController):
"""
"""
# body_rotation_speed_control = 1.0
def __init__(self, position, view_azimuth=0, targets=None):
super().__init__()
# camera.fov = 2000 # 100
# camera.rotation_y = 90
self.planets = None
if targets is not None:
self.planets = []
# targets = [view.planet.parent for view in targets]
# targets_parent = Entity()
for view in targets:
# view.planet.parent = targets_parent
self.planets.append(view.planet)
# self.camera_adj(planets)
# # planets.append(view.planet)
#
# camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20)))
pos = np.array(position) * UrsinaConfig.SCALE_FACTOR
self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机位置设置为 x=0、y=1、z=0 的位置
camera.position = Vec3(pos[0], pos[1], pos[2])
# self.x = 90
# self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度
# self.rotation = Vec3(45, 90, 0)
# camera.look_at(Vec3(0, 0, 0))
# camera.world_rotation = Vec3(0, 190, 190)
# camera.enabled = True
# self.gravity = 0
# self.vspeed = 400
# self.speed = 1000
# self.mouse_sensitivity = Vec2(160, 160)
# self.on_enable()
# self.rotation_speed = 80
self.on_disable() # 防止鼠标被窗口锁定
# def input(self, key):
# if key == "escape":
# if mouse.locked:
# self.on_disable()
# else:
# sys.exit()
# return super().input(key)
class Planet(Entity):
def on_reset(self):
# 删除拖尾
self.clear_trails()
self.body_view.body.reset()
def __init__(self, body_view: BodyView):
self.body_view = body_view
self.rotation_speed = self.body_view.body.rotation_speed
self.rotMode = 'x' # random.choice(["x", "y", "z"])
self.name = body_view.name
pos = body_view.position * body_view.body.distance_scale * UrsinaConfig.SCALE_FACTOR
scale = body_view.body.diameter * body_view.body.size_scale * UrsinaConfig.SCALE_FACTOR
self.init_scale = scale
if hasattr(body_view, "texture"):
texture = load_texture(body_view.texture)
# color.white
self.plant_color = color.white
else:
texture = None
b_color = self.body_view.color
if len(b_color) == 3:
b_color = (b_color[0], b_color[1], b_color[2], 1.0)
self.plant_color = color.rgba(*b_color)
if hasattr(self.body_view.body, "torus_stars"):
# 创建一个星环小天体群(主要模拟小行星群,非一个天体)
model = create_torus(0.83, 1.05, 64, 1)
rotation = (90, 0, 0)
else:
# 创建一个天体
subdivisions = 32
if self.body_view.body.resolution is not None:
subdivisions = self.body_view.body.resolution
model = create_sphere(0.5, subdivisions)
rotation = (0, 0, 0)
UrsinaEvent.on_reset_subscription(self.on_reset)
super().__init__(
# model="sphere",
model=model,
scale=scale,
texture=texture,
color=self.plant_color,
position=pos,
rotation=rotation,
double_sided=True
)
if hasattr(self.body_view.body, "torus_stars"):
# 星环小天体群(主要模拟小行星群,非一个天体)
self.set_light_off()
self.double_sided = True
else:
# 一个天体
# 拖尾球体的初始化
self.trail_init()
if self.body_view.body.is_fixed_star:
# 如果是恒星,开启恒星的发光的效果、并作为灯光源
self.create_fixed_star_lights()
elif self.body_view.body.light_disable:
# 如果是非恒星,并且禁用灯光
self.set_light_off()
if self.body_view.body.show_name:
self.create_name_text()
def create_name_text(self):
b_color = self.body_view.color
self.name_text = Text(self.body_view.body.name, scale=1, billboard=True, parent=self,
font=UrsinaConfig.CN_FONT, background=True,
origin=(0, 0))
self.name_text.background.color = color.rgba(b_color[0], b_color[1], b_color[2], 0.3)
# self.name_text.scale = self.scale
inverse_color = get_inverse_color(b_color)
self.name_text.color = color.rgba(inverse_color[0], inverse_color[1], inverse_color[2], 1)
def trail_init(self):
"""
拖尾球体的初始化
:return:
"""
# 存放拖尾球体
self.trails = {}
# 根据天体的颜色获取拖尾的颜色
trail_color = conv_to_vec4_color(self.body_view.body.trail_color)
trail_color = adjust_brightness(trail_color, 0.4)
self.trail_color = color.rgba(trail_color[0], trail_color[1], trail_color[2], 0.6)
# 拖尾球体的大小为该天体的 1/5
self.trail_scale = self.scale_x / 5
if self.trail_scale < 1:
# 如果太小,则
pass
def distance_between_two_points(self, point_a: Vec3, point_b: Vec3) -> float:
# 计算两点在 x、y、z 三个坐标轴上的差值
diff_x = point_a.x - point_b.x
diff_y = point_a.y - point_b.y
diff_z = point_a.z - point_b.z
# 计算两点之间的距离
distance = math.sqrt(diff_x ** 2 + diff_y ** 2 + diff_z ** 2)
return distance
def create_trails(self):
"""
创建拖尾
:return:
"""
# 当前天体的位置
try:
pos = self.position
except Exception as e:
print(self.body_view.body)
self.destroy_all()
return
trails_keys = self.trails.keys()
# 如果有拖尾
if len(trails_keys) > 0:
# 获取最后一个拖尾的位置
last_key = list(trails_keys)[-1]
last_pos = self.trails[last_key]
# 获取拖尾与当前天体的位置
last_pos_distance = self.distance_between_two_points(pos, last_pos)
self_pos_distance = self.distance_between_two_points(pos, self.position)
# # 如果拖尾在天体的内部也不要生成
# if self_pos_distance < self.scale_x + (self.trail_scale / 2):
# pass
# 如果位置比较近,就不创建拖尾了,保证拖尾间隔一定的距离
if last_pos_distance < self.trail_scale * 1.2: # 间隔距离不小于1.2倍的拖尾球体
return
# 创建拖尾球体,并作为字典的key,存放拖尾球体的位置
self.trails[self.create_trail(pos)] = pos
# 计算拖尾球体超过的数量
trail_overflow_count = len(self.trails) - UrsinaConfig.trail_length
if trail_overflow_count > 0:
# 如果拖尾球体超过的数量,就删除之前的拖尾球体
for entity, pos in self.trails.items():
destroy(entity)
trail_overflow_count -= 1
if trail_overflow_count <= 0:
break
def create_trail(self, pos):
"""
在天体当前的位置创建一个拖尾球体
:param pos:
:return:
"""
# sphere = create_sphere(1,6) diamond sphere
trail = Entity(model='sphere', color=self.trail_color, scale=self.trail_scale, position=pos)
trail.set_light_off()
# trail.set_color_off()
# trail.set_color_scale_off()
# trail.enabled = False
return trail
def turn(self):
if hasattr(self.body_view.body, "torus_stars"):
# 星环小天体群(主要模拟小行星群,非一个天体)不受 body_size_factor 影响
self.scale = self.init_scale
else:
self.scale = self.init_scale * UrsinaConfig.body_size_factor
pos = self.body_view.position * UrsinaConfig.SCALE_FACTOR
if self.body_view.body.parent is None:
self.x = -pos[1]
self.y = pos[2]
self.z = pos[0]
else:
self.follow_parent()
dt = 0
if hasattr(self.body_view.body, "dt"):
dt = self.body_view.body.dt
if self.rotation_speed is None or dt == 0:
self.rotspeed = 0
# 旋转速度和大小成反比(未使用真实数据)
# self.rotspeed = 30000 / self.body_view.raduis # random.uniform(1.0, 2.0)
else:
# 是通过月球保持一面面对地球,调整得到
self.rotspeed = self.rotation_speed * (dt / 3600) / 2.4 * \
UrsinaConfig.ROTATION_SPEED_FACTOR * UrsinaConfig.body_spin_factor
# rotation_speed 度/小时 dt 秒 = (dt / 3600)小时
# if self.rotation_y < 0:
# self.rotation_y += 360
try:
# 天体旋转
self.rotation_y -= self.rotspeed
except Exception as e:
print(self.body_view.body)
self.destroy_all()
return
# 如果有行星环
if hasattr(self, "ring"):
# 如果有行星环,则不让行星环跟随行星转动
self.ring.rotation = -Vec3(self.rotation_x - self.ring_rotation_x,
self.rotation_y,
self.rotation_z)
if UrsinaConfig.show_trail:
# 有时候第一个位置不正确,所以判断一下有历史记录后在创建
if len(self.body_view.body.his_position()) > 1:
self.create_trails()
else:
self.clear_trails()
if hasattr(self, "name_text"):
d = (camera.world_position - self.name_text.world_position).length()
if d < pow(self.scale_x, 1.02) * 1.2:
self.name_text.visible = False
else:
self.name_text.visible = True
# print(d, self.name_text.text, self.scale_x ,self.scale_x*1.23)
# # 计算相机和实体之间的距离
# distance = (camera.world_position - self.world_position).length()
# # 根据距离设置文本缩放比例
# self.name_text.scale = distance / 10
def follow_parent(self):
if not hasattr(self, "f_parent"):
if not hasattr(self.body_view, "bodies_system"):
return
sys = self.body_view.bodies_system
for b in sys.bodies:
if self.body_view.body.parent == b:
self.f_parent = b
break
pos = self.f_parent.position * UrsinaConfig.SCALE_FACTOR
self.x = -pos[1]
self.y = pos[2]
self.z = pos[0]
def create_fixed_star_lights(self):
"""
创建恒星的发光的效果、并作为灯光源
:param entity:
:return:
"""
# 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
self.set_light_off()
# lights = []
# # 创建多个新的 Entity 对象,作为光晕的容器
# _color = color.rgba(1.0, 0.6, 0.2, 1)
if hasattr(self.body_view.body, "glows"):
# glows = (glow_num:10, glow_scale:1.03 glow_alpha:0.1~1)
glows = self.body_view.body.glows
if glows is not None:
if isinstance(glows, tuple):
if len(glows) == 3:
glow_num, glow_scale, glow_alpha = glows
elif len(glows) == 2:
glow_num, glow_scale = glows
glow_alpha = None
else:
glow_num = glows
glow_scale = 1.02
glow_alpha = None
if glow_num > 0:
glow_alphas = [0, 0.5, 0.4, 0.3, 0.2, 0.1]
if glow_alpha is None:
if glow_num < len(glow_alphas) - 1:
glow_alpha = glow_alphas[glow_num]
else:
glow_alpha = glow_alphas[-1]
# _color = color.white
_color = self.body_view.body.color
_color = color.rgba(_color[0] / 255, _color[1] / 255, _color[2] / 255, 1)
for i in range(glow_num):
glow_entity = Entity(parent=self, model='sphere', color=_color,
scale=math.pow(glow_scale, i + 1), alpha=glow_alpha)
if hasattr(self.body_view.body, "light_on"):
if self.body_view.body.light_on:
for i in range(2):
# 创建 PointLight 对象,作为恒星的灯光源
light = PointLight(parent=self, intensity=10, range=10, color=color.white)
def create_rings(self):
"""
创建行星环(使用土星贴图)
:return:
"""
rings_texture = 'textures/saturnRings.jpg'
rings_texture = find_file(rings_texture)
# 行星环偏移角度
# self.ring_rotation_x = 80
# 创建行星环
# self.ring = Entity(parent=self.planet, model='circle', texture=rings_texture, scale=3.5,
# rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
# 行星环偏移角度
self.ring_rotation_x = 80
# 创建行星环
torus = create_torus(0.7, 1.2, 64)
self.ring = Entity(parent=self, model=torus, texture=rings_texture, scale=1,
rotation=(self.ring_rotation_x, 0, 0), double_sided=True)
# 设置行星环不受灯光影响,否则看不清行星环
self.ring.set_light_off()
def clear_trails(self):
if not hasattr(self, "trails"):
return
# 删除拖尾
for entity, pos in self.trails.items():
destroy(entity)
self.trails.clear()
def destroy_all(self):
# 从天体系统中移除自己(TODO:暂时还不能移除)
# self.body_view.bodies_system.bodies.remove(self.body_view.body)
# 删除拖尾
self.clear_trails()
# 如果有行星环,则删除行星环
if hasattr(self, "ring"):
destroy(self.ring)
self.body_view.body.appeared = False
self.body_view.appeared = False
# 最后删除自己
destroy(self)
class UrsinaView(BodyView): class UrsinaView(BodyView):
""" """
ursina天体视图(天体效果展示用) ursina天体视图(天体效果展示用)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册