Task Example
在开始本文之前请保证详细阅读前文内容,对于之前详细提及的本文将忽略处理。oas 为实现一个任务建立了三个基石:User Option
、Manipulation Device
、Process Element
,当然第二个不需要开发者操作什么,oas 已经为其搭建好了。在实现前三者的基础上即可开始我们的任务编写,以结界突破RealmRaid
为例子。
1、User Option
请按照该文操作新增。为此新增如下文件:
# RealmRaid/config.py 只是复制了核心的部分以源码为准
from tasks.RealmRaid.config_scheduler import Scheduler
from tasks.GeneralBattle.config_general_battle import GeneralBattleConfig
class RealmRaid(BaseModel):
scheduler: Scheduler = Field(default_factory=Scheduler)
raid_config: RaidConfig = Field(default_factory=RaidConfig)
general_battle_config: GeneralBattleConfig = Field(default_factory=GeneralBattleConfig)
# RealmRaid/config_scheduler.py
class Scheduler(BaseModel):
enable: bool = Field(default=False, description='[是否启用]:默认为False')
next_run: datetime = Field(default="2023-01-01 00:00:00", description='[下次执行时间]:默认为2023-01-01 00:00:00\n 清空后回车设置当前的时间')
interval_days: int = Field(default=1, description='[间隔天数]:默认为1\n 可选0-7')
interval_hours: int = Field(default=0, description='[间隔小时]:默认为0\n 可选0-23')
interval_minutes: int = Field(default=0, description='[间隔分钟]:默认为0\n 可选0-59')
2、Process Element
请按照该文操作, 为此新增了res
文件夹:包括匹配目标截图、image.json、ocr.json。
随后执行了./module/dev_tools/assets_extract.py
来将信息提取成assets.py
文件:
# 完整的assets.py 文件
from module.atom.image import RuleImage
from module.atom.click import RuleClick
from module.atom.long_click import RuleLongClick
from module.atom.swipe import RuleSwipe
from module.atom.ocr import RuleOcr
# This file was automatically generated by module/dev_tools/assets_extract.py.
# Don't modify it manually.
class RealmRaidAssets:
# Image Rule Assets
# 点击结界突破的图片
I_REALM_RAID = RuleImage(roi_front=(246,628,63,64), roi_back=(246,628,63,64), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_realm_raid.png")
# 五个勋章
I_MEDAL_5 = RuleImage(roi_front=(238,205,212,53), roi_back=(216,187,919,364), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_5.png")
# description
I_MEDAL_4 = RuleImage(roi_front=(241,483,193,46), roi_back=(228,178,899,362), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_4.png")
# description
I_MEDAL_3 = RuleImage(roi_front=(240,210,193,41), roi_back=(229,189,894,345), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_3.png")
# description
I_MEDAL_2 = RuleImage(roi_front=(572,478,198,48), roi_back=(217,193,923,354), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_2.png")
# description
I_MEDAL_1 = RuleImage(roi_front=(570,206,199,52), roi_back=(237,198,892,336), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_1.png")
# 没有勋章的
I_MEDAL_0 = RuleImage(roi_front=(510,336,202,51), roi_back=(231,200,898,336), threshold=0.9, method="Template matching", file="./tasks/RealmRaid/res/res_medal_0.png")
# 右上角红色的关闭
I_BACK_RED = RuleImage(roi_front=(1178,101,57,64), roi_back=(1178,101,57,64), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_back_red.png")
# 没有锁的状态图标
I_UNLOCK = RuleImage(roi_front=(818,579,38,42), roi_back=(818,579,38,42), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_unlock.png")
# 以锁的状态图片
I_LOCK = RuleImage(roi_front=(818,579,36,41), roi_back=(818,579,36,41), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_lock.png")
# 刷新按钮
I_FRESH = RuleImage(roi_front=(957,564,182,66), roi_back=(957,564,182,66), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_fresh.png")
# 点击的式神录
I_SHIKIGAMI = RuleImage(roi_front=(1206,608,54,51), roi_back=(1206,608,54,51), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_shikigami.png")
# 进攻
I_FIRE = RuleImage(roi_front=(982,494,136,63), roi_back=(140,129,1024,584), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_fire.png")
# 打完个后出现的领取奖励
I_SOUL_RAID = RuleImage(roi_front=(577,502,100,100), roi_back=(577,502,100,100), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_soul_raid.png")
# 刷新确认
I_FRESH_ENSURE = RuleImage(roi_front=(672,403,173,59), roi_back=(672,403,173,59), threshold=0.8, method="Template matching", file="./tasks/RealmRaid/res/res_fresh_ensure.png")
# Ocr Rule Assets
# 刷新的时间
O_FRESH_TIME = RuleOcr(roi=(1042,582,85,36), area=(0,0,100,100), mode="Duration", method="Default", keyword="", name="fresh_time")
# 右上角 突破卷的数量
O_NUMBER = RuleOcr(roi=(1139,13,91,39), area=(0,0,100,100), mode="DigitCounter", method="Default", keyword="", name="number")
3、实现任务
建立文件
./tasks/RealmRaid/script_task.py
caution文件名必须是
script_task.py
新增类
ScriptTask
和方法run()
caution类名必须是
ScriptTask
, 任务执行的入口必须是run()
为其加入父类
class ScriptTask(GeneralBattle, GameUi, RealmRaidAssets):
此时我们可以使用 战斗模块、页面切换模块、本任务特有的资源
在
run()
方法中开始编写脚本代码,这里取几个典型步骤;# 点击突破
while 1:
self.screenshot()
if self.appear_then_click(self.I_REALM_RAID, interval=1):
continue
if self.appear(self.I_BACK_RED, threshold=0.6):
break上面的代码块中是一个步骤的循环判断,是非常清晰明了的,
I_REALM_RAID
表示探索界面下方的按钮图片结界突破
,I_BACK_RED
表示个人突破界面的右上角红色关闭按钮
,非常方便的来进行代码编写。加入参数interval=1
是为了防止模拟器设备响应不及时导致多次点击操作。def is_ticket(self) -> bool:
"""
如果没有票了,那么就返回False
:return:
"""
self.screenshot()
cu, res, total = self.O_NUMBER.ocr(self.device.image)
if cu == 0 and cu+res == total:
logger.warning(f'Execute round failed, no ticket')
return False
return True上面的代码块中使用
DigitCounter
类型的ocr来判断是否还有票self.set_next_run(task='RealmRaid')
raise TaskEnd运行任务结束后,重新设置下次的执行时间,并且抛出任务结束的异常。
这个是一个简易的例子,建议看源码