From 13e0fe0d2a45dc6ee4a963c5b0d7a6077a5a3bc3 Mon Sep 17 00:00:00 2001 From: march3 Date: Sat, 18 Nov 2023 15:28:56 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_lab/wormhole_sim_2.py | 275 ++++++++++++++++++++++++++++++++++++++ sim_scenes/func.py | 14 +- 2 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 sim_lab/wormhole_sim_2.py diff --git a/sim_lab/wormhole_sim_2.py b/sim_lab/wormhole_sim_2.py new file mode 100644 index 0000000..89a4557 --- /dev/null +++ b/sim_lab/wormhole_sim_2.py @@ -0,0 +1,275 @@ +# -*- coding:utf-8 -*- +# title :虫洞效果模拟 +# description :虫洞效果模拟 +# author :Python超人 +# date :2023-11-03 +# link :https://gitcode.net/pythoncr/ +# python_version :3.9 +# ============================================================================== +from bodies import Sun, Earth +from bodies.universe_body import create_universe_body +from common.consts import SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH, SECONDS_PER_YEAR, AU +from objs import Obj, SpaceShip, StarWarsSpeeder, ScifiGunship, SciFiBomber, CoreValagaClas +from sim_scenes.func import mayavi_run, mpl_run, ursina_run, camera_look_at, two_bodies_colliding, camera_move_control, \ + get_run_speed_factor +from ursina import camera, application, lerp + +from bodies import Body +from simulators.ursina.ursina_event import UrsinaEvent + + +class WormholeSim: + SIZE_SCALE = 1 + D = AU / 10 * SIZE_SCALE + + def __init__(self): + D = self.D + self.camera_target = CoreValagaClas(name="摄像机目标", mass=1e30, color=(111, 140, 255), + # init_position=[0, 0, 0], + init_position=[D, 0, -D], + init_velocity=[0, 0, 0], + size_scale=self.SIZE_SCALE * 1e2).set_ignore_gravity(True) + + self.universes = [] + # self.textures = ["cosmic_pan_1.jpg", "cosmic_pan_4.jpg", "cosmic_pan_2.jpg", "cosmic_pan_3.jpg"] + self.create_universes() + self.bodies = [self.camera_target] + self.universes + # self.bodies = self.universes + + def create_universe(self, idx, position): + universe_body = create_universe_body(f"宇宙{idx}", texture=f'cosmic_pan_{idx + 1}.jpg', # self.textures[idx], + size_scale=self.SIZE_SCALE, + init_position=position, + init_velocity=[0, 0, 0], + ) + return universe_body + + def create_universes(self): + D = self.D + positions = [[D, 0, -D], [D, 0, D], [- D, 0, -D], [- D, 0, D], + [D, D, -D], [D, D, D], [- D, D, -D], [- D, D, D], + [D, -D, -D], [D, -D, D], [- D, -D, -D], [- D, -D, D] + ] + for idx, pos in enumerate(positions): + self.universes.append(self.create_universe(idx, pos)) + + def init_setting(self): + camera.clip_plane_near = 0.00005 + # camera.clip_plane_near = 0.01 + camera.clip_plane_far = 100000000 + # create_sphere_sky(scale=200000) + application.time_scale = 0.001 + # camera.scale = 1000 + # camera.parent = camera_target.planet + # camera.rotation_x = 90 + camera.fov = 120 + + for universe in self.universes: + universe.planet.collider = "sphere" + universe.planet.enabled = False + + def universe_reset(self): + self.camera_target.speed = 1 + self.current_idx += 1 + self.target_idx += 1 + if self.current_idx > len(self.universes) - 1: + self.current_idx = 0 + if self.target_idx > len(self.universes) - 1: + self.target_idx = 0 + + for u in self.universes: + self.scale_down(u) + u.planet.enabled = False + + self.current_universe = self.universes[self.current_idx] + self.target_universe = self.universes[self.target_idx] + + self.scale_up(self.current_universe) + # self.scale_down(self.target_universe) + + self.current_universe.planet.enabled = True + self.target_universe.planet.enabled = True + + def body_update_reset(self): + # for b in self.bodies: + # b.planet.update = lambda: None + self.camera_target.planet.update = lambda: None + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + self.init_setting() + self.current_idx = -1 + self.target_idx = 0 + self.current_universe = None + self.body_update_reset() + self.universe_reset() + + # self.target_universe.planet.rotation_y = 100 + # self.current_universe.planet.rotation_y = 200 + # self.current_universe.planet.rotation_x = 30 + + # camera_look_at(self.camera_target) + self.camera_target.planet.collider = "sphere" + self.camera_target.planet.enabled = False + camera.collider = "sphere" + camera.current_universe = self.current_universe + camera_look_at(self.camera_target, rotation_z=0) + + def scale_up(self, obj): + if obj is None: + return + obj.planet.init_scale = self.SIZE_SCALE * 1000 + + def scale_down(self, obj): + if obj is None: + return + obj.planet.init_scale = self.SIZE_SCALE + + # def camera_move(self, time_data): + # """ + # 摄像机移动控制 + # @param dt: + # @return: + # """ + # + # def camera_rotation(): + # # camera.rotation_y += 1 + # # self.scale_up(self.target_universe) + # # self.scale_down(self.current_universe) + # if camera.intersects(self.target_universe.planet).hit: + # self.universe_reset() + # return False + # return True + # + # # 摄像机移动控制数据 + # camera_move_infos = [ + # # 条件:年份 + # # 移动的信息: + # # 按坐标系方向移动 x:右+左-, y:升+降-, z:前+(接近太阳)后-(远离太阳) + # # 以摄像机视角移动 f:前 b:后 l:左 r:右 u:上 d:下 + # (0, {"z": 1}), + # # (1983, {"to": {"ct_id": 1, "t": 10}}), + # (2, {"begin_execution": lambda p: camera_rotation()}), + # (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}), + # (2062, {"y": -3}), + # (2063, {"y": -10, "z": 2}), + # (2181, {}), + # # (2082, {"exit": True}) + # ] + # + # camera_move_control(camera_move_infos, + # cond_cb=lambda ps: ps["next_cond"] > time_data.total_hours >= ps["cond"], + # value_conv=self.s_f, smooth=10) + # print(time_data.total_hours) + # + # def s_f(self, value=1): + # if value == 0: + # return 0 + # return get_run_speed_factor() * value + + def on_timer_changed(self, time_data): + # return + # pass + self.target_universe.planet.rotation_y -= 0.5 + camera_look_at(self.camera_target, rotation_z=0) + # camera.rotation_x -= 2 + self.camera_target.planet.look_at(self.target_universe.planet) + # self.camera_move(time_data) + from ursina import time, distance + self.camera_target.speed *= 1.02 + if self.camera_target.speed > 1000: + self.camera_target.speed = 1000 + self.camera_target.planet.position = \ + lerp(self.camera_target.planet.position, self.target_universe.planet.position, + self.camera_target.speed * time.dt) + + # self.camera_target.planet.position += self.camera_target.planet.forward*100 + # print(self.camera_target.planet.position) + + dd = distance(camera.position, self.target_universe.planet.position) + camera.position = lerp(camera.position, self.target_universe.planet.position, 1500 * time.dt / dd) + # camera.position += camera.forward * 2 + + # if self.camera_target.planet.intersects(self.target_universe.planet).hit: + if camera.intersects(self.target_universe.planet).hit: + self.universe_reset() + return + if camera.intersects(self.target_universe.planet).hit: + # worm_hole.planet.init_scale = SIZE_SCALE * 1000 + self.current_universe.planet.init_scale = self.SIZE_SCALE + if self.target_universe.planet.init_scale < self.SIZE_SCALE * 1000: + self.target_universe.planet.init_scale *= 1.1 + # if ours_universe.planet.init_scale > SIZE_SCALE: + # ours_universe.planet.init_scale /= 1.1 + if not hasattr(camera, "init_rotation_y"): + camera.init_rotation_y = camera.rotation_y + camera.rotation_y_v = 0.01 + + if abs(camera.init_rotation_y - camera.rotation_y) < 10: + camera.rotation_y_v += 0.2 + elif abs(camera.init_rotation_y - camera.rotation_y) < 90: + camera.rotation_y_v += 0.15 + elif abs(camera.init_rotation_y - camera.rotation_y) < 120: + camera.rotation_y_v -= 0.1 + elif abs(camera.init_rotation_y - camera.rotation_y) < 180: + camera.rotation_y_v -= 0.01 + if camera.rotation_y_v < 0.1: + camera.rotation_y_v = 0.1 + else: + camera.rotation_y_v = 0 + camera.rotation_y += camera.rotation_y_v + # camera_look_at(ours_universe) + # else: + # if two_bodies_colliding(camera_target, worm_hole): + # camera_target.stop_and_ignore_gravity() + # print(1,camera_target.planet.position) + # camera_target.planet.position = lerp(camera_target.planet.position, worm_hole.planet.position, 1e-2) + # print(2,camera_target.planet.position) + # camera.position = (camera.position[0],camera.position[1],camera.position[2]) # + from ursina import application, time + camera.position = lerp(camera.position, self.target_universe.planet.position, 0.2e-2 * time.dt) + + # camera_position = [camera_position[0], camera_position[1], camera_position[2] - 0.01] + # camera.position = camera_position + + def build_events(self): + # 订阅事件后,上面2个函数功能才会起作用 + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(wormhole_sim.on_timer_changed) + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(wormhole_sim.on_ready) + + def run(self): + self.build_events() + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + ursina_run(self.bodies, SECONDS_PER_DAY / 24, + # position=(0, AU / 1200, -1.003 * AU), + # position=[-AU/100, 0, 0], + # position=[0, 0, -AU / 10], + # position=[0, 0, ], + position=[0, self.D, -self.D * 2], + cosmic_bg='', + gravity_works=False, + timer_enabled=True, + show_grid=False, + show_trail=False) + + +if __name__ == '__main__': + """ + + """ + wormhole_sim = WormholeSim() + wormhole_sim.run() diff --git a/sim_scenes/func.py b/sim_scenes/func.py index 9a53307..3d99ff5 100644 --- a/sim_scenes/func.py +++ b/sim_scenes/func.py @@ -867,10 +867,18 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None, smooth=None cond_cb_params = {"cond": cond, "next_cond": next_cond, "idx": idx, "info": info, "next_info": next_info} if cond_cb(cond_cb_params): + begin_execution = info.get("begin_execution", None) + if callable(begin_execution): + if not begin_execution(cond_cb_params): + break + + end_execution = info.get("end_execution", None) t = info.get("to", None) if t is not None: camera_to_target(info) - continue + if callable(end_execution): + end_execution(cond_cb_params) + break p = camera.position x, y, z = [info.get("x", 0), info.get("y", 0), info.get("z", 0)] @@ -918,10 +926,14 @@ def camera_move_control(camera_move_infos, cond_cb, value_conv=None, smooth=None camera.position = p + if callable(end_execution): + end_execution(cond_cb_params) + e = next_info.get("exit", None) if e: print("自动退出...") exit(0) + break if __name__ == '__main__': -- GitLab