Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Python_超人
宇宙模拟器
提交
deadd2c8
宇宙模拟器
项目概览
Python_超人
/
宇宙模拟器
通知
19
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
宇宙模拟器
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
deadd2c8
编写于
7月 04, 2023
作者:
三月三net
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Python超人-宇宙模拟器
上级
13a2fe21
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
213 addition
and
3 deletion
+213
-3
common/func.py
common/func.py
+10
-0
sim_scenes/func.py
sim_scenes/func.py
+25
-0
sim_scenes/science/speed_of_light_3d.py
sim_scenes/science/speed_of_light_3d.py
+28
-3
tools/sim_video_3d_cap.py
tools/sim_video_3d_cap.py
+150
-0
未找到文件。
common/func.py
浏览文件 @
deadd2c8
...
@@ -12,6 +12,7 @@ import numpy as np
...
@@ -12,6 +12,7 @@ import numpy as np
import
random
import
random
import
os
import
os
import
math
import
math
import
time
def
get_dominant_colors
(
infile
,
resize
=
(
20
,
20
)):
def
get_dominant_colors
(
infile
,
resize
=
(
20
,
20
)):
...
@@ -96,6 +97,15 @@ def find_file(file_path, default_val=None, find_deep=5):
...
@@ -96,6 +97,15 @@ def find_file(file_path, default_val=None, find_deep=5):
return
default_val
return
default_val
def
wait_for
(
secs
):
wait
=
secs
*
800
while
True
:
if
wait
<=
0
:
return
time
.
sleep
(
0.001
)
wait
-=
1
def
calculate_distance
(
pos1
,
pos2
=
[
0
,
0
,
0
]):
def
calculate_distance
(
pos1
,
pos2
=
[
0
,
0
,
0
]):
"""
"""
计算两点间的距离
计算两点间的距离
...
...
sim_scenes/func.py
浏览文件 @
deadd2c8
...
@@ -285,6 +285,31 @@ def create_light_ship(size_scale, init_position, speed=LIGHT_SPEED):
...
@@ -285,6 +285,31 @@ def create_light_ship(size_scale, init_position, speed=LIGHT_SPEED):
init_velocity
=
[
0
,
0
,
speed
]).
set_light_disable
(
True
)
init_velocity
=
[
0
,
0
,
speed
]).
set_light_disable
(
True
)
def
create_3d_card
(
left
=-
.
885
,
top
=
0.495
,
width
=
0.02
,
height
=
0.02
):
# 创建一个 Panel 组件
from
ursina
import
Text
,
Panel
,
color
,
camera
,
Vec3
from
simulators.ursina.ursina_config
import
UrsinaConfig
panel
=
Panel
(
parent
=
None
,
model
=
'quad'
,
# texture='white_cube',
color
=
color
.
black
,
origin
=
(
-
.
48
,
.
48
,
-
.
48
),
scale
=
(
width
,
height
),
position
=
(
left
,
top
,
0
)
)
def
switch_color
():
if
panel
.
color
==
color
.
black
:
panel
.
color
=
color
.
white
else
:
panel
.
color
=
color
.
black
panel
.
switch_color
=
switch_color
return
panel
def
create_text_panel
(
width
=
0.35
,
height
=
.
5
):
def
create_text_panel
(
width
=
0.35
,
height
=
.
5
):
# 创建一个 Panel 组件
# 创建一个 Panel 组件
from
ursina
import
Text
,
Panel
,
color
,
camera
,
Vec3
from
ursina
import
Text
,
Panel
,
color
,
camera
,
Vec3
...
...
sim_scenes/science/speed_of_light_3d.py
浏览文件 @
deadd2c8
...
@@ -7,8 +7,10 @@
...
@@ -7,8 +7,10 @@
# python_version :3.8
# python_version :3.8
# ==============================================================================
# ==============================================================================
import
sys
import
sys
import
time
from
common.func
import
wait_for
from
common.consts
import
AU
from
common.consts
import
AU
from
sim_scenes.func
import
ursina_run
,
create_solar_system_bodies
,
create_light_ship
from
sim_scenes.func
import
ursina_run
,
create_solar_system_bodies
,
create_light_ship
,
create_3d_card
from
common.consts
import
LIGHT_SPEED
from
common.consts
import
LIGHT_SPEED
from
sim_scenes.science.speed_of_light_init
import
SpeedOfLightInit
from
sim_scenes.science.speed_of_light_init
import
SpeedOfLightInit
...
@@ -42,7 +44,7 @@ else:
...
@@ -42,7 +44,7 @@ else:
camera_pos
=
"right"
camera_pos
=
"right"
print
(
"camera_pos:"
,
camera_pos
)
print
(
"camera_pos:"
,
camera_pos
)
camera_l2r
=
0.1
*
AU
camera_l2r
=
0.
0
1
*
AU
if
camera_pos
==
"right"
:
# 摄像机右眼
if
camera_pos
==
"right"
:
# 摄像机右眼
init
.
light_init_position
[
0
]
+=
camera_l2r
init
.
light_init_position
[
0
]
+=
camera_l2r
...
@@ -56,9 +58,22 @@ init.light_init_position[1] = 1000000
...
@@ -56,9 +58,22 @@ init.light_init_position[1] = 1000000
# 从 init 对象中获取 光体的大小(light_size_scale),光体的位置(light_init_position)
# 从 init 对象中获取 光体的大小(light_size_scale),光体的位置(light_init_position)
# 创建一个以光速前进的天体(模拟一个光子) speed=1光速=299792.458千米/秒,注意:质量为0才能达到光速,虽然如此,但也可以试试超光速
# 创建一个以光速前进的天体(模拟一个光子) speed=1光速=299792.458千米/秒,注意:质量为0才能达到光速,虽然如此,但也可以试试超光速
light_ship
=
create_light_ship
(
init
.
light_size_scale
,
init
.
light_init_position
,
speed
=
LIGHT_SPEED
*
1
)
light_ship
=
create_light_ship
(
init
.
light_size_scale
,
init
.
light_init_position
,
speed
=
LIGHT_SPEED
*
1
)
light_ship
.
camera_pos
=
camera_pos
# 增加光速天体到天体集合
# 增加光速天体到天体集合
bodies
.
append
(
light_ship
)
bodies
.
append
(
light_ship
)
def
switch_position
():
if
light_ship
.
camera_pos
==
"right"
:
# 摄像机右眼
light_ship
.
position
[
0
]
-=
2
*
camera_l2r
light_ship
.
camera_pos
=
"left"
elif
light_ship
.
camera_pos
==
"left"
:
# 摄像机左眼
light_ship
.
position
[
0
]
+=
2
*
camera_l2r
light_ship
.
camera_pos
=
"right"
light_ship
.
switch_position
=
switch_position
# 运行前指定bodies、light_body并订阅事件
# 运行前指定bodies、light_body并订阅事件
init
.
light_ship
=
light_ship
init
.
light_ship
=
light_ship
init
.
bodies
=
bodies
init
.
bodies
=
bodies
...
@@ -68,22 +83,32 @@ UrsinaEvent.on_reset_unsubscription(init.on_reset)
...
@@ -68,22 +83,32 @@ UrsinaEvent.on_reset_unsubscription(init.on_reset)
def
on_reset
():
def
on_reset
():
init
.
on_reset
init
.
on_reset
()
init
.
arrived_info
=
"距离[太阳中心]:${distance}
\n\n
"
init
.
arrived_info
=
"距离[太阳中心]:${distance}
\n\n
"
init
.
arrived_info
=
"距离[太阳中心]:${distance}
\n\n
光速飞船速度:${speed}
\n\n
"
init
.
arrived_info
=
"距离[太阳中心]:${distance}
\n\n
光速飞船速度:${speed}
\n\n
"
def
on_ready
():
init
.
_3d_card
=
create_3d_card
()
def
on_timer_changed
(
time_data
:
TimeData
):
def
on_timer_changed
(
time_data
:
TimeData
):
init
.
text_panel
.
parent
.
enabled
=
False
init
.
text_panel
.
parent
.
enabled
=
False
velocity
,
_
=
get_value_direction_vectors
(
light_ship
.
velocity
)
velocity
,
_
=
get_value_direction_vectors
(
light_ship
.
velocity
)
distance
=
round
(
init
.
light_ship
.
position
[
2
]
/
AU
,
4
)
distance
=
round
(
init
.
light_ship
.
position
[
2
]
/
AU
,
4
)
text
=
init
.
arrived_info
.
replace
(
"${distance}"
,
"%.4f AU"
%
distance
)
text
=
init
.
arrived_info
.
replace
(
"${distance}"
,
"%.4f AU"
%
distance
)
init
.
text_panel
.
text
=
text
.
replace
(
"${speed}"
,
str
(
round
(
velocity
/
LIGHT_SPEED
,
1
))
+
"倍光速"
)
init
.
text_panel
.
text
=
text
.
replace
(
"${speed}"
,
str
(
round
(
velocity
/
LIGHT_SPEED
,
1
))
+
"倍光速"
)
init
.
_3d_card
.
switch_color
()
light_ship
.
switch_position
()
if
time_data
.
total_seconds
>
20
:
wait_for
(
0.3
)
# 订阅重新开始事件
# 订阅重新开始事件
# 按键盘的 “O” 重置键会触发 on_reset
# 按键盘的 “O” 重置键会触发 on_reset
UrsinaEvent
.
on_reset_subscription
(
on_reset
)
UrsinaEvent
.
on_reset_subscription
(
on_reset
)
UrsinaEvent
.
on_ready_subscription
(
on_ready
)
# 订阅计时器事件(记录已到达天体列表)
# 订阅计时器事件(记录已到达天体列表)
# 运行中,每时每刻都会触发 on_timer_changed
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent
.
on_timer_changed_subscription
(
on_timer_changed
)
UrsinaEvent
.
on_timer_changed_subscription
(
on_timer_changed
)
...
...
tools/sim_video_3d_cap.py
0 → 100644
浏览文件 @
deadd2c8
import
cv2
from
PIL
import
ImageGrab
,
Image
import
numpy
as
np
import
argparse
import
time
import
os
import
win32gui
import
win32ui
import
win32con
import
win32api
import
traceback
def
get_window_handle
(
window_name
=
"universe_sim"
):
"""
获取模拟器窗口句柄
@param window_name:
@return:
"""
handle
=
win32gui
.
FindWindow
(
None
,
window_name
)
return
handle
def
get_args
():
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'--fps'
,
type
=
int
,
default
=
30
,
help
=
'frame per second'
)
parser
.
add_argument
(
'--total_time'
,
type
=
int
,
default
=
10000000
,
help
=
'video total time'
)
parser
.
add_argument
(
'--save_name'
,
type
=
str
,
default
=
'video.mp4'
,
help
=
'save file name'
)
# parser.add_argument('--screen_type', default=0, type=int, choices=[0, 1], help='1: full screen, 0: region screen')
args
=
parser
.
parse_args
()
print
(
"total_time:"
,
args
.
total_time
)
print
(
"fps:"
,
args
.
fps
)
print
(
"save_name:"
,
args
.
save_name
)
return
args
def
screen_shot
(
window_img_dc
):
width
,
height
=
win32api
.
GetSystemMetrics
(
win32con
.
SM_CXVIRTUALSCREEN
),
\
win32api
.
GetSystemMetrics
(
win32con
.
SM_CYVIRTUALSCREEN
)
# 创建一个内存设备描述表
mem_dc
=
window_img_dc
.
CreateCompatibleDC
()
# 创建位图对象
screenshot
=
win32ui
.
CreateBitmap
()
screenshot
.
CreateCompatibleBitmap
(
window_img_dc
,
width
,
height
)
mem_dc
.
SelectObject
(
screenshot
)
# 截图至内存设备描述表
mem_dc
.
BitBlt
((
0
,
0
),
(
width
,
height
),
window_img_dc
,
(
0
,
0
),
win32con
.
SRCCOPY
)
# 将截图保存到文件中
# screenshot.SaveBitmapFile(mem_dc, 'screenshot.bmp')
signedIntsArray
=
screenshot
.
GetBitmapBits
(
True
)
# 下面3个语句都能实现转换,推荐第1个
img
=
np
.
fromstring
(
signedIntsArray
,
dtype
=
'uint8'
)
img
.
shape
=
(
height
,
width
,
4
)
# 内存释放
mem_dc
.
DeleteDC
()
win32gui
.
DeleteObject
(
screenshot
.
GetHandle
())
img
=
img
[:,
:,
0
:
3
]
# 去掉透明数据
return
img
# def is_blank_screen(img_arr):
# for x in range(500, 600):
# for y in range(10, 20):
# pix = img_arr[x, y, ]
# # 检查标题栏,此时标题栏的颜色为白色
# if pix.sum() > 600:
# return True
# return False
def
sim_window_screen_shot
(
wait_ses
=-
1
):
times
=
wait_ses
*
100
while
True
:
handle
=
get_window_handle
()
if
handle
>
0
:
desktop_dc
=
win32gui
.
GetWindowDC
(
handle
)
img_dc
=
win32ui
.
CreateDCFromHandle
(
desktop_dc
)
try
:
img
=
screen_shot
(
img_dc
)
except
Exception
as
e
:
print
(
"ERROR:"
,
str
(
e
))
traceback
.
print_exc
()
return
None
return
img
if
wait_ses
<
0
:
return
None
time
.
sleep
(
0.01
)
times
-=
1
if
times
<=
0
:
return
None
def
create_video
(
args
,
height
,
width
):
fourcc
=
cv2
.
VideoWriter_fourcc
(
*
'mp4v'
)
video
=
cv2
.
VideoWriter
(
args
.
save_name
,
fourcc
,
args
.
fps
,
(
width
,
height
))
return
video
# def show_image(img):
# from PIL import Image
# image = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
# image = Image.fromarray(image)
# print(type(image)) # 结果为<class 'PIL.JpegImagePlugin.JpegImageFile'>
# print(image.size) # 结果为(822,694),这里注意Image输出的结果先显示列数,后显示行数
# image.show()
if
__name__
==
'__main__'
:
args
=
get_args
()
handle
=
get_window_handle
()
# print(get_args())
print
(
"请在10秒内打开模拟器"
)
img
=
sim_window_screen_shot
(
10
)
if
img
is
None
:
print
(
"没有找到模拟器窗口,录屏失败!"
)
exit
(
1
)
# show_image(img)
video
=
create_video
(
args
,
img
.
shape
[
0
],
img
.
shape
[
1
])
imageNum
=
0
print
(
"开始录屏"
)
while
True
:
img
=
sim_window_screen_shot
()
if
img
is
None
:
print
(
"
\n
模拟器窗口已关闭,退出录屏"
)
break
# if is_blank_screen(img):
# if imageNum % args.fps == 0:
# print('x', end='')
#
# continue
if
imageNum
%
args
.
fps
==
0
:
print
(
'.'
,
end
=
''
)
# else:
# print(imageNum, end='')
imageNum
+=
1
# frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
if
imageNum
<
args
.
fps
*
args
.
total_time
:
# show_image(frame)
video
.
write
(
img
)
print
(
"视频保存中"
)
video
.
release
()
cv2
.
destroyAllWindows
()
# crop('video.mp4')
print
(
"视频保存完成"
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录