# -*- 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 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 = "bg_pan.jpg" worms_cosmic_bg = "bg_pan_red.jpg" class UniverseBody(Body): def __init__(self, name="虫洞", mass=1.9891e35, init_position=[0, 0, 0], init_velocity=[0, 0, 0], color=(0, 0, 0), texture=None, density=1.408e20, size_scale=1.0, distance_scale=1.0, rotation_speed=0, ignore_mass=False, trail_color=None, show_name=False): params = { "name": name, "mass": mass, "init_position": init_position, "init_velocity": init_velocity, "density": density, "color": color, "texture": texture, "size_scale": size_scale * 10000, "distance_scale": distance_scale, "rotation_speed": rotation_speed, "ignore_mass": ignore_mass, "trail_color": trail_color, "show_name": show_name } super().__init__(**params) class WormHole(UniverseBody): def __init__(self, name="虫洞", mass=1.9891e35, texture=worms_cosmic_bg, size_scale=1.0, init_position=[0, 0, 0], init_velocity=[0, 0, 0]): params = { "name": name, "mass": mass, "init_position": init_position, "init_velocity": init_velocity, "density": 1.408e20, # "color": color, "texture": texture, "size_scale": size_scale, # "distance_scale": distance_scale, # "rotation_speed": rotation_speed, # "ignore_mass": ignore_mass, # "trail_color": trail_color, # "show_name": show_name } super().__init__(**params) class OursUniverse(UniverseBody): def __init__(self, name="我们的宇宙", texture=ours_cosmic_bg, size_scale=1.0, init_position=[0, 0, 0], init_velocity=[0, 0, 0]): params = { "name": name, "mass": 1.9891e35, "init_position": init_position, "init_velocity": init_velocity, "density": 1.408e20, # "color": color, "texture": texture, "size_scale": size_scale, # "distance_scale": distance_scale, # "ignore_mass": ignore_mass, # "trail_color": trail_color, # "show_name": show_name } super().__init__(**params) if __name__ == '__main__': """ """ # 代码案例如下: SIZE_SCALE = 1 # 生成的太阳放大 50 倍 RUN_DIAMETER = 1.392e6 velocity_rate = 22 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=SIZE_SCALE * 1e1) # .set_ignore_gravity(True) ours_universe = OursUniverse( # size_scale=SIZE_SCALE * 1e3, size_scale=SIZE_SCALE, init_position=[0, 0, -AU/120], init_velocity=[0, 0, 0], ).set_ignore_gravity(True) worm_hole = WormHole( # init_position=[RUN_DIAMETER, RUN_DIAMETER, 0], init_position=[0, 0, AU/120], init_velocity=[0, 0, 0], size_scale=SIZE_SCALE).set_ignore_gravity(True) bodies = [ camera_target, ours_universe, worm_hole ] # camera_position = [0, 0, 0] def on_ready(): """ 事件绑定后,模拟器运行前会触发 @return: """ # 创建天空 camera.clip_plane_near = 0.001 camera.clip_plane_far = 10000000000000 # create_sphere_sky(scale=200000) application.time_scale = 0.001 # camera.scale = 1000 # camera.parent = camera_target.planet # camera.rotation_x = 90 worm_hole.planet.rotation_y = 30 ours_universe.planet.rotation_y = 130 camera_look_at(camera_target) camera.collider = "sphere" worm_hole.planet.collider = "sphere" ours_universe.planet.init_scale = SIZE_SCALE * 1000 # camera_position = camera.position def on_timer_changed(time_data): global camera_position # return # pass # camera_look_at(camera_target) # camera.rotation_x -= 2 camera_target.planet.look_at(worm_hole.planet) if camera.intersects(worm_hole.planet).hit: # worm_hole.planet.init_scale = SIZE_SCALE * 1000 ours_universe.planet.init_scale = SIZE_SCALE if worm_hole.planet.init_scale < SIZE_SCALE*1000: worm_hole.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.005 elif abs(camera.init_rotation_y - camera.rotation_y) < 90: camera.rotation_y_v += 0.01 elif abs(camera.init_rotation_y - camera.rotation_y) < 120: camera.rotation_y_v -= 0.01 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, camera_target.planet.position, 0.3e-2) # camera_position = [camera_position[0], camera_position[1], camera_position[2] - 0.01] # camera.position = camera_position # 订阅事件后,上面2个函数功能才会起作用 # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(on_timer_changed) # 运行前会触发 on_ready UrsinaEvent.on_ready_subscription(on_ready) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(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)