feat(task): 优化 P 饮料领取

将 OCR 识别替换为模板匹配
This commit is contained in:
XcantloadX 2025-04-08 20:57:10 +08:00
parent a768f01e89
commit b1a3b98771
9 changed files with 48 additions and 90 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

View File

@ -0,0 +1 @@
{"definitions":{"e4683def-8d1d-472b-a5ab-bb3885c0c98e":{"name":"InPurodyuusu.TextDontClaim","displayName":"受け取らない","type":"template","annotationId":"e4683def-8d1d-472b-a5ab-bb3885c0c98e","useHintRect":false,"description":"用在不领取饮料上"}},"annotations":[{"id":"e4683def-8d1d-472b-a5ab-bb3885c0c98e","type":"rect","data":{"x1":281,"y1":989,"x2":437,"y2":1023}}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

View File

@ -0,0 +1 @@
{"definitions":{"447d0e44-5d87-4b7c-8e60-edb111fe1639":{"name":"InPurodyuusu.ButtonDontClaim","displayName":"「受け取らない」按钮","type":"template","annotationId":"447d0e44-5d87-4b7c-8e60-edb111fe1639","useHintRect":false,"description":"用在不领取饮料上"}},"annotations":[{"id":"447d0e44-5d87-4b7c-8e60-edb111fe1639","type":"rect","data":{"x1":263,"y1":1072,"x2":451,"y2":1121}}]}

View File

@ -13,7 +13,7 @@ from kotonebot import (
Interval,
)
from kotonebot.tasks.game_ui import WhiteFilter, CommuEventButtonUI
from .pdorinku import acquire_pdorinku
from .p_drink import acquire_p_drink
from kotonebot.tasks.actions.commu import handle_unread_commu
from kotonebot.util import measure_time
@ -37,16 +37,6 @@ def acquire_skill_card():
sleep(0.2)
logger.debug("Click acquire button")
device.click(image.expect_wait(R.InPurodyuusu.AcquireBtnDisabled))
# acquisitions(['PSkillCardSelect']) 优先做这个
# device.screenshot()
# (SimpleDispatcher('acquire_skill_card')
# .click(contains("受け取る"), finish=True, log="Skill card #1 acquired")
# # .click_any([
# # R.InPurodyuusu.PSkillCardIconBlue,
# # R.InPurodyuusu.PSkillCardIconColorful
# # ], finish=True, log="Skill card #1 acquired")
# ).run()
# # logger.info("Skill card #1 acquired")
@action('选择P物品', screenshot_mode='auto')
def select_p_item():
@ -147,11 +137,8 @@ AcquisitionType = Literal[
@measure_time()
@action('处理培育事件', screenshot_mode='manual')
def fast_acquisitions() -> AcquisitionType | None:
"""处理行动开始前和结束后可能需要处理的事件,直到到行动页面为止"""
"""处理行动开始前和结束后可能需要处理的事件"""
img = device.screenshot()
screen_size = device.screen_size
bottom_pos = (int(screen_size[0] * 0.5), int(screen_size[1] * 0.7)) # 底部中间
logger.info("Acquisition stuffs...")
# 跳过未读交流
@ -184,6 +171,8 @@ def fast_acquisitions() -> AcquisitionType | None:
logger.info("Leave button found")
device.click(leave)
return "PDrinkMax"
# P饮料到达上限 确认提示框
# [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_pdrink_max_confirm.png]
if image.find(R.InPurodyuusu.TextPDrinkMaxConfirmTitle):
logger.debug("PDrink max confirm found")
device.screenshot()
@ -227,7 +216,7 @@ def fast_acquisitions() -> AcquisitionType | None:
logger.debug("Check PDrink select...")
if image.find(R.InPurodyuusu.TextPDrink):
logger.info("PDrink select found")
acquire_pdorinku(index=0)
acquire_p_drink()
return "PDrinkSelect"
# 技能卡选择
logger.debug("Check skill card select...")

View File

@ -0,0 +1,41 @@
from logging import getLogger
from .. import R
from kotonebot import device, image, action, sleep
logger = getLogger(__name__)
# 三个饮料的坐标
POSTIONS = [
(157, 820, 128, 128), # x, y, w, h
(296, 820, 128, 128),
(435, 820, 128, 128),
] # TODO: HARD CODED
@action('领取 P 饮料')
def acquire_p_drink():
"""
领取 P 饮料
:param index: 要领取的 P 饮料的索引 0 开始
"""
# TODO: 随机领取一个饮料改成根据具体情况确定最佳
# 如果能不领取,就不领取
if image.find(R.InPurodyuusu.TextDontClaim):
# [kotonebot-resource/sprites/jp/in_purodyuusu/screenshot_select_p_drink_full.png]
logger.info("Skip claiming PDrink.")
device.click()
sleep(0.3)
device.click(image.expect_wait(R.InPurodyuusu.ButtonDontClaim))
else:
# 点击饮料
device.click(POSTIONS[0])
logger.debug(f"PDrink clicked: {POSTIONS[0]}")
sleep(0.3)
# 确定按钮
device.click(image.expect_wait(R.InPurodyuusu.AcquireBtnDisabled))
logger.debug("受け取る clicked")
if __name__ == '__main__':
acquire_p_drink()
input()

View File

@ -1,74 +0,0 @@
from logging import getLogger
from .. import R
from kotonebot import device, ocr, image, Rect, action, sleep, contains
logger = getLogger(__name__)
# TODO: 加入一个 device.snapshot() 方法,用于保存当前设备画面,避免重复截图。
# TODO: 比较 OCR 和模板匹配文字的性能,如果模板匹配更好,
# 则首次使用 OCR找到结果后自动截图后续使用模板匹配。
@action('检测是否在 P 饮料领取中')
def is_on_pdorinku_acquisition() -> bool:
"""检查是否在 P 饮料领取中"""
return ocr.find('受け取るPドリンクを選んでください。') is not None
@action('列出当前要领取的 P 饮料')
def list_pdorinku() -> list[tuple[str, Rect]]:
"""
列出当前要领取的 P 饮料
:return: 检测结果`[(饮料名称, 饮料矩形坐标), ...]`
"""
# 截图所有饮料
# TODO: 自动记录未知饮料
dorinkus = image.find_all_crop(
R.InPurodyuusu.Action.PDorinkuBg,
mask=R.InPurodyuusu.Action.PDorinkuBgMask,
)
return [
('', dorinku.rect) # TODO: 获取饮料名称
for dorinku in dorinkus
]
@action('领取 P 饮料')
def acquire_pdorinku(index: int):
"""
领取 P 饮料
:param index: 要领取的 P 饮料的索引 0 开始
"""
# TODO: 随机领取一个饮料改成根据具体情况确定最佳
# 如果能不领取,就不领取
if ocr.find(contains('受け取らない')):
device.click()
sleep(0.3)
device.click(image.expect_wait(R.InPurodyuusu.ButtonNotAcquire))
# TODO: 可能超时。需要更好的处理方式。
sleep(0.8)
if image.find(R.Common.ButtonConfirm):
device.click()
else:
# 点击饮料
drinks = list_pdorinku()
dorinku = drinks[index]
device.click(dorinku[1])
logger.debug(f"Pドリンク clicked: {dorinku[0]}")
sleep(0.3)
# 确定按钮
ret = ocr.expect('受け取る')
device.click(ret.rect)
logger.debug("受け取る clicked")
sleep(1.3)
# 再次确定
device.click_center()
logger.debug("再次确定 clicked")
__actions__ = [acquire_pdorinku]
if __name__ == '__main__':
from pprint import pprint as print
# print(list_pdorinku())
acquire_pdorinku(0)
input()