From 33306154b46b8536856d5e755fa7204a1f6457ce Mon Sep 17 00:00:00 2001 From: march3 Date: Thu, 7 Dec 2023 21:36:07 +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/the_lost_planet.py | 408 ++++++++++++++++++++++--------------- 1 file changed, 248 insertions(+), 160 deletions(-) diff --git a/sim_lab/the_lost_planet.py b/sim_lab/the_lost_planet.py index ec9047d..7432267 100644 --- a/sim_lab/the_lost_planet.py +++ b/sim_lab/the_lost_planet.py @@ -15,79 +15,80 @@ from sim_scenes.universe_sim_scenes import UniverseSimScenes from simulators.func import ext_fun_for_method from simulators.ursina.ursina_event import UrsinaEvent -if __name__ == '__main__': - sun = Sun(size_scale=5e2).set_resolution(60) # 太阳放大 500 倍 - sun.glows = (30, 1.005, 0.03) - asteroids = Asteroids(size_scale=1.08e2, parent=sun) # 小行星模拟(仅 ursina 模拟器支持) - - # 环状星群带(inner_radius, outer_radius, subdivisions) - # inner_radius:内圆半径 outer_radius:外圆半径,subdivisions:细分数,控制圆环的细节和精度 - asteroids.torus_zone = 4.7, 5.5, 64 - - moon = Moon(size_scale=3e3, init_position=[0, 0, (0.4 + 2.4) * AU], distance_scale=1.8) - ceres = Ceres(size_scale=3e3, distance_scale=1.7) - earth = Earth(size_scale=3e3, distance_scale=3.8) - mars = Mars(size_scale=3e3, distance_scale=2.9) - jupiter = Jupiter(size_scale=0.68e3, distance_scale=1.15) - saturn = Saturn(size_scale=0.68e3, distance_scale=0.74) - bodies = [ - sun, - Mercury(size_scale=3e3, distance_scale=7), # 水星放大 4000 倍 - Venus(size_scale=3e3, distance_scale=4.3), # 金星放大 4000 倍 - earth, # 地球放大 4000 倍 - mars, # 火星放大 4000 倍 - asteroids, - moon, - ceres, - # Earth(size_scale=3e3, init_position=[0, 0, (2.17) * AU]), # 地球放大 4000 倍 - # Earth(size_scale=3e3, init_position=[0, 0, (3.64) * AU]), # 地球放大 4000 倍 - jupiter, # 木星放大 680 倍 - saturn, # 土星放大 680 倍 - Uranus(size_scale=0.8e3, distance_scale=0.42), # 天王星放大 800 倍 - Neptune(size_scale=1e3, distance_scale=0.3), # 海王星放大 1000 倍 - ] - # 水星 0.4AU - # 金星 0.4+0.3 AU - # 地球 0.4+0.6 AU - # 火星 0.4+1.2 AU - # 木星 0.4+4.8 AU - # 土星 0.4+9.6 AU - # 天王星 0.4+19.2 AU - # d = (n+4)/10 - # an = 0.4+0.3×(2n-2) - planet_no = -1 - for idx, body in enumerate(bodies): - if isinstance(body, Asteroids): - continue - body.rotation_speed = 0 - planet_no += 1 - # body.init_velocity = [0, 0, 0] - # an = 0.4 + 0.3 * pow(2,idx) - # an = (idx+4)/10 - # 其中k=0,1,2,4,8,16,32,64,128 (0以后数字为2的2次方) - # 行星 公式推得值 实测值 - # 金星 0.7 0.72 - # 地球 1 1 - # 火星 1.6 1.52 - # 谷神星 2.8 2.9 [1] - # 木星 5.2 5.2 - # 土星 10 9.54 - # 天王星 19.6 19.18 - # 海王星 38.8 30.06 - # 冥王星 77.2 39.44 - # 提丢斯-波得定则 - # https://baike.baidu.com/item/%E6%8F%90%E4%B8%A2%E6%96%AF-%E6%B3%A2%E5%BE%97%E5%AE%9A%E5%88%99/859407 - # 小行星 2.17-3.64天文单位 - if planet_no == 0: - continue - elif planet_no == 1: - an = 0.4 - else: - an = 0.4 + 0.3 * pow(2, planet_no - 2) - print(body.name, an, body.position[2] / AU) +class TheLostPlanetSim(UniverseSimScenes): + def __init__(self): + self.sun = Sun(size_scale=5e2).set_resolution(60) # 太阳放大 500 倍 + self.sun.glows = (30, 1.005, 0.03) + # self.asteroids = Asteroids(size_scale=1.08e2, parent=self.sun) # 小行星模拟(仅 ursina 模拟器支持) + + # 环状星群带(inner_radius, outer_radius, subdivisions) + # inner_radius:内圆半径 outer_radius:外圆半径,subdivisions:细分数,控制圆环的细节和精度 + # self.asteroids.torus_zone = 4.7, 5.5, 64 + + self.moon = Moon(size_scale=3e3, init_position=[0, 0, (0.4 + 2.4) * AU], distance_scale=1.76) + # ceres = Ceres(size_scale=3e3, distance_scale=1.7) + self.earth = Earth(size_scale=3e3, distance_scale=3.8) + self.mars = Mars(size_scale=3e3, distance_scale=2.9) + self.jupiter = Jupiter(size_scale=0.68e3, distance_scale=1.12) + self.saturn = Saturn(size_scale=0.68e3, distance_scale=0.74) + self.bodies = [ + self.sun, + Mercury(size_scale=3e3, distance_scale=7.3), # 水星放大 4000 倍 + Venus(size_scale=3e3, distance_scale=4.5), # 金星放大 4000 倍 + self.earth, # 地球放大 4000 倍 + self.mars, # 火星放大 4000 倍 + # asteroids, + self.moon, + # ceres, + # Earth(size_scale=3e3, init_position=[0, 0, (2.17) * AU]), # 地球放大 4000 倍 + # Earth(size_scale=3e3, init_position=[0, 0, (3.64) * AU]), # 地球放大 4000 倍 + self.jupiter, # 木星放大 680 倍 + self.saturn, # 土星放大 680 倍 + Uranus(size_scale=0.8e3, distance_scale=0.42), # 天王星放大 800 倍 + Neptune(size_scale=1e3, distance_scale=0.3), # 海王星放大 1000 倍 + ] + # 水星 0.4AU + # 金星 0.4+0.3 AU + # 地球 0.4+0.6 AU + # 火星 0.4+1.2 AU + # 木星 0.4+4.8 AU + # 土星 0.4+9.6 AU + # 天王星 0.4+19.2 AU + # d = (n+4)/10 + # an = 0.4+0.3×(2n-2) + planet_no = -1 + for idx, body in enumerate(self.bodies): + if isinstance(body, Asteroids): + continue + body.rotation_speed = 0 + planet_no += 1 + # body.init_velocity = [0, 0, 0] + # an = 0.4 + 0.3 * pow(2,idx) + # an = (idx+4)/10 + # 其中k=0,1,2,4,8,16,32,64,128 (0以后数字为2的2次方) + # 行星 公式推得值 实测值 + # 金星 0.7 0.72 + # 地球 1 1 + # 火星 1.6 1.52 + # 谷神星 2.8 2.9 [1] + # 木星 5.2 5.2 + # 土星 10 9.54 + # 天王星 19.6 19.18 + # 海王星 38.8 30.06 + # 冥王星 77.2 39.44 + # 提丢斯-波得定则 + # https://baike.baidu.com/item/%E6%8F%90%E4%B8%A2%E6%96%AF-%E6%B3%A2%E5%BE%97%E5%AE%9A%E5%88%99/859407 + # 小行星 2.17-3.64天文单位 + if planet_no == 0: + continue + elif planet_no == 1: + an = 0.4 + else: + an = 0.4 + 0.3 * pow(2, planet_no - 2) + print(body.name, an, body.position[2] / AU) - def on_ready(): + def on_ready(self): """ 事件绑定后,模拟器运行前会触发 @return: @@ -99,7 +100,7 @@ if __name__ == '__main__': camera.clip_plane_near = 0.1 camera.clip_plane_far = 1000000 - camera.look_at(jupiter.planet) + camera.look_at(self.jupiter.planet) # camera.look_at(sun.planet) camera.rotation_z -= 90 @@ -109,13 +110,16 @@ if __name__ == '__main__': # UniverseSimScenes.show_grid_axises() - asteroids.planet.enabled = False - moon.planet.enabled = False - ceres.planet.enabled = False + # self.asteroids.planet.enabled = False + self.moon.planet.enabled = False + # ceres.planet.enabled = False - - def set_alpha_animation(body, begin_alpha, end_alpha, interval): - planet = body.planet + def set_alpha_animation(self, body, begin_alpha, end_alpha, interval, is_destroy=False): + from ursina import destroy + if hasattr(body, "planet"): + planet = body.planet + else: + planet = body planet.alpha = begin_alpha if begin_alpha > end_alpha: interval = -abs(interval) @@ -135,127 +139,211 @@ if __name__ == '__main__': planet.enabled = (alpha > 0) planet.alpha = alpha + if is_destroy and not planet.enabled: + destroy(planet) # planet.color = Vec4(planet.color[0], planet.color[1], planet.color[2], alpha) - print(planet.alpha) + # print(planet.alpha) planet.update = alpha_animation # ext_fun_for_method(planet, after_run_fun=alpha_animation) - - def create_asteroid(): + def create_asteroid(self, init_angle=89.5): from ursina import Entity, color, Vec3 import math import random - pos = moon.planet.position # + Vec3() - radius = moon.planet.position[2] + 40 * random.random() - 20 # * moon.distance_scale + pos = self.moon.planet.position # + Vec3() + radius = self.moon.planet.position[2] + 40 * random.random() - 20 # * moon.distance_scale asteroid = Entity(model='sphere', position=pos, color=color.white, scale=1.5) - asteroid.s_angle = 89.5 + asteroid.s_angle = init_angle y = 10 * random.random() - 5 + def rotation(): - x = sun.planet.x + radius * math.cos(asteroid.s_angle) - z = sun.planet.z + radius * math.sin(asteroid.s_angle) + x = self.sun.planet.x + radius * math.cos(asteroid.s_angle) + z = self.sun.planet.z + radius * math.sin(asteroid.s_angle) asteroid.position = (x, y, z) - speed = random.random() / 100 + speed = random.random() / 50 asteroid.s_angle += speed asteroid.update = rotation + return asteroid + def create_asteroids(self): + self.asteroids = [] + for i in range(500): + self.asteroids.append(self.create_asteroid(i)) - # - # def after_ready(): - # from ursina import camera, Vec3 - # camera.position = Vec3(0,149.60,-665.76) - # camera.world_position = Vec3(-14.71,-98.38,0) - # - def on_timer_changed(time_data): - from ursina import camera, Vec3, distance - import math - # print(time_data.years) - if time_data.years > 1 and not hasattr(asteroids, "years_1"): - - set_alpha_animation(asteroids, 0.0, 1.0, 0.01) - setattr(asteroids, "years_1", True) - elif time_data.years > 4 and not hasattr(asteroids, "years_5"): - set_alpha_animation(asteroids, 1.0, 0.0, 0.01) - setattr(asteroids, "years_5", True) - elif time_data.years > 6 and not hasattr(moon, "years_6"): - moon.planet.look_at(mars.planet) - moon.planet.update = lambda: None - set_alpha_animation(moon, 0.0, 1.0, 0.005) - setattr(moon, "years_6", True) - elif time_data.years > 8 and not hasattr(asteroids, "years_8"): - if not hasattr(asteroids, "c_time"): - asteroids.c_time = time.time() - c_time = time.time() - # set_alpha_animation(asteroids, 0.0, 1.0, 0.01) - if c_time - asteroids.c_time > 0.1: - asteroids.c_time = c_time - create_asteroid() - - if time_data.years > 30 and not hasattr(moon, "mars_rotation"): - setattr(asteroids, "years_8", True) - moon.planet.look_at(mars.planet) - radius = 12 - d = distance(moon.planet, mars.planet.position) - if d > 12: - moon.planet.position += moon.planet.forward * 0.1 - else: - if not hasattr(mars, "moon_angle"): - setattr(mars, "moon_angle", 90) + # def clear_asteroids(self): + # for a in self.asteroids: + # a.enabled = False - moon_angle = getattr(mars, "moon_angle") - x = mars.planet.x + radius * math.cos(moon_angle) - z = mars.planet.z + radius * math.sin(moon_angle) - moon.planet.position = (x, 0, z) + def asteroid_fade_in(self): + """ + 小行星群渐渐显示 + @return: + """ + self.create_asteroids() + for a in self.asteroids: + self.set_alpha_animation(a, 0.0, 1.0, 0.01) - setattr(mars, "moon_angle", moon_angle + 0.08) + def asteroid_fade_out(self): + """ + 小行星群渐渐消失 + @return: + """ + for a in self.asteroids: + self.set_alpha_animation(a, 1.0, 0.0, 0.01, is_destroy=True) - if moon_angle >= 110: - setattr(moon, "mars_rotation", True) + def moon_fade_in(self): + """ + 月球渐渐显示 + @return: + """ + self.moon.planet.look_at(self.mars.planet) + self.moon.planet.update = lambda: None + self.set_alpha_animation(self.moon, 0.0, 1.0, 0.005) + + def moon_renovation(self): + """ + 月球改造中 + @return: + """ + if not hasattr(self, "moon_redesign_last_time"): + self.moon_redesign_last_time = time.time() + c_time = time.time() + # set_alpha_animation(asteroids, 0.0, 1.0, 0.01) + if c_time - self.moon_redesign_last_time > 0.05: + self.moon_redesign_last_time = c_time + self.create_asteroid() + + def moon_move_to_target_and_rotation(self, target, rotation_radius, end_angle, end_tag, + forward=0.1, + angle_val=0.08): + from ursina import camera, Vec3, distance + import math + if hasattr(target, "planet"): + target_planet = target.planet.main_entity + else: + target_planet = target.main_entity - print("moon_angle", moon_angle) + self.moon.planet.look_at(target_planet) - elif hasattr(mars, "moon_angle") and not hasattr(moon, "earth_rotation"): - earth_target = earth.planet.main_entity - moon.planet.look_at(earth_target) - radius = 15 - d = distance(moon.planet.position, earth_target.position) - if d > 15: - moon.planet.position += moon.planet.forward * 0.1 - else: - if not hasattr(earth, "moon_angle"): - setattr(earth, "moon_angle", 90) + d = distance(self.moon.planet, target_planet) + if d > rotation_radius: + self.moon.planet.position += self.moon.planet.forward * forward + else: + if not hasattr(target_planet, "moon_angle"): + setattr(target_planet, "moon_angle", 90) + + moon_angle = getattr(target_planet, "moon_angle") + x = target_planet.x + rotation_radius * math.cos(moon_angle) + z = target_planet.z + rotation_radius * math.sin(moon_angle) + self.moon.planet.position = (x, 0, z) - moon_angle = getattr(earth, "moon_angle") - x = earth_target.x + radius * math.cos(moon_angle) - z = earth_target.z + radius * math.sin(moon_angle) - moon.planet.position = (x, 0, z) + setattr(target_planet, "moon_angle", moon_angle + angle_val) - setattr(earth, "moon_angle", moon_angle + 0.08) + if moon_angle >= end_angle: + setattr(self, end_tag, True) - if moon_angle >= 360 * 2 + 90: - setattr(moon, "earth_rotation", True) + # print("moon_angle", moon_angle) - print("moon_angle", moon_angle) - # moon.planet.world_rotation_z = 90 - # moon.planet.position += moon.planet.right * 0.1 + def on_timer_changed(self, time_data): + from ursina import camera, Vec3, distance + import math - # setattr(moon, "years_8", True) + if time_data.years > 1 and not hasattr(self, "step_01"): + # 小行星群渐渐显示,运行一次 + self.asteroid_fade_in() + setattr(self, "step_01", True) # 控制运行一次 + elif time_data.years > 6 and not hasattr(self, "step_02"): + # 小行星群渐渐消失,运行一次 + self.asteroid_fade_out() + setattr(self, "step_02", True) # 控制运行一次 + elif time_data.years > 8 and not hasattr(self.moon, "step_03"): + # 月球渐渐显示,运行一次 + self.moon_fade_in() + setattr(self.moon, "step_03", True) # 控制运行一次 + elif time_data.years > 10 and not hasattr(self, "step_04"): + # 月球改造中,运行多次 + self.moon_renovation() + + if time_data.years > 25 and not hasattr(self, "moon_around_mars"): + setattr(self, "step_04", True) + self.moon_move_to_target_and_rotation(target=self.mars, + rotation_radius=12, + end_angle=110, + end_tag="moon_around_mars", + forward=0.03, angle_val=0.05) + # self.moon.planet.look_at(self.mars.planet) + # radius = 12 + # d = distance(self.moon.planet, self.mars.planet.position) + # if d > 12: + # self.moon.planet.position += self.moon.planet.forward * 0.1 + # else: + # if not hasattr(self.mars, "moon_angle"): + # setattr(self.mars, "moon_angle", 90) + # + # moon_angle = getattr(self.mars, "moon_angle") + # x = self.mars.planet.x + radius * math.cos(moon_angle) + # z = self.mars.planet.z + radius * math.sin(moon_angle) + # self.moon.planet.position = (x, 0, z) + # + # setattr(self.mars, "moon_angle", moon_angle + 0.08) + # + # if moon_angle >= 110: + # setattr(self.moon, "mars_rotation", True) + + # print("moon_angle", moon_angle) + + elif hasattr(self, "moon_around_mars") and not hasattr(self, "moon_around_earth"): + self.moon_move_to_target_and_rotation(target=self.earth, + rotation_radius=15, + end_angle=360, + end_tag="moon_around_earth", + forward=0.03, angle_val=0.05) + + # earth_target = self.earth.planet.main_entity + # self.moon.planet.look_at(earth_target) + # radius = 15 + # d = distance(self.moon.planet.position, earth_target.position) + # if d > 15: + # self.moon.planet.position += self.moon.planet.forward * 0.1 + # else: + # if not hasattr(self.earth, "moon_angle"): + # setattr(self.earth, "moon_angle", 90) + # + # moon_angle = getattr(self.earth, "moon_angle") + # x = earth_target.x + radius * math.cos(moon_angle) + # z = earth_target.z + radius * math.sin(moon_angle) + # self.moon.planet.position = (x, 0, z) + # + # setattr(self.earth, "moon_angle", moon_angle + 0.08) + + # if moon_angle >= 360 * 2 + 90: + # setattr(moon, "earth_rotation", True) + + # print("moon_angle", moon_angle) + # moon.planet.world_rotation_z = 90 + # moon.planet.position += moon.planet.right * 0.1 + + # setattr(moon, "years_8", True) # elif time_data.years > 15 and not hasattr(moon, "years_15"): # set_alpha_animation(moon, 1.0, 0.0, 0.05) # setattr(moon, "years_15", True) +if __name__ == '__main__': + sim = TheLostPlanetSim() + # UniverseSimScenes.set_window_size((1920, 1079), False) # 运行前会触发 on_ready - UrsinaEvent.on_ready_subscription(on_ready) + UrsinaEvent.on_ready_subscription(sim.on_ready) # UrsinaEvent.after_ready_subscription(after_ready) - UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- - ursina_run(bodies, + ursina_run(sim.bodies, SECONDS_PER_YEAR, gravity_works=False, show_exit_button=False, -- GitLab