# -*- 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()