Skip to main content

Task Example

在开始本文之前请保证详细阅读前文内容,对于之前详细提及的本文将忽略处理。oas 为实现一个任务建立了三个基石:User OptionManipulation DeviceProcess 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、实现任务

  1. 建立文件./tasks/RealmRaid/script_task.py

    caution

    文件名必须是script_task.py

  2. 新增类ScriptTask和方法run()

    caution

    类名必须是ScriptTask, 任务执行的入口必须是run()

  3. 为其加入父类

    class ScriptTask(GeneralBattle, GameUi, RealmRaidAssets):

    此时我们可以使用 战斗模块、页面切换模块、本任务特有的资源

  4. 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

    运行任务结束后,重新设置下次的执行时间,并且抛出任务结束的异常。

  5. 这个是一个简易的例子,建议看源码