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

Python超人-宇宙模拟器

上级 efbdb7d1
......@@ -795,7 +795,7 @@ def get_run_speed_factor(run_speed_factor=1 / 8):
return run_speed_factor * control_speed_factor
def camera_move_control(camera_move_infos, cond_cb, value_conv=None):
def camera_move_control(camera_move_infos, cond_cb, value_conv=None, smooth=None):
"""
@param camera_move_infos:
......@@ -809,6 +809,7 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None):
@param cond_cb: 条件回调,参数为:
cond:当前条件数据, next_cond:下一个条件数据, idx:当前索引, info:当前信息, next_info:下一个信息
@param value_conv:
@param smooth:
@return:
"""
from ursina import camera, Vec3
......@@ -822,17 +823,57 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None):
return value_conv(val, p_name)
return val
if smooth:
if not hasattr(camera, "last_move_ps"):
camera.last_move_ps = None
for idx, (cond, info) in enumerate(camera_move_infos[:-1]):
next_cond = camera_move_infos[idx + 1][0]
next_info = camera_move_infos[idx + 1][1]
cond_cb_params = {"cond": cond, "next_cond": next_cond, "idx": idx, "info": info, "next_info": next_info}
if cond_cb(cond_cb_params):
p = camera.position
x, y, z = info.get("x", 0), info.get("y", 0), info.get("z", 0)
mis = info.get("f", 0), info.get("b", 0), info.get("l", 0), info.get("r", 0), \
info.get("u", 0), info.get("d", 0)
x, y, z = [info.get("x", 0), info.get("y", 0), info.get("z", 0)]
mis = [info.get("f", 0), info.get("b", 0), info.get("l", 0), info.get("r", 0), \
info.get("u", 0), info.get("d", 0)]
dns = "fblrud"
mas = camera.forward, camera.back, camera.left, camera.right, camera.up, camera.down
update_last_ps = False
if smooth:
if camera.last_move_ps is None:
update_last_ps = True
else:
ps = [x, y, z]
ps += mis
last_move_ps = camera.last_move_ps
diff = np.array(last_move_ps) - np.array(ps)
if not np.all(diff == 0):
update_last_ps = True
# print(diff)
if abs(diff[0]) < 0.05:
x = round(last_move_ps[0] - diff[0] / smooth, 2)
# print("x", x)
if abs(diff[1]) < 0.05:
y = round(last_move_ps[1] - diff[1] / smooth, 2)
# print("y", y)
if abs(diff[2]) < 0.05:
z = round(last_move_ps[2] - diff[2] / smooth, 2)
# print("z", z)
for _i in range(0, 6):
if abs(diff[_i + 3]) < 0.05:
mis[_i] = round(last_move_ps[_i + 3] - diff[_i + 3] / 100, 2)
# print(f"{dns[_i]}", mis[_i])
# if diff[4] != 0:
# mis[1] = 0
# if diff[5] != 0:
# z = 0
# if diff[6] != 0:
# x = 0
# if diff[7] != 0:
# y = 0
# if diff[8] != 0:
# z = 0
if x != 0 or y != 0 or z != 0:
p += Vec3(conv_val(x, "x"), conv_val(y, "y"), conv_val(z, "z"))
......@@ -840,6 +881,11 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None):
if mi != 0:
p += mas[i] * conv_val(mi, dns[i])
if smooth and update_last_ps:
last_ps = [x, y, z]
last_ps += mis
camera.last_move_ps = last_ps
camera.position = p
......
......@@ -149,3 +149,33 @@ class HalleyCometSimBase(UniverseSimScenes):
origin=origin,
font="verdana.ttf",
close_time=-1)
def interval_run(self, total_times, interval, fun, fun_args=None):
"""
需要注意的是 total_times 前后之间的间隔大于 interval,基本上是每次都运行。
@param total_times:
@param interval:
@param fun:
@param fun_args:
@return:
"""
if not hasattr(self, "interval_method_register"):
self.interval_method_register = {}
if fun not in self.interval_method_register.keys():
self.interval_method_register[fun] = total_times
if fun_args is None:
fun()
elif len(fun_args) == 1:
fun(fun_args[0])
elif len(fun_args) > 1:
fun(*fun_args)
else:
if total_times - self.interval_method_register[fun] > interval:
if fun_args is None:
fun()
elif len(fun_args) == 1:
fun(fun_args[0])
elif len(fun_args) > 1:
fun(*fun_args)
self.interval_method_register[fun] = total_times
......@@ -13,6 +13,7 @@ from common.celestial_data_service import init_bodies_reality_pos_vels, conv_to_
set_solar_system_celestial_position
from common.consts import SECONDS_PER_YEAR, AU
from common.func import calculate_distance
from bodies import Earth
from sim_scenes.func import create_text_panel, camera_look_at, get_run_speed_factor, \
camera_move_update, camera_move_to_target_update, camera_move_control
from sim_scenes.func import ursina_run, create_sphere_sky
......@@ -54,6 +55,7 @@ class HalleyCometSim(HalleyCometSimBase):
self.sun.glows = (80, 1.005, 0.01)
# 创建哈雷彗星创建哈雷彗星
self.halley_comet = create_halley_comet(self.params.init_velocity, self.params.init_position)
self.bodies.append(self.halley_comet)
def init_settings(self):
......@@ -88,7 +90,11 @@ class HalleyCometSim(HalleyCometSimBase):
"""
self.orbit_lines = []
for body in self.bodies[1:]:
orbit_line = create_orbit_line(self.sun, body, self.start_time)
if isinstance(body, Earth):
alpha = 0.5
else:
alpha = 0.2
orbit_line = create_orbit_line(self.sun, body, self.start_time, alpha=alpha)
if orbit_line is not None:
self.orbit_lines.append(orbit_line)
......@@ -115,8 +121,8 @@ class HalleyCometSim(HalleyCometSimBase):
@return:
"""
# 为了不影响 2023年12月9日的显示,附近的 Label 就不显示
if year in ["1986", "2061", "2023", "2024", "2025"]:
return
# if year in ["1986", "2061", "2023"]:
# return
if trail is None:
_pos = halley_comet_pos
......@@ -133,7 +139,9 @@ class HalleyCometSim(HalleyCometSimBase):
scale=scale, alpha=1.0, background=background
)
label.set_light_off()
self.last_year = year
# 只记录年
if len(str(year)) == 4:
self.last_year = year
def update_comet_trail_alpha(self, distance_sun):
"""
......@@ -156,7 +164,7 @@ class HalleyCometSim(HalleyCometSimBase):
else:
alpha = MAX_ALPHA
# 修改彗星尾巴的透明度
c = self.halley_comet.planet.children[0]
c = self.halley_comet.planet.comet_trail
c.alpha = alpha
def show_milestone_lable(self, last_trail, dt):
......@@ -167,7 +175,7 @@ class HalleyCometSim(HalleyCometSimBase):
@param dt:
@return:
"""
milestones = [("1986-02-09", (0, 2, 0)), ("2023-12-09", (0, 2, 0)), ("2061-07-28", (0, 2, 0))]
milestones = [("1986-02-09", (0, 2, 0)), ("2023-12-09", (0, 0, -3)), ("2061-07-28", (0, 3, 0))]
for milestone, pos in milestones:
prop_name = f"milestone_{milestone}"
if not hasattr(self, prop_name) and dt.strftime("%Y-%m-%d") >= milestone:
......@@ -179,7 +187,7 @@ class HalleyCometSim(HalleyCometSimBase):
background=True)
# application.paused = True
# UrsinaEvent.on_pause()
ControlUI.current_ui.on_off_switch.on_value_changed()
# ControlUI.current_ui.on_off_switch.on_value_changed()
def s_f(self, value=1):
if value == 0:
......@@ -198,19 +206,24 @@ class HalleyCometSim(HalleyCometSimBase):
# 移动的信息:
# 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳)
# 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下
(1982, {"x": 2, "y": 2, "z": 0}),
(1986, {"x": 2, "y": 2, "z": 2}),
(1996, {"x": 2, "y": 0, "z": 0, "f": 3}),
(2004, {"x": 0, "y": 0, "z": 0, "f": 3}),
(2006, {}),
(1982, {"x": 2, "y": 1}),
(1986, {"x": 2, "y": -2, "z": -15}),
(1987, {"y": -6, "z": -12}),
(1988, {"y": -3, "z": -12}),
(1989, {"z": -8, "f": -5}),
(1993, {"z": -8, "f": -3}),
(1995, {"z": -8}),
(2000, {"z": -8, "y": -0.2}),
(2013, {}),
(2048, {"f": 3}),
(2061, {}),
(2124, {}),
(2062, {"y": -3}),
(2063, {"y": -4, "z": 2}),
(2072, {}),
]
camera_move_control(camera_move_infos,
cond_cb=lambda ps: ps["next_cond"] > dt.year >= ps["cond"],
value_conv=self.s_f)
value_conv=self.s_f, smooth=10)
def check_create_year_label(self, last_trail, dt):
"""
......@@ -328,12 +341,12 @@ class HalleyCometSim(HalleyCometSimBase):
@param dt:
@return:
"""
if dt.year > 2045:
UrsinaConfig.trail_length = 211
if dt.year > 2041:
UrsinaConfig.trail_length = 210
# 更新天体的位置
self.set_bodies_position(time_data)
# 更新时钟
self.show_clock(dt)
# # 更新时钟
# self.show_clock(dt)
# 更新轨道的位置(TODO:短时间可以忽略)
# for i, orbit_line in enumerate(self.orbit_lines):
# orbit_line.position = self.sun.planet.position
......@@ -370,17 +383,43 @@ class HalleyCometSim(HalleyCometSimBase):
time_total_hours = time_data.total_hours
if not hasattr(self, "last_total_hours"):
self.last_total_hours = time_total_hours
# if not hasattr(self, "last_total_hours"):
# self.last_total_hours = time_total_hours
# self.update_halley_comet_info(dt)
# print("time_total_hours", time_total_hours)
# # 摄像机移动每10小时更新一次
# self.interval_run(fun=self.camera_move, fun_args=[dt],
# total_times=time_total_hours,
# interval=20)
self.camera_move(dt)
self.update_halley_comet_info(dt)
# 每隔一段时间运行一次更新(不要太频繁更新,会导致摄像机抖动)
if time_total_hours - self.last_total_hours > 100:
self.update_ui(time_data, dt)
# 记录最后更新的总耗时(小时)
self.last_total_hours = time_total_hours
if 2040 > dt.year > 1987:
update_halley_comet_info_interval = 400
update_clock_interval = 400
else:
update_halley_comet_info_interval = 33
update_clock_interval = 60
# 更新哈雷彗星信息是每20个小时更新一次(哈雷彗星姿态、哈雷彗星距离信息)
self.interval_run(fun=self.update_halley_comet_info, fun_args=[dt],
total_times=time_total_hours,
interval=update_halley_comet_info_interval)
# 每50个小时更新一次界面(天体位置)
self.interval_run(fun=self.update_ui, fun_args=[time_data, dt],
total_times=time_total_hours,
interval=60)
self.interval_run(fun=self.show_clock, fun_args=[dt],
total_times=time_total_hours,
interval=update_clock_interval)
# # 每隔一段时间运行一次更新(不要太频繁更新,会导致摄像机抖动)
# if time_total_hours - self.last_total_hours > 50:
# self.update_halley_comet_info(dt)
# self.update_ui(time_data, dt)
# # 记录最后更新的总耗时(小时)
# self.last_total_hours = time_total_hours
if __name__ == '__main__':
......
### ffmpeg 命令
```shell
# 视频截断 开始时间 -ss 结束时间 -to
# 修改视频的尺寸 -s
ffmpeg -i "input/一向箔.mp4" -s 450x255 -y -ss 00:00:09.0 -to 00:00:13.0 "output/一向箔.webp"
```
```shell
# -ss 00:00:02 表示从视频的第2秒开始截图
# -vframes 1 表示只截取一帧
ffmpeg -i "input/一向箔.mp4" -ss 00:00:02 -vframes 1 "output/一向箔.png"
```
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册