Table of Contents
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
1. Start
这里是 Alas 的开发文档,会讲述 Alas 的框架和设计模式,介绍常用组件,带初来乍到的开发者熟悉项目。但是这里不会把每一个函数的功能都复读一遍,如果你希望了解具体某个函数是如何使用的,最好去翻阅源码。
Alas 的应用场景
Alas 是为长时间运行,甚至是 7*24 运行而设计的,这一点与市面上多数针对手机的脚本不同。Alas 在早期已经放弃了对安卓真机的支持,同时也放弃了对除 1280x720 以外的分辨率的支持。
放弃安卓真机的原因是:
- 安卓机在长时间运行下,容易出现黑屏/假死的情况
- 部分安卓机型截图会压缩,早期代码中有不少基于颜色识别的方法
- 需要另外占用一台安卓机。由于 ocr 模型的存在,将 Alas 迁移至安卓存在困难
使用 1280x720 分辨率的原因是:
- 720p 在图像清晰度和截图耗时之间有较好的平衡,480p 下海图识别正确率明显下降,1080p 截图耗时几乎翻倍
- 异型屏没有统一的标准,适配非 16:9 分辨率带来的维护成本和获得的收益不符
基本运作模式
在低级的脚本中,往往充斥着这样的代码:
click(XXXX)
sleep(2)
click(YYYY)
sleep(3)
这样的代码稳定性很差,如果游戏卡顿,或者脚本需要对低配设备优化,就得延长等待的间隔,最后等待变得越来越长。很多时候,脚本慢,并不是因为截图慢,语言运行慢,而是因为开发者写了大量的固定时长的等待。
对于 Alas 而言,“快” 是最主要的目标。
针对快慢设备的兼容问题,Alas 使用了这样的运作模式,也希望开发者使用它,以减少对 sleep() 的依赖。这种模式在高配电脑上可以运行得很快,在低配电脑上也有很好的兼容性,它可以在点击失败时自动重试,我们也不再需要关心点击的执行顺序。
以进入地图为例:
while 1:
self.device.screenshot()
if self.appear_then_click(ENTRANCE):
continue
if self.appear_then_click(MAP_PREPARATION):
continue
if self.appear_then_click(FLEET_PREPARATION):
continue
# End
if self.handle_in_map_with_enemy_searching():
break
处理死循环
在上面示例代码中,如果陷入死循环,Alas 会抛出异常。
- **
GameStuckError** 无操作连续截图超过 1 分钟。战斗中和客户端启动中,将延长至 5 分钟。 - **
GameTooManyClickError** 最后 15 次操作中,有一项操作 >= 12 次,或有两项操作都 >= 6 次。
这两个异常只会在最顶层捕获。捕获后,Alas 会将 log 和最近截图保存在单独的文件夹,并处理其中可能会暴露用户身份的信息,包括混淆路径名称,遮挡游戏昵称等。处理完成后 Alas 停止。
性能优化
与一般认知不同,开发者在编写 Alas 时,不需要特别注意性能优化。因为在 Alas 运行时,超过 99% 的时间是在等待模拟器截图。
在配置过关的电脑上,截图耗时约 350 ms,而 Alas 处理只花费约 2.5 ms。在海图识别或者 OCR 时,Alas 耗时也不过 100-180 ms。
基于图片的 assets 管理
手动写坐标会给后期维护带来麻烦,因为没人知道这个坐标是在哪里。它也会大量占据开发者的时间,以至于脚本的规模受限。
area = (790, 275, 911, 321)
Alas 编写了一个简单粗暴的代码生成器(button_extract.py),来管理 assets ,它优势在:
- 打开图片即可方便地查看这个区域在哪里,以及这个区域所包含的内容,方便后期维护。
- 设置好 PhotoShop 动作后,制作一张 assets,比手动输入坐标快。
- 多服务器适配。
- 可以在 IDE 中使用自动补全。
OCR
Alas 使用了 cnocr 作为 OCR 库,也针对碧蓝航线内的字体训练了两个 OCR 模型。许多脚本都迈不过 OCR 这道坎,需要依赖在线 OCR,但是在 Alas 里,你可以大量地调用 OCR。
以识别石油量为例:
OCR_OIL = Digit(OCR_OIL, name='OCR_OIL', letter=(247, 247, 247), threshold=128)
oil = OCR_OIL.ocr(self.device.image)
注释
使用 Google 注释规范,例如:
"""
Re-focus to the center of a grid.
Args:
tolerance (float): 0 to 0.5. If None, use MAP_GRID_CENTER_TOLERANCE
Returns:
bool: Map swiped.
"""
同时增加 Pages,说明函数进出时的游戏界面,可以是 UI Page,也可以是 Button。(旧代码中可能缺少 Pages 注释)
Pages:
in: page_moewfficer
out: MEOWFFICER_BUY
在注释中,应当全部使用英语,不能使用汉语拼音或者拼音缩写。
尽量做到:
- 一个函数的注释占 1/3 ~ 1/2
- 一个函数不超过一个屏幕
- 一个 .py 文件不超过 500 行。
Getting Started
- Installation [EN]
- Installation [CN]
- Installation With Docker [EN]
- Emulator Support [CN]
- FAQ [EN/CN]
- FAQ [JP]
- Troubleshooting [EN]
- Another Installation guide
- Research Filter String [EN]
- Research Filter String [CN]
- Reward Shop Filter String [EN/CN]
- Onepush Configuration [EN]
- Onepush Configuration [CN]
Development
- Perspective [CN]
- Perspective [EN]
- Debug perspective [CN]
- Debug perspective [EN]
- Item Statistics [EN]
- 1. Start
- 2.1. Debugging
- 2.2. Multi-server support
- 3.1. Utils
- 3.2. Decorators
- 3.3. Log
- 3.4. Exception
- 4.1. Detection objects
- 4.2. UI control
- 4.3. OCR
- 4.4. State loop
- 5.1. Local Map
- 5.2. Create globe Map
- 5.3. Globe Map
- 6.1. GUI Option
MISC