Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Python_超人
宇宙模拟器
提交
013fb2ef
宇宙模拟器
项目概览
Python_超人
/
宇宙模拟器
通知
19
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
宇宙模拟器
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
013fb2ef
编写于
3月 31, 2023
作者:
三月三net
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Python超人-宇宙模拟器
上级
ce0fe1bb
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
464 addition
and
406 deletion
+464
-406
sim_scenes/science/gravity_slingshot_1.py
sim_scenes/science/gravity_slingshot_1.py
+0
-0
sim_scenes/science/gravity_slingshot_2.py
sim_scenes/science/gravity_slingshot_2.py
+35
-0
simulators/ursina/entities/__init__.py
simulators/ursina/entities/__init__.py
+0
-0
simulators/ursina/entities/planet.py
simulators/ursina/entities/planet.py
+359
-0
simulators/ursina/entities/ursina_player.py
simulators/ursina/entities/ursina_player.py
+65
-0
simulators/ursina/ui/control_handler.py
simulators/ursina/ui/control_handler.py
+2
-1
simulators/ursina_simulator.py
simulators/ursina_simulator.py
+2
-1
simulators/views/ursina_view.py
simulators/views/ursina_view.py
+1
-404
未找到文件。
sim_scenes/science/gravity_slingshot.py
→
sim_scenes/science/gravity_slingshot
_1
.py
浏览文件 @
013fb2ef
文件已移动
sim_scenes/science/gravity_slingshot_2.py
0 → 100644
浏览文件 @
013fb2ef
# -*- 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
)
simulators/ursina/entities/__init__.py
0 → 100644
浏览文件 @
013fb2ef
simulators/ursina/entities/planet.py
0 → 100644
浏览文件 @
013fb2ef
# -*- 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
)
simulators/ursina/entities/ursina_player.py
0 → 100644
浏览文件 @
013fb2ef
# -*- 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)
simulators/ursina/ui/control_handler.py
浏览文件 @
013fb2ef
...
...
@@ -224,7 +224,8 @@ class ControlHandler(EventHandler):
elif
key
==
'space'
:
self
.
ui
.
enabled
=
not
self
.
ui
.
enabled
elif
key
==
'left mouse down'
:
print
(
key
)
# print(key)
pass
elif
key
==
'y'
:
# 寻找天体
if
hasattr
(
self
,
"search_bodies_button_list"
):
if
self
.
search_bodies_button_list
.
enabled
:
...
...
simulators/ursina_simulator.py
浏览文件 @
013fb2ef
...
...
@@ -16,7 +16,8 @@ from simulators.ursina.ursina_event import UrsinaEvent
from
simulators.ursina.ui.control_ui
import
ControlUI
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.simulator
import
Simulator
from
common.system
import
System
...
...
simulators/views/ursina_view.py
浏览文件 @
013fb2ef
...
...
@@ -7,416 +7,13 @@
# python_version :3.8
# ==============================================================================
# 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
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
from
simulators.
ursina.entities.planet
import
Planet
import
numpy
as
np
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
):
"""
ursina天体视图(天体效果展示用)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录