diff --git a/sim_lab/wormhole_sim.py b/sim_lab/wormhole_sim.py index 20cbee28e78f6c5655dfd5971d54e3bf885dc86e..0e977d7f83eed9b67227ec000fd20f4b49415fc6 100644 --- a/sim_lab/wormhole_sim.py +++ b/sim_lab/wormhole_sim.py @@ -2,58 +2,161 @@ # title :虫洞效果模拟 # description :虫洞效果模拟 # author :Python超人 -# date :2023-11-03 +# date :2023-11-19 # link :https://gitcode.net/pythoncr/ # python_version :3.9 # ============================================================================== from bodies import Sun, Earth +from simulators.ursina.entities.entity_utils import create_ambient_light 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 -from ursina import camera, application, lerp +from sim_scenes.func import mayavi_run, mpl_run, ursina_run, camera_look_at, two_bodies_colliding, camera_move_control, \ + get_run_speed_factor, create_text_panel +from ursina import camera, application, lerp, Vec3 from bodies import Body from simulators.ursina.ursina_event import UrsinaEvent +from dataclasses import dataclass, field +import inspect -ours_cosmic_bg = "cosmic_pan_1.jpg" -worms_cosmic_bg = "cosmic_pan_4.jpg" + +@dataclass(order=True) +class WormholeInfo: + # entity: object + name: str = field(default='') + position: list[float] = field(default_factory=[0, 0, 0]) + camera_target_init_speed: int = 100 + camera_init_speed: int = 100 + camera_target_speed: int = 2000 + camera_target_max_speed: int = 2000 + camera_forward_speed: int = - 0.1 + camera_max_speed: int = 5000 + camera_acc_speed: int = 1.02 + camera_forward_acc_speed: int = 0.01 + size_factor: float = 10 + rotation_x: float = None + rotation_y: float = None + rotation_z: float = None + around_max_count: int = 300 + around_max_speed: int = -200 + around_min_speed: int = 100 + around_direction: str = "right" + around_acc_speed: int = -2 + + +# class WormholeInfoParams: +# def __init__(self): +# self.params = [] +# +# def add(self, param_name): +# +# return self class WormholeSim: - SIZE_SCALE = 1 # 生成的太阳放大 50 倍 - RUN_DIAMETER = 1.392e6 - velocity_rate = 22 + SIZE_SCALE = 1 + D = AU / 10 * SIZE_SCALE def __init__(self): - self.camera_target = CoreValagaClas(name="摄像机目标", mass=1e30, color=(111, 140, 255), + D = self.D + self.camera_target = CoreValagaClas(name="摄像机镜头", mass=1e30, color=(111, 140, 255), # init_position=[0, 0, 0], - init_position=[0, 0, AU / 10], + init_position=[D, 0, -D], init_velocity=[0, 0, 0], - size_scale=WormholeSim.SIZE_SCALE * 1e1) # .set_ignore_gravity(True) + size_scale=self.SIZE_SCALE * 1e3).set_ignore_gravity(True) + self.wormholeinfo_default_vals = None + self.camera_target.go_target = None + self.camera_target.go_target_stage = None + self.last_universe = None + self.current_universe = None + self.target_universe = None self.universes = [] + self.wormhole_infos = {} - self.ours_universe = create_universe_body("我们的宇宙", "cosmic_pan_1.jpg", - size_scale=WormholeSim.SIZE_SCALE, - init_position=[0, 0, -AU / 120], - init_velocity=[0, 0, 0], - ) - self.universes.append(self.ours_universe) - self.worm_hole = create_universe_body("虫洞1", "cosmic_pan_4.jpg", - init_position=[0, 0, AU / 120], - init_velocity=[0, 0, 0], - size_scale=WormholeSim.SIZE_SCALE) - self.universes.append(self.worm_hole) + self.create_universes() self.bodies = [self.camera_target] + self.universes - def on_ready(self): - """ - 事件绑定后,模拟器运行前会触发 - @return: - """ - # 创建天空 - camera.clip_plane_near = 0.0001 - camera.clip_plane_far = 10000000000 + def create_universe(self, name, idx, position): + if name is None: + name = f"宇宙{idx}" + universe_body = create_universe_body(name, 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 + # camera_target_init_speed: int = 100 + # camera_init_speed: int = 100 + # camera_target_speed: int = 2000 + # camera_forward_speed: int = - 0.1 + # camera_max_speed: int = 2000 + # camera_acc_speed: int = 1.02 + # camera_forward_acc_speed: int = 0.01 + # size_factor: float = 10 + # rotation_x: float = None + # rotation_y: float = None + # rotation_z: float = None + # around_max_count: int = 300 + # around_max_speed: int = -200 + # around_direction: str = "right" + # around_acc_speed: int = -2 + + wormhole_infos = [ + {"position": [D, 0, -D], "rotation_y": -150}, + {"position": [D, 0, D], "rotation_z": 30, "around_acc_speed": -20, "around_min_speed": 150, + "camera_forward_speed": -0.3,"around_max_count":500}, + {"position": [- D, -D, D]}, + {"position": [- D, 0, -D]}, + {"position": [D, D, D]}, + {"position": [D, -D, D]}, + {"position": [- D, -D, -D]}, + {"position": [- D, 0, D]}, + {"position": [D, D, -D]}, + {"position": [- D, D, -D]}, + {"position": [- D, D, D]}, + {"position": [D, -D, -D]} + ] + + def build_wormhole_info_param(wormhole_info): + # ps = WormholeInfoParams() + if self.wormholeinfo_default_vals is None: + self.wormholeinfo_default_vals = {} + init_wormholeinfo_default_vals = True + else: + init_wormholeinfo_default_vals = False + + ps = {} + attributes = inspect.getmembers(WormholeInfo) + for attr in attributes: + if not attr[0].startswith('_'): + pn = attr[0] + if init_wormholeinfo_default_vals: + self.wormholeinfo_default_vals[pn] = attr[1] + if pn not in wormhole_info.keys(): + continue + ps[pn] = wormhole_info[pn] # attr[1].default + + return ps + + for idx, wormhole_info in enumerate(wormhole_infos): + pos = wormhole_info.get("position", [0, 0, 0]) + name = wormhole_info.get("name", f"宇宙{idx}") + ps1 = build_wormhole_info_param(wormhole_info) + ps1["position"] = pos + ps1["name"] = name + universe = self.create_universe(name, idx, pos) + self.universes.append(universe) + self.wormhole_infos[universe] = WormholeInfo(**ps1) + + 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 @@ -61,60 +164,278 @@ class WormholeSim: # camera.rotation_x = 90 camera.fov = 100 - self.worm_hole.planet.rotation_y = 100 - self.ours_universe.planet.rotation_y = 200 - self.ours_universe.planet.rotation_x = 30 + for universe in self.universes: + universe.planet.collider = "sphere" + universe.planet.enabled = False + camera.forward_speed = 0 + + def get_wormhole_data(self, data_name, default_val=None, universe=None): + def ret_value(): + if default_val is None: + if data_name in self.wormholeinfo_default_vals.keys(): + return self.wormholeinfo_default_vals[data_name] + + return default_val + + if universe is None: + universe = self.current_universe + wormhole_info = self.wormhole_infos[universe] + if wormhole_info is None: + return ret_value() + + if not hasattr(wormhole_info, data_name): + return ret_value() + + val = getattr(wormhole_info, data_name) + if val is None: + return ret_value() + + return val + + def universe_reset(self): + + 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.last_universe = self.current_universe + self.current_universe = self.universes[self.current_idx] + self.target_universe = self.universes[self.target_idx] + + rotation_x: float = self.get_wormhole_data("rotation_x") + rotation_y: float = self.get_wormhole_data("rotation_y") + rotation_z: float = self.get_wormhole_data("rotation_z") + + if rotation_x is not None: + self.current_universe.planet.rotation_x = rotation_x + if rotation_y is not None: + self.current_universe.planet.rotation_y = rotation_y + if rotation_z is not None: + self.current_universe.planet.rotation_z = rotation_z + + self.camera_target.speed = self.get_wormhole_data("camera_target_init_speed") + camera.speed = self.get_wormhole_data("camera_init_speed") + + if self.last_universe is None: + self.camera_target.go_target = self.target_universe + self.camera_target.go_target_stage = "target_universe" + self.camera_target.go_target_hit = False + else: + self.camera_target.go_target = self.last_universe + self.last_universe.planet.enabled = True + + size_factor = self.get_wormhole_data("size_factor", universe=self.last_universe) + + self.scale_down(self.last_universe, scale_size=self.SIZE_SCALE * size_factor) + self.camera_target.go_target_stage = "last_universe" + self.camera_target.go_target_hit = False + self.scale_down(u) + self.camera_target.speed = self.get_wormhole_data("camera_target_speed") + camera.forward_speed = self.get_wormhole_data("camera_forward_speed") + + self.scale_up(self.current_universe) + # self.scale_down(self.target_universe) + + self.current_universe.planet.enabled = True + # self.current_universe.planet.set_light_off() + self.target_universe.planet.enabled = True + # self.target_universe.planet.set_light_off() + + 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() + # create_ambient_light(parent=camera) + + self.current_idx = -1 + self.target_idx = 0 + self.current_universe = None + self.body_update_reset() + self.universe_reset() - camera_look_at(self.camera_target) + # camera_look_at(self.camera_target) + self.camera_target.planet.collider = "sphere" + self.camera_target.planet.enabled = False camera.collider = "sphere" - self.worm_hole.planet.collider = "sphere" - self.ours_universe.planet.init_scale = self.SIZE_SCALE * 1000 - self.camera_target.current_universe = self.ours_universe - self.camera_target.targe_universe = self.worm_hole - # camera_position = camera.position + camera.current_universe = self.current_universe + camera_look_at(self.camera_target, rotation_z=0) + + self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3) + + def update_text_panel(self): + """ + 更新文字信息面板 + @param d_sun: + @return: + """ + panel_text = "虫洞穿越宇宙:\n\n当前宇宙:%s " % self.current_universe.name + panel_text += "\n\n下站宇宙:%s" % self.target_universe.name + if self.last_universe is not None: + panel_text += "\n\n上站宇宙:%s " % self.last_universe.name + + self.text_panel.text = panel_text + + def scale_up(self, obj): + if obj is None: + return + obj.planet.init_scale = self.SIZE_SCALE * 100 + + def scale_down(self, obj, scale_size=None): + if obj is None: + return + if scale_size is None: + scale_size = self.SIZE_SCALE + obj.planet.init_scale = scale_size + + def around_universe(self, around_target): + around_max_count = self.get_wormhole_data("around_max_count") + around_max_speed = self.get_wormhole_data("around_max_speed") + around_min_speed = self.get_wormhole_data("around_min_speed") + around_direction = self.get_wormhole_data("around_direction") + around_acc_speed = self.get_wormhole_data("around_acc_speed") + # around_target = camera + + self.camera_target.planet.look_at(around_target) + + # print(self.camera_target.planet.rotation_x,self.camera_target.planet.rotation_y,self.camera_target.planet.rotation_z) + planet_direction = getattr(self.camera_target.planet, around_direction) + + if not hasattr(self.camera_target, "around_speed"): + self.camera_target.around_speed = 0 + if not hasattr(self.camera_target, "around_count"): + self.camera_target.around_count = 0 + + if self.camera_target.around_count > around_max_count: + if hasattr(self.camera_target, "around_speed") and \ + abs(self.camera_target.around_speed) > abs(around_min_speed): + self.camera_target.around_speed -= around_acc_speed + else: + # delattr(self.camera_target, "around_speed") + delattr(self.camera_target, "around_count") + self.camera_target.go_target_stage = "last_universe" + self.camera_target.speed = self.get_wormhole_data("camera_init_speed") + else: + self.camera_target.around_speed += around_acc_speed + + if hasattr(self.camera_target, "around_speed"): + if abs(self.camera_target.around_speed) > abs(around_max_speed): + self.camera_target.around_speed = around_max_speed + + self.camera_target.planet.position += planet_direction * self.camera_target.around_speed + + print("around_speed", self.camera_target.around_speed) + + if hasattr(self.camera_target, "around_count"): + self.camera_target.around_count += 1 + + # camera.forward_speed = -0.05 + if abs(camera.forward_speed) > 0.01: + camera_forward_acc_speed = self.get_wormhole_data("camera_forward_acc_speed") + camera.forward_speed += camera_forward_acc_speed + # else: + # camera.forward_speed = 0 + + def go_last_universe(self, go_target): + if self.camera_target.planet.intersects(go_target).hit: + if not self.camera_target.go_target_hit: + self.camera_target.go_target_hit = True + self.camera_target.go_target_stage = "around_universe" + self.camera_target.go_target = self.target_universe + self.camera_target.speed = self.get_wormhole_data("camera_init_speed") + camera.speed = 1 # 在看上一个宇宙时候,停留一会 + # # camera.forward_speed = -0.05 + # if camera.forward_speed < 0: + # camera_forward_acc_speed = self.get_wormhole_data("camera_forward_acc_speed") + # camera.forward_speed += camera_forward_acc_speed + # else: + # camera.forward_speed = 0 + if hasattr(self.camera_target, "around_speed"): + if abs(self.camera_target.around_speed) > abs(10): + around_acc_speed = self.get_wormhole_data("around_acc_speed") + around_direction = self.get_wormhole_data("around_direction") + planet_direction = getattr(self.camera_target.planet, around_direction) + + self.camera_target.around_speed -= around_acc_speed + self.camera_target.planet.position += planet_direction * self.camera_target.around_speed + else: + delattr(self.camera_target, "around_speed") def on_timer_changed(self, time_data): - # return - # pass - # camera_look_at(camera_target) + self.target_universe.planet.rotation_y -= 0.5 + if self.last_universe is not None: + self.last_universe.planet.rotation_y += 0.3 + camera_look_at(self.camera_target, rotation_z=0) # camera.rotation_x -= 2 - self.camera_target.planet.look_at(self.camera_target.targe_universe.planet) - if camera.intersects(self.camera_target.targe_universe.planet).hit: - # worm_hole.planet.init_scale = SIZE_SCALE * 1000 - self.camera_target.current_universe.planet.init_scale = self.SIZE_SCALE - if self.camera_target.targe_universe.planet.init_scale < self.SIZE_SCALE * 1000: - self.camera_target.targe_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.5 - elif abs(camera.init_rotation_y - camera.rotation_y) < 90: - camera.rotation_y_v += 0.3 - 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 + + # self.camera_target.planet.look_at(self.target_universe.planet) + # self.camera_move(time_data) + from ursina import time, distance + + camera_max_speed = self.get_wormhole_data("camera_max_speed") + camera_acc_speed = self.get_wormhole_data("camera_acc_speed") + camera_target_max_speed = self.get_wormhole_data("camera_target_max_speed", ) + + if self.camera_target.go_target is not None: + go_target = self.camera_target.go_target.planet + if self.camera_target.go_target_stage == "around_universe": + # 摄像机镜头环绕目标宇运动(摄像机镜头暂时不去目标) + self.around_universe(go_target) 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]) # - camera.position = lerp(camera.position, self.camera_target.planet.position, 0.1e-2) + # 摄像机镜头看向目标宇宙,并逐渐靠近目标 + self.camera_target.planet.look_at(go_target) + self.camera_target.planet.position = \ + lerp(self.camera_target.planet.position, go_target.position, + self.camera_target.speed * time.dt) + + # 摄像机镜头加速度计算(摄像机镜头圆滑效果),并对摄像机镜头移动速度进行限制 + self.camera_target.speed *= camera_acc_speed + if self.camera_target.speed > camera_target_max_speed: + self.camera_target.speed = camera_target_max_speed + + if self.camera_target.go_target_stage == "last_universe": + # 进入新的宇宙后,摄像机回看上一个宇宙的镜头 + self.go_last_universe(go_target) + + elif self.camera_target.go_target_stage == "target_universe": + # 摄像机镜头去往新的宇宙进行中 + if self.camera_target.planet.intersects(go_target).hit and not self.camera_target.go_target_hit: + # 摄像机镜头达到新的目标宇宙后,摄像机就不后退了 + self.camera_target.go_target_hit = True + camera.forward_speed = 0 + # camera.speed = 3000 # TODO:这个不能反复执行 + + # self.camera_target.planet.position += self.camera_target.planet.forward*100 + # print(self.camera_target.planet.position) + # 摄像机加速度计算(摄像机圆滑效果) + camera.speed *= camera_acc_speed + if camera.speed > camera_max_speed: + camera.speed = camera_max_speed + + if camera.speed != 0: + dd = distance(camera.position, self.target_universe.planet.position) + camera.position = lerp(camera.position, self.target_universe.planet.position, camera.speed * time.dt / dd) + if camera.forward_speed != 0: + camera.position += camera.forward * camera.forward_speed + + # if self.camera_target.planet.intersects(self.target_universe.planet).hit: + if camera.intersects(self.target_universe.planet).hit: + self.universe_reset() - # camera_position = [camera_position[0], camera_position[1], camera_position[2] - 0.01] - # camera.position = camera_position + self.update_text_panel() def build_events(self): # 订阅事件后,上面2个函数功能才会起作用 @@ -131,9 +452,11 @@ class WormholeSim: 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, -AU / 10], + # position=[0, 0, ], + position=[0, self.D, -self.D * 2], cosmic_bg='', - # gravity_works=False, + gravity_works=False, timer_enabled=True, show_grid=False, show_trail=False) diff --git a/sim_lab/wormhole_sim_01.py b/sim_lab/wormhole_sim_01.py new file mode 100644 index 0000000000000000000000000000000000000000..20cbee28e78f6c5655dfd5971d54e3bf885dc86e --- /dev/null +++ b/sim_lab/wormhole_sim_01.py @@ -0,0 +1,147 @@ +# -*- 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 +from ursina import camera, application, lerp + +from bodies import Body +from simulators.ursina.ursina_event import UrsinaEvent + +ours_cosmic_bg = "cosmic_pan_1.jpg" +worms_cosmic_bg = "cosmic_pan_4.jpg" + + +class WormholeSim: + SIZE_SCALE = 1 # 生成的太阳放大 50 倍 + RUN_DIAMETER = 1.392e6 + velocity_rate = 22 + + def __init__(self): + self.camera_target = CoreValagaClas(name="摄像机目标", mass=1e30, color=(111, 140, 255), + # init_position=[0, 0, 0], + init_position=[0, 0, AU / 10], + init_velocity=[0, 0, 0], + size_scale=WormholeSim.SIZE_SCALE * 1e1) # .set_ignore_gravity(True) + self.universes = [] + + self.ours_universe = create_universe_body("我们的宇宙", "cosmic_pan_1.jpg", + size_scale=WormholeSim.SIZE_SCALE, + init_position=[0, 0, -AU / 120], + init_velocity=[0, 0, 0], + ) + self.universes.append(self.ours_universe) + self.worm_hole = create_universe_body("虫洞1", "cosmic_pan_4.jpg", + init_position=[0, 0, AU / 120], + init_velocity=[0, 0, 0], + size_scale=WormholeSim.SIZE_SCALE) + self.universes.append(self.worm_hole) + self.bodies = [self.camera_target] + self.universes + + def on_ready(self): + """ + 事件绑定后,模拟器运行前会触发 + @return: + """ + # 创建天空 + camera.clip_plane_near = 0.0001 + camera.clip_plane_far = 10000000000 + # create_sphere_sky(scale=200000) + application.time_scale = 0.001 + # camera.scale = 1000 + # camera.parent = camera_target.planet + # camera.rotation_x = 90 + camera.fov = 100 + + self.worm_hole.planet.rotation_y = 100 + self.ours_universe.planet.rotation_y = 200 + self.ours_universe.planet.rotation_x = 30 + + camera_look_at(self.camera_target) + camera.collider = "sphere" + self.worm_hole.planet.collider = "sphere" + self.ours_universe.planet.init_scale = self.SIZE_SCALE * 1000 + self.camera_target.current_universe = self.ours_universe + self.camera_target.targe_universe = self.worm_hole + # camera_position = camera.position + + def on_timer_changed(self, time_data): + # return + # pass + # camera_look_at(camera_target) + # camera.rotation_x -= 2 + self.camera_target.planet.look_at(self.camera_target.targe_universe.planet) + if camera.intersects(self.camera_target.targe_universe.planet).hit: + # worm_hole.planet.init_scale = SIZE_SCALE * 1000 + self.camera_target.current_universe.planet.init_scale = self.SIZE_SCALE + if self.camera_target.targe_universe.planet.init_scale < self.SIZE_SCALE * 1000: + self.camera_target.targe_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.5 + elif abs(camera.init_rotation_y - camera.rotation_y) < 90: + camera.rotation_y_v += 0.3 + 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]) # + camera.position = lerp(camera.position, self.camera_target.planet.position, 0.1e-2) + + # 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], + 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_lab/wormhole_sim_2.py b/sim_lab/wormhole_sim_03.py similarity index 100% rename from sim_lab/wormhole_sim_2.py rename to sim_lab/wormhole_sim_03.py diff --git a/sim_scenes/wormhole_sim.py b/sim_scenes/wormhole_sim.py deleted file mode 100644 index 4cc5928d9ff0ef5e6f957cea66e7ddc803dcb99a..0000000000000000000000000000000000000000 --- a/sim_scenes/wormhole_sim.py +++ /dev/null @@ -1,458 +0,0 @@ -# -*- coding:utf-8 -*- -# title :虫洞效果模拟 -# description :虫洞效果模拟 -# author :Python超人 -# date :2023-11-19 -# link :https://gitcode.net/pythoncr/ -# python_version :3.9 -# ============================================================================== -from bodies import Sun, Earth -from simulators.ursina.entities.entity_utils import create_ambient_light -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, create_text_panel -from ursina import camera, application, lerp, Vec3 - -from bodies import Body -from simulators.ursina.ursina_event import UrsinaEvent -from dataclasses import dataclass, field -import inspect - - -@dataclass(order=True) -class WormholeInfo: - # entity: object - name: str = field(default='') - position: list[float] = field(default_factory=[0, 0, 0]) - camera_target_init_speed: int = 100 - camera_init_speed: int = 100 - camera_target_speed: int = 2000 - camera_target_max_speed: int = 2000 - camera_forward_speed: int = - 0.1 - camera_max_speed: int = 5000 - camera_acc_speed: int = 1.02 - camera_forward_acc_speed: int = 0.01 - size_factor: float = 10 - rotation_x: float = None - rotation_y: float = None - rotation_z: float = None - around_max_count: int = 300 - around_max_speed: int = -200 - around_min_speed: int = 100 - around_direction: str = "right" - around_acc_speed: int = -2 - - -# class WormholeInfoParams: -# def __init__(self): -# self.params = [] -# -# def add(self, param_name): -# -# return self - - -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 * 1e3).set_ignore_gravity(True) - self.wormholeinfo_default_vals = None - self.camera_target.go_target = None - self.camera_target.go_target_stage = None - self.last_universe = None - self.current_universe = None - self.target_universe = None - self.universes = [] - self.wormhole_infos = {} - - self.create_universes() - self.bodies = [self.camera_target] + self.universes - - def create_universe(self, name, idx, position): - if name is None: - name = f"宇宙{idx}" - universe_body = create_universe_body(name, 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 - # camera_target_init_speed: int = 100 - # camera_init_speed: int = 100 - # camera_target_speed: int = 2000 - # camera_forward_speed: int = - 0.1 - # camera_max_speed: int = 2000 - # camera_acc_speed: int = 1.02 - # camera_forward_acc_speed: int = 0.01 - # size_factor: float = 10 - # rotation_x: float = None - # rotation_y: float = None - # rotation_z: float = None - # around_max_count: int = 300 - # around_max_speed: int = -200 - # around_direction: str = "right" - # around_acc_speed: int = -2 - - wormhole_infos = [ - {"position": [D, 0, -D], "rotation_y": -150}, - {"position": [D, 0, D], "rotation_z": 30, "around_acc_speed": -10, "around_min_speed": 150}, - {"position": [- D, -D, D]}, - {"position": [- D, 0, -D]}, - {"position": [D, D, D]}, - {"position": [D, -D, D]}, - {"position": [- D, -D, -D]}, - {"position": [- D, 0, D]}, - {"position": [D, D, -D]}, - {"position": [- D, D, -D]}, - {"position": [- D, D, D]}, - {"position": [D, -D, -D]} - ] - - def build_wormhole_info_param(wormhole_info): - # ps = WormholeInfoParams() - if self.wormholeinfo_default_vals is None: - self.wormholeinfo_default_vals = {} - init_wormholeinfo_default_vals = True - else: - init_wormholeinfo_default_vals = False - - ps = {} - attributes = inspect.getmembers(WormholeInfo) - for attr in attributes: - if not attr[0].startswith('_'): - pn = attr[0] - if init_wormholeinfo_default_vals: - self.wormholeinfo_default_vals[pn] = attr[1] - if pn not in wormhole_info.keys(): - continue - ps[pn] = wormhole_info[pn] # attr[1].default - - return ps - - for idx, wormhole_info in enumerate(wormhole_infos): - pos = wormhole_info.get("position", [0, 0, 0]) - name = wormhole_info.get("name", f"宇宙{idx}") - ps1 = build_wormhole_info_param(wormhole_info) - ps1["position"] = pos - ps1["name"] = name - universe = self.create_universe(name, idx, pos) - self.universes.append(universe) - self.wormhole_infos[universe] = WormholeInfo(**ps1) - - 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 = 100 - - for universe in self.universes: - universe.planet.collider = "sphere" - universe.planet.enabled = False - camera.forward_speed = 0 - - def get_wormhole_data(self, data_name, default_val=None, universe=None): - def ret_value(): - if default_val is None: - if data_name in self.wormholeinfo_default_vals.keys(): - return self.wormholeinfo_default_vals[data_name] - - return default_val - - if universe is None: - universe = self.current_universe - wormhole_info = self.wormhole_infos[universe] - if wormhole_info is None: - return ret_value() - - if not hasattr(wormhole_info, data_name): - return ret_value() - - val = getattr(wormhole_info, data_name) - if val is None: - return ret_value() - - return val - - def universe_reset(self): - - 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.last_universe = self.current_universe - self.current_universe = self.universes[self.current_idx] - self.target_universe = self.universes[self.target_idx] - - rotation_x: float = self.get_wormhole_data("rotation_x") - rotation_y: float = self.get_wormhole_data("rotation_y") - rotation_z: float = self.get_wormhole_data("rotation_z") - - if rotation_x is not None: - self.current_universe.planet.rotation_x = rotation_x - if rotation_y is not None: - self.current_universe.planet.rotation_y = rotation_y - if rotation_z is not None: - self.current_universe.planet.rotation_z = rotation_z - - self.camera_target.speed = self.get_wormhole_data("camera_target_init_speed") - camera.speed = self.get_wormhole_data("camera_init_speed") - - if self.last_universe is None: - self.camera_target.go_target = self.target_universe - self.camera_target.go_target_stage = "target_universe" - self.camera_target.go_target_hit = False - else: - self.camera_target.go_target = self.last_universe - self.last_universe.planet.enabled = True - - size_factor = self.get_wormhole_data("size_factor", universe=self.last_universe) - - self.scale_down(self.last_universe, scale_size=self.SIZE_SCALE * size_factor) - self.camera_target.go_target_stage = "last_universe" - self.camera_target.go_target_hit = False - self.scale_down(u) - self.camera_target.speed = self.get_wormhole_data("camera_target_speed") - camera.forward_speed = self.get_wormhole_data("camera_forward_speed") - - self.scale_up(self.current_universe) - # self.scale_down(self.target_universe) - - self.current_universe.planet.enabled = True - # self.current_universe.planet.set_light_off() - self.target_universe.planet.enabled = True - # self.target_universe.planet.set_light_off() - - 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() - # create_ambient_light(parent=camera) - - self.current_idx = -1 - self.target_idx = 0 - self.current_universe = None - self.body_update_reset() - self.universe_reset() - - # 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) - - self.text_panel = create_text_panel(font="fonts/DroidSansFallback.ttf", font_scale=1.3) - - def update_text_panel(self): - """ - 更新文字信息面板 - @param d_sun: - @return: - """ - panel_text = "虫洞穿越宇宙:\n\n当前宇宙:%s " % self.current_universe.name - panel_text += "\n\n下站宇宙:%s" % self.target_universe.name - if self.last_universe is not None: - panel_text += "\n\n上站宇宙:%s " % self.last_universe.name - - self.text_panel.text = panel_text - - def scale_up(self, obj): - if obj is None: - return - obj.planet.init_scale = self.SIZE_SCALE * 100 - - def scale_down(self, obj, scale_size=None): - if obj is None: - return - if scale_size is None: - scale_size = self.SIZE_SCALE - obj.planet.init_scale = scale_size - - def on_timer_changed(self, time_data): - self.target_universe.planet.rotation_y -= 0.5 - if self.last_universe is not None: - self.last_universe.planet.rotation_y += 0.3 - 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 - - camera_max_speed = self.get_wormhole_data("camera_max_speed") - camera_acc_speed = self.get_wormhole_data("camera_acc_speed") - camera_target_max_speed = self.get_wormhole_data("camera_target_max_speed", ) - - if self.camera_target.go_target is not None: - go_target = self.camera_target.go_target.planet - if self.camera_target.go_target_stage == "around_universe": - around_max_count = self.get_wormhole_data("around_max_count") - around_max_speed = self.get_wormhole_data("around_max_speed") - around_min_speed = self.get_wormhole_data("around_min_speed") - around_direction = self.get_wormhole_data("around_direction") - around_acc_speed = self.get_wormhole_data("around_acc_speed") - # around_target = camera - around_target = go_target - - self.camera_target.planet.look_at(around_target) - - # print(self.camera_target.planet.rotation_x,self.camera_target.planet.rotation_y,self.camera_target.planet.rotation_z) - planet_direction = getattr(self.camera_target.planet, around_direction) - - if not hasattr(self.camera_target, "around_speed"): - self.camera_target.around_speed = 0 - if not hasattr(self.camera_target, "around_count"): - self.camera_target.around_count = 0 - - if self.camera_target.around_count > around_max_count: - if hasattr(self.camera_target, "around_speed") and \ - abs(self.camera_target.around_speed) > abs(around_min_speed): - self.camera_target.around_speed -= around_acc_speed - else: - # delattr(self.camera_target, "around_speed") - delattr(self.camera_target, "around_count") - self.camera_target.go_target_stage = "last_universe" - self.camera_target.speed = self.get_wormhole_data("camera_init_speed") - else: - self.camera_target.around_speed += around_acc_speed - - if hasattr(self.camera_target, "around_speed"): - if abs(self.camera_target.around_speed) > abs(around_max_speed): - self.camera_target.around_speed = around_max_speed - - self.camera_target.planet.position += planet_direction * self.camera_target.around_speed - - print("around_speed", self.camera_target.around_speed) - - if hasattr(self.camera_target, "around_count"): - self.camera_target.around_count += 1 - - # camera.forward_speed = -0.05 - if camera.forward_speed < 0: - camera_forward_acc_speed = self.get_wormhole_data("camera_forward_acc_speed") - camera.forward_speed += camera_forward_acc_speed - else: - camera.forward_speed = 0 - - else: - self.camera_target.planet.look_at(go_target) - self.camera_target.planet.position = \ - lerp(self.camera_target.planet.position, go_target.position, - self.camera_target.speed * time.dt) - - self.camera_target.speed *= camera_acc_speed - if self.camera_target.speed > camera_target_max_speed: - self.camera_target.speed = camera_target_max_speed - - if self.camera_target.go_target_stage == "last_universe": - if self.camera_target.planet.intersects(go_target).hit: - if not self.camera_target.go_target_hit: - self.camera_target.go_target_hit = True - self.camera_target.go_target_stage = "around_universe" - self.camera_target.go_target = self.target_universe - self.camera_target.speed = self.get_wormhole_data("camera_init_speed") - camera.speed = 1 # 在看上一个宇宙时候,停留一会 - # # camera.forward_speed = -0.05 - # if camera.forward_speed < 0: - # camera_forward_acc_speed = self.get_wormhole_data("camera_forward_acc_speed") - # camera.forward_speed += camera_forward_acc_speed - # else: - # camera.forward_speed = 0 - if hasattr(self.camera_target, "around_speed"): - if abs(self.camera_target.around_speed) > abs(10): - around_acc_speed = self.get_wormhole_data("around_acc_speed") - around_direction = self.get_wormhole_data("around_direction") - planet_direction = getattr(self.camera_target.planet, around_direction) - - self.camera_target.around_speed -= around_acc_speed - self.camera_target.planet.position += planet_direction * self.camera_target.around_speed - else: - delattr(self.camera_target, "around_speed") - - elif self.camera_target.go_target_stage == "target_universe": - if self.camera_target.planet.intersects(go_target).hit and not self.camera_target.go_target_hit: - self.camera_target.go_target_hit = True - camera.forward_speed = 0 - # camera.speed = 3000 # TODO:这个不能反复执行 - - # self.camera_target.planet.position += self.camera_target.planet.forward*100 - # print(self.camera_target.planet.position) - camera.speed *= camera_acc_speed - if camera.speed > camera_max_speed: - camera.speed = camera_max_speed - - dd = distance(camera.position, self.target_universe.planet.position) - if camera.speed != 0: - camera.position = lerp(camera.position, self.target_universe.planet.position, camera.speed * time.dt / dd) - if camera.forward_speed != 0: - camera.position += camera.forward * camera.forward_speed - - # if self.camera_target.planet.intersects(self.target_universe.planet).hit: - if camera.intersects(self.target_universe.planet).hit: - self.universe_reset() - - self.update_text_panel() - - 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()