Table of Contents
消除惯性
在一段拖动后,有两种消除惯性的手法:
- 原地等待
- 向与原方向垂直的方向拖动(简称“拐弯”)
有些界面只能使用特定的方法,比如生息演算拖动地图只能用原地等待的手法;选关界面和终端主线界面无法用原地等待的手法消除惯性,只能用拐弯的手法。
要消除惯性,必须实现复杂的拖拽动作。目前有两种通用方案:scrcpy和uiautomator2。MuMu的触控API也支持复杂的拖拽动作。
swipe_ext
用法介绍
这两种消除惯性的手法可以用统一的方法实现:将“原地等待”看成“起点与终点相同的拖动”,这样两种手法都可以看成在最后附加了一段拖拽动作。
BaseSolver
类封装了方法swipe_ext
,用来实现复杂的拖动。它的参数up_wait
为正时,会在拖拽结束后原地等待。函数返回前会清除截图缓存。例如
solver.swipe_ext([(1700, 500), (1000, 500)], [500], up_wait=300, interval=0.2)
表示花费500ms从 (1700, 500)
处拖拽至 (1000, 500)
处(水平向左拖拽700像素),然后原地等待300ms以消除惯性,抬手之后用0.2秒等待回弹动画消失,最后清除截图缓存。
如果使用拐弯的手法消除惯性,可以这样写:
solver.swipe_ext([(1700, 500), (1000, 500), (1000, 200)], [500, 300], up_wait=0, interval=0.2)
第一段拖拽还是水平向左拖700像素,第二段是花费300ms垂直向上拖拽300像素。
swipe_update
用法介绍
消除惯性的滑动,包括以下四步:
- 拖动
- 等待或拐弯
- 抬手
- 等待回弹动画
swipe_update
在第2步开始后截图。这张截图有两个作用:
判断滑动是否到底
抬手前的截图与回弹动画结束后的截图如果有差异,说明发生了回弹,滑动已经到底了。
如果只在第4步后截图,要判断滑动是否到底,只能比较一次滑动前后的截图是否相同,滑动到底之后会再拖拽一次。使用
swipe_update
可以省去额外的一次滑动。
加快识别速度
大部分的滑动不会到底,从第2步开始到第4步结束,画面是不变的。如果在等待惯性消失和回弹动画消失的时候,用第2步的截图代替第4步的截图进行识别,让识别时间与等待时间重叠,并在第4步结束后检查截图与第2步是否一样(也就是检查是否发生了回弹),能够降低整体用时。
在滑动结束后识别,整体用时为:\text{拖动时间}+\text{等待时间}+\text{识别用时}
使用swipe_update
,没有发生回弹时的整体用时为:\text{拖动时间}+\max(\text{等待时间}, \text{识别用时})+\text{验证用时}
swipe_update
节省的时间为:\min(\text{等待时间}, \text{识别用时})-\text{验证用时}
因此使用swipe_update
时,验证一定要快于识别,否则swipe_update
只会更慢。
API
swipe_update
与swipe_ext
的大部分参数含义相同。在滑动的最后一段,也就是等待惯性消失的时,运行func
函数,swipe_update
的返回值就是它的结果。
swipe_update
退出后,config.recog.img
为等待抬手过程中的截图。运行config.recog.update()
后再访问config.recog.im
,得到回弹动画结束后的截图。
以基建选人遍历为例:
# 识别第一页的干员
print([i[0] for i in operator_room_select(config.recog.img)])
while True:
# swipe_update的返回值就是operator_room_select的返回值
result = solver.swipe_update(
[(1820, 770), (725, 770)],
[200],
up_wait=400,
interval=0.1,
func=operator_room_select,
)
print([i[0] for i in result])
# 截图缓存中为等待惯性消失时的截图
img1 = config.recog.gray
# 清除缓存后重新截图,为回弹动画结束后的截图
config.recog.update()
img2 = config.recog.gray
# 识别回弹动画
if diff_ratio(img1, img2, thresh=10):
break
以上示例中使用了原地等待的手法消除惯性。swipe_update
同样也支持拐弯的手法:
result = solver.swipe_update(
[(1820, 770), (725, 770), (725, 900)],
[200, 400],
up_wait=0,
interval=0.1,
func=operator_room_select,
)