提交 0d1da2e1 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 c7aa8388
......@@ -11,8 +11,38 @@ from objs import RockSnow, Rock, create_rock
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY
from sim_scenes.func import ursina_run, camera_look_at, 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_event import UrsinaEvent
def create_comet(index, gravity_only_for):
"""
随机生成石头
@param index: 索引号
@param gravity_only_for: 指定一个天体,石头的引力只对该天体有效
@return:
"""
# 随机生成石头的位置和初始速度信息
pos = [-r * random.randint(120, 200) / 100,
-r * random.randint(120, 200) / 1000,
-r * random.randint(100, 300) / 100]
# 随机速度
vel = [0, -random.randint(90, 200) / 30, 0]
# 石头随机大小
size_scale = random.randint(600, 1200)
# 随机创建石头
comet = create_rock(no=index % 8 + 1, name=f'岩石{index + 1}', mass=4.4e10,
size_scale=size_scale, color=(255, 200, 0),
init_position=pos, init_velocity=vel,
gravity_only_for=[gravity_only_for],
)
# 给石头一个随机旋转的方向和值
comet.rotation = [0, 0, 0]
comet.rotation[random.randint(0, 2)] = random.randint(90, 200) / 100
return comet
if __name__ == '__main__':
"""
彗木相撞模拟
......@@ -24,53 +54,47 @@ if __name__ == '__main__':
size_scale=1, texture="jupiter_hd.jpg")
bodies = [jupiter]
rocks = []
comets = []
r = jupiter.raduis
for i in range(30):
# 随机生成岩石位置和初始速度信息
pos = [-r * random.randint(120, 200) / 100,
-r * random.randint(120, 200) / 1000,
-r * random.randint(100, 300) / 100]
# 随机速度
vel = [0, -random.randint(90, 200) / 30, 0]
size_scale = random.randint(600, 1200)
rock = create_rock(no=i % 8 + 1, name=f'岩石{i + 1}', mass=4.4e10,
size_scale=size_scale, color=(255, 200, 0),
init_position=pos, init_velocity=vel,
gravity_only_for=[jupiter],
)
# 岩石随机旋转量
rock.rotation = [0, 0, 0]
rock.rotation[random.randint(0, 2)] = random.randint(90, 200) / 100
bodies.append(rock)
rocks.append(rock)
# 随机生成石头
comet = create_comet(i, gravity_only_for=jupiter)
bodies.append(comet)
comets.append(comet)
def on_reset():
for rock in rocks:
rock.set_visible(True)
rock.ignore_mass = False
# 重置后恢复所有石头的状态(石头可见、引力有效)
for comet in comets:
comet.set_visible(True)
comet.ignore_mass = False
def on_ready():
# 运行前触发
# 创建太阳光
create_directional_light(position=(200, 0, -300), target=jupiter)
# 摄像机看向木星
camera_look_at(jupiter, rotation_z=0)
def on_timer_changed(time_data: TimeData):
for rock in rocks:
if rock.visibled:
rock.planet.rotation += rock.rotation
# 循环判断每个抛出物与木星是否相碰撞
if two_bodies_colliding(rock, jupiter):
# 岩石爆炸
rock.explode(jupiter)
UrsinaEvent.on_reset_subscription(on_reset)
UrsinaEvent.on_ready_subscription(on_ready)
UrsinaEvent.on_timer_changed_subscription(on_timer_changed)
# 运行中,每时每刻都会触发
for comet in comets:
if comet.visibled:
# 如果是否可见,则旋转石头
comet.planet.rotation += comet.rotation
# 循环判断每个石头与木星是否相碰撞,如果相碰撞就爆炸
if two_bodies_colliding(comet, jupiter):
# 将石头隐藏、设置引力无效后,展示爆炸效果
comet.explode(jupiter)
# 订阅事件
UrsinaEvent.on_reset_subscription(on_reset) # 重置了会触发 on_reset
UrsinaEvent.on_ready_subscription(on_ready) # 运行前会触发 on_ready
UrsinaEvent.on_timer_changed_subscription(on_timer_changed) # 运行中,每时每刻都会触发 on_timer_changed
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
......
......@@ -9,7 +9,7 @@
# 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, distance
load_texture, held_keys, destroy, PointLight, DirectionalLight, distance
from simulators.ursina.entities.body_trail import BodyTrail, BodyTrailLine
from simulators.ursina.ursina_config import UrsinaConfig
......@@ -37,7 +37,7 @@ def create_name_text(parent):
if text_color is None:
text_color = get_inverse_color(b_color)
else:
text_color = (text_color[0]/255, text_color[1]/255, text_color[2]/255)
text_color = (text_color[0] / 255, text_color[1] / 255, text_color[2] / 255)
name_text.set_light_off()
name_text.color = color.rgba(text_color[0], text_color[1], text_color[2], 1)
parent.name_text = name_text
......@@ -159,6 +159,33 @@ def create_trail_sphere(parent, pos):
# return value, direction
def create_directional_light(position, target=None, shadows=False, light_color=None):
"""
创建平行光(DirectionalLight)
@param position: 光源位置
@param target: 光源指向目标
@param shadows: 是否支持阴影
@param light_color: 光的颜色
@return:
"""
from ursina.shaders import lit_with_shadows_shader
if shadows:
Entity.default_shader = lit_with_shadows_shader
if light_color is None:
light_color = color.white
else:
light_color = color.rgba(light_color[0] / 255, light_color[1] / 255, light_color[2] / 255, 1)
light = DirectionalLight(position=position, intensity=10, range=10, color=light_color)
if target is not None:
if hasattr(target, "planet"):
if hasattr(target.planet, "main_entity"):
light.look_at(target.planet.main_entity)
else:
light.look_at(target.planet)
else:
light.look_at(target)
def create_trail_line(parent, pos):
"""
在天体当前的位置创建一个拖尾球体
......
......@@ -105,6 +105,7 @@ class UrsinaSimulator(Simulator):
position=body.planet.position,
scale=scale, fps=6,
loop=False, autoplay=True)
explode_ani.set_light_off()
if target is not None:
if hasattr(target, "planet"):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册