diff --git a/sim_scenes/wormhole_sim.py b/sim_scenes/wormhole_sim.py new file mode 100644 index 0000000000000000000000000000000000000000..590123282ba37e7c45f4800ddb17901f0de3bdd3 --- /dev/null +++ b/sim_scenes/wormhole_sim.py @@ -0,0 +1,225 @@ +# -*- 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 +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.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.create_universes() + self.bodies = [self.camera_target] + 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 = 100 + + for universe in self.universes: + universe.planet.collider = "sphere" + universe.planet.enabled = False + + def universe_reset(self): + self.camera_target.speed = 100 + camera.speed = 100 + 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] + 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.camera_target.go_target_stage = "last_universe" + self.camera_target.go_target_hit = False + + 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() + + + + # 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 * 100 + + def scale_down(self, obj): + if obj is None: + return + obj.planet.init_scale = self.SIZE_SCALE + + def on_timer_changed(self, time_data): + 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 + if self.camera_target.go_target is not None: + go_target = self.camera_target.go_target.planet + self.camera_target.planet.look_at(go_target) + self.camera_target.speed *= 1.02 + if self.camera_target.speed > 2000: + self.camera_target.speed = 2000 + self.camera_target.planet.position = \ + lerp(self.camera_target.planet.position, go_target.position, + self.camera_target.speed * time.dt) + + if self.camera_target.go_target_stage == "last_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 + self.camera_target.go_target_stage == "target_universe" + self.camera_target.go_target = self.target_universe + self.camera_target.speed = 100 + camera.speed = 100 # TODO:这个不能反复执行 + 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.speed = 1000 # TODO:这个不能反复执行 + + # self.camera_target.planet.position += self.camera_target.planet.forward*100 + # print(self.camera_target.planet.position) + camera.speed *= 1.02 + if camera.speed > 5000: + camera.speed = 5000 + + dd = distance(camera.position, self.target_universe.planet.position) + camera.position = lerp(camera.position, self.target_universe.planet.position, camera.speed * 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() + + 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/simulators/ursina/entities/entity_utils.py b/simulators/ursina/entities/entity_utils.py index 9f99db90a596ce068cf76980458e1e5288a75085..81e042fa28ee164f09160e3dd2c85035c91cd8fa 100644 --- a/simulators/ursina/entities/entity_utils.py +++ b/simulators/ursina/entities/entity_utils.py @@ -9,7 +9,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, DirectionalLight, distance + load_texture, held_keys, destroy, distance, \ + PointLight, DirectionalLight, AmbientLight from common import color_utils from common.image_utils import find_texture @@ -385,6 +386,27 @@ def create_fixed_star_lights(fixed_star): intensity=10, range=10, color=color.white) +def create_point_light(parent, light_color=None, position=(0, 0, 0)): + if light_color is None: + light_color = color.white + + light = PointLight(parent=parent, + position=position, + scale=1000000, + intensity=100000, color=light_color) + return light + + +def create_ambient_light(parent, light_color=None, position=(0, 0, 0)): + if light_color is None: + light_color = color.white + + light = AmbientLight(parent=parent, + position=position, + intensity=1000, color=light_color) + return light + + def get_value_direction_vectors(vectors): # 计算速度的大小 x, y, z = vectors[0], vectors[1], vectors[2]