From 4118345ef32bea358d1942a2676a85a8f3fa6e26 Mon Sep 17 00:00:00 2001 From: march3 Date: Fri, 4 Aug 2023 19:13:52 +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_scenes/func.py | 22 ++++++++ sim_scenes/tri_bodies/water_drop_01.py | 71 +++++++++++++++++++++++--- simulators/ursina_simulator.py | 12 +++-- 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/sim_scenes/func.py b/sim_scenes/func.py index ce62dd1..312e6ea 100644 --- a/sim_scenes/func.py +++ b/sim_scenes/func.py @@ -81,6 +81,28 @@ def set_camera_parent(target): camera.parent = target +def create_main_entity(target, rotation_x=None, rotation_y=None, rotation_z=None): + from ursina import Entity + + if hasattr(target, "planet"): + planet = target.planet + else: + planet = target + + main_entity = Entity(position=planet.position) + planet.position = [0, 0, 0] + planet.parent = main_entity + + if rotation_x is not None: + planet.rotation_x = rotation_x + if rotation_y is not None: + planet.rotation_y = rotation_y + if rotation_z is not None: + planet.rotation_z = rotation_z + + planet.main_entity = main_entity + + def camera_look_at(target, rotation_x=None, rotation_y=None, rotation_z=None): """ 让摄像机看向指定天体 diff --git a/sim_scenes/tri_bodies/water_drop_01.py b/sim_scenes/tri_bodies/water_drop_01.py index 4b74d1a..746de41 100644 --- a/sim_scenes/tri_bodies/water_drop_01.py +++ b/sim_scenes/tri_bodies/water_drop_01.py @@ -11,7 +11,7 @@ from bodies import Sun, Earth, Moon from objs import CoreValagaClas, SciFiBomber, WaterDrop from common.consts import AU, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH -from sim_scenes.func import ursina_run, camera_look_at +from sim_scenes.func import ursina_run, camera_look_at, create_main_entity, two_bodies_colliding from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.ursina_config import UrsinaConfig @@ -29,18 +29,20 @@ if __name__ == '__main__': # OFFSETTING = 0.01265 sun = Sun(name="太阳", size_scale=6e1, init_position=[0, 0, -3 * AU]).set_ignore_gravity(True) earth_size_scale = 2.5e2 + resolution = 100 earth = Earth(init_position=[0, -2500000, 0], texture="earth-huge.jpg", # rotate_angle=0, rotation_speed=0, - init_velocity=[OFFSETTING, 0, 0], size_scale=earth_size_scale).set_ignore_gravity( - True) # 地球放大 5 倍,距离保持不变 + init_velocity=[OFFSETTING, 0, 0], + size_scale=earth_size_scale).set_ignore_gravity(True).set_resolution(resolution) # 地球放大 5 倍,距离保持不变 # 创建云层(texture纹理图使用了透明云层的图片,云层的 size_scale 要稍微比地球大一点) clouds = Earth(name="地球云层", texture="transparent_clouds.png", # rotate_angle=0, rotation_speed=0, init_position=[0, -2500000, 0], - size_scale=earth_size_scale * 1.01, parent=earth).set_ignore_gravity(True) + size_scale=earth_size_scale * 1.01, + parent=earth).set_ignore_gravity(True).set_resolution(resolution) water_drop = WaterDrop(init_position=[AU / 300, 0, AU / 100], texture="drops_bright.png", @@ -56,6 +58,8 @@ if __name__ == '__main__': num_x = 10 num_y = 10 num_z = 10 + + d = 100000 num_x = 2 num_y = 2 num_z = 2 @@ -104,6 +108,37 @@ if __name__ == '__main__': import math + def calc_acceleration(current_pos, to_pos, desired_velocity): + """ + Calculate the acceleration vector components (x, y, z) for an object to move from its current position to a specified position, + considering the desired velocity. + @param current_pos: Current position of the object (in a three-dimensional coordinate system) + @param to_pos: Specified position (in a three-dimensional coordinate system) + @param desired_velocity: Desired velocity of the object + @return: Acceleration vector components (x, y, z) + """ + acceleration = [0, 0, 0] + # Calculate the differences in each dimension + diff_x = to_pos[0] - current_pos[0] + diff_y = to_pos[1] - current_pos[1] + diff_z = to_pos[2] - current_pos[2] + # Calculate the total distance + total_distance = math.sqrt(diff_x ** 2 + diff_y ** 2 + diff_z ** 2) + # Calculate the time required to reach the specified position + time = total_distance / desired_velocity + # Calculate the acceleration required to reach the desired velocity in the calculated time + acceleration_magnitude = desired_velocity / time + # Calculate the acceleration in each dimension + acceleration[0] = diff_x / time + acceleration[1] = diff_y / time + acceleration[2] = diff_z / time + # Adjust the acceleration using the acceleration magnitude + acceleration[0] *= acceleration_magnitude + acceleration[1] *= acceleration_magnitude + acceleration[2] *= acceleration_magnitude + return acceleration + + def calc_velocity(current_pos, to_pos, velocity_fact): """ Calculate the velocity vector components (x, y, z) for an object to move from its current position to a specified position, @@ -140,13 +175,31 @@ if __name__ == '__main__': water_drop.planet.rotation_z = 90 water_drop.velocity = [-WATER_SPEED, 0, 0] else: - velocity = calc_velocity(water_drop.position, ship_list[0].position, 1) - # water_drop.acceleration = [-9.8e-4, 0, 0] + velocity = calc_velocity(water_drop.position, ship_list[0].position, 5) water_drop.velocity = velocity + # acceleration = calc_acceleration(water_drop.position, ship_list[0].position, 1e-4) + # water_drop.acceleration = acceleration # [-9.8e-4, 0, 0] + + water_drop.look_at(ship_list[0], rotation_x=None, rotation_y=None, rotation_z=None) + camera_look_at(water_drop, rotation_z=0) # camera.y += UrsinaConfig.SCALE_FACTOR * 100 + for ship in ship_list: + # 循环判断每个石头与木星是否相碰撞,如果相碰撞就爆炸 + if two_bodies_colliding(water_drop, ship): + # velocity = water_drop.velocity + # acceleration = water_drop.acceleration + + # 将石头隐藏、设置引力无效后,展示爆炸效果 + water_drop.explode(ship, scale=1e1, fps=0.5) + # water_drop.planet.enabled = True + # water_drop.set_ignore_gravity(False) + # + # water_drop.velocity = velocity + # water_drop.acceleration = acceleration + def on_ready(): UrsinaConfig.trail_type = 'line' @@ -157,11 +210,13 @@ if __name__ == '__main__': elif isinstance(body, SciFiBomber): body.planet.rotation_x = -90 - water_drop.planet.rotation_z = 90 + water_drop.planet.main_entity.rotation_z = 90 - water_drop.init_position = (0, 0, 0) + water_drop.init_position = (0, 0, 2000) water_drop.init_velocity = [0, 0, 0] + create_main_entity(water_drop, rotation_y=90) + # 订阅事件后,上面2个函数功能才会起作用 # 运行前会触发 on_ready diff --git a/simulators/ursina_simulator.py b/simulators/ursina_simulator.py index befd348..6154478 100644 --- a/simulators/ursina_simulator.py +++ b/simulators/ursina_simulator.py @@ -93,7 +93,7 @@ class UrsinaSimulator(Simulator): return body.planet.enabled # Explosion animation - def body_explode(target=None): + def body_explode(target=None, scale=1, fps=6): # from panda3d.core import GeomUtils if body.planet.enabled: # TODO:下面代码保留,由于运行太快导致两个天体不是在表面碰撞,这样就要进行计算,希望在表面爆炸,但是需要耗费CPU资源,暂时注释 @@ -107,8 +107,10 @@ class UrsinaSimulator(Simulator): # explode_pos = body.planet.position # else: # print("explode_pos", explode_pos) - - explode_pos = body.planet.position + if hasattr(body.planet, "main_entity"): + explode_pos = body.planet.main_entity.position + else: + explode_pos = body.planet.position # 如果爆炸,则静止不动(停止并忽略引力) body.stop_and_ignore_gravity() body.planet.enabled = False @@ -117,11 +119,11 @@ class UrsinaSimulator(Simulator): # 获取体积数据(开三次方) volume_scale = pow(body.planet.model.get_bounds().volume, 1 / 3) # 根据体积、大小缩放判断爆炸的量 - scale = 3 * volume_scale * body.size_scale * UrsinaConfig.SCALE_FACTOR + scale = 3 * volume_scale * body.size_scale * UrsinaConfig.SCALE_FACTOR * scale print(scale, body) explode_ani = Animation(explosion_file, position=explode_pos, - scale=scale, fps=6, + scale=scale, fps=fps, loop=False, autoplay=True) explode_ani.set_light_off() -- GitLab