Skip to content

Commit

Permalink
#245 完善合成指令
Browse files Browse the repository at this point in the history
  • Loading branch information
DoctorReid committed Jun 23, 2024
1 parent ef87502 commit 14dca42
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 6 deletions.
3 changes: 1 addition & 2 deletions src/sr/sim_uni/op/move_in_sim_uni.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def _move_and_interact(self) -> OperationOneRoundResult:
self.is_moving = False
self.move_times += 1

if self.move_times >= 4: # 正常情况不会连续移动这么多次都没有到下层入口 尝试脱困
if self.move_times > 0 and self.move_times % 4 == 0: # 正常情况不会连续移动这么多次都没有到下层入口 尝试脱困
self.ctx.controller.move(self.get_rid_direction, 1)
self.get_rid_direction = OPPOSITE_DIRECTION[self.get_rid_direction]
return self.round_wait()
Expand All @@ -288,7 +288,6 @@ def _move_and_interact(self) -> OperationOneRoundResult:
else:
angle = 35
self.ctx.controller.turn_by_angle(angle)
self.move_times = 0 # 没有识别到就是没有移动
return self.round_retry(MoveToNextLevel.STATUS_ENTRY_NOT_FOUND, wait=1)

target = self.get_target_entry(type_list, self.config)
Expand Down
1 change: 1 addition & 0 deletions src/sr/sim_uni/op/sim_uni_battle.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ def _try_attack(self, screen: MatLike) -> OperationOneRoundResult:

if self.disposable:
result = self._attack(now_time)
time.sleep(0.5) # 攻击可破坏时 多等一会 防止刮刮乐出奖
return result
else:
with_alert, attack_direction = self.ctx.yolo_detector.get_attack_direction(screen, self.last_attack_direction, now_time)
Expand Down
167 changes: 163 additions & 4 deletions src/sr/synthesize/synthesize.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,174 @@
from typing import Optional

from basic import str_utils, Point
from basic.i18_utils import gt
from basic.img import cv2_utils, MatchResult
from sr.const import phone_menu_const
from sr.context.context import Context
from sr.operation import StateOperation
from sr.operation import StateOperation, OperationOneRoundResult, StateOperationNode
from sr.operation.common.back_to_normal_world_plus import BackToNormalWorldPlus
from sr.operation.unit.menu.click_phone_menu_item import ClickPhoneMenuItem
from sr.operation.unit.menu.open_phone_menu import OpenPhoneMenu
from sr.synthesize.synthesize_const import ScreenSynthesize, SynthesizeItem


class Synthesize(StateOperation):

def __init__(self, ctx: Context):
def __init__(self, ctx: Context, item: SynthesizeItem, num: int):
"""
如果不在合成页面 则进入合成页面
合成指定物品后 停留在指定页面
:param ctx:
:param ctx: 上下文
:param item: 要合成的物品
:param num: 要合成的数量 0为最大值。当前只支持最大值
"""
super().__init__(ctx, try_times=5,
op_name='%s %s' % (gt('合成', 'ui')))
op_name='%s %s' % (gt('合成', 'ui'), ''))

self.item: SynthesizeItem = item # 要合成的物品
self.num: int = num # 要合成的数量 0为最大值

def add_edges_and_nodes(self) -> None:
"""
初始化前 添加边和节点 由子类实行
:return:
"""
check_screen = StateOperationNode('识别画面', self.check_screen)

first_to_world = StateOperationNode('返回大世界', op=BackToNormalWorldPlus(self.ctx))
self.add_edge(check_screen, first_to_world)

open_menu = StateOperationNode('打开菜单', op=OpenPhoneMenu(self.ctx))
self.add_edge(first_to_world, open_menu)

choose_synthesize = StateOperationNode('选择合成', op=ClickPhoneMenuItem(self.ctx, phone_menu_const.SYNTHESIZE))
self.add_edge(open_menu, choose_synthesize)

choose_category = StateOperationNode('选择合成类别', self.choose_category)
self.add_edge(choose_synthesize, choose_category)
self.add_edge(check_screen, choose_category, status=ScreenSynthesize.TITLE.value.status)

choose_item = StateOperationNode('选择合成物品', self.choose_item)
self.add_edge(choose_category, choose_item)

choose_num = StateOperationNode('选择数量', self.choose_num)
self.add_edge(choose_item, choose_num)

click_synthesize = StateOperationNode('点击合成', self.click_synthesize)
self.add_edge(choose_num, click_synthesize)

click_confirm = StateOperationNode('点击确认', self.click_confirm)
self.add_edge(click_synthesize, click_confirm)

click_empty = StateOperationNode('点击空白处关闭', self.click_empty)
self.add_edge(click_confirm, click_empty)

def check_screen(self) -> OperationOneRoundResult:
"""
识别画面
:return:
"""
screen = self.screenshot()
title = ScreenSynthesize.TITLE.value

if self.find_area(screen=screen, area=title):
return self.round_success(status=title.status)
else:
return self.round_success()

def choose_category(self) -> OperationOneRoundResult:
"""
选择合成类别
:return:
"""
category = self.item.category

screen = self.screenshot()
area = ScreenSynthesize.CATEGORY_TITLE.value
part = cv2_utils.crop_image_only(screen, area)

ocr_result = self.ctx.ocr.ocr_for_single_line(part)
if str_utils.find_by_lcs(ocr_result, gt(category.name, 'ocr'), percent=0.5):
return self.round_success()
else:
self.ctx.controller.click(category.area.center)
return self.round_retry(wait=0.5)

def choose_item(self) -> OperationOneRoundResult:
"""
选择合成物品
:return:
"""
screen = self.screenshot()
area = ScreenSynthesize.ITEM_LIST.value
result = self.get_item_pos(screen)

if result is None:
drag_from = area.center
drag_to = drag_from + Point(0, -100)
self.ctx.controller.drag_to(start=drag_from, end=drag_to)
return self.round_retry(f'未找到{self.item.name}', wait=0.5)
else:
self.ctx.controller.click(result.center)
return self.round_success(wait=0.5)

def get_item_pos(self, screen) -> Optional[MatchResult]:
"""
获取合成物品的位置
:param screen:
:return:
"""
area = ScreenSynthesize.ITEM_LIST.value
part = cv2_utils.crop_image_only(screen, area)

mrl = self.ctx.im.match_template(part, self.item.template_id, template_sub_dir='consumable')

if mrl.max is None:
return None

result = mrl.max
result.x += area.rect.left_top.x
result.y += area.rect.left_top.y

return result

def choose_num(self) -> OperationOneRoundResult:
"""
选择合成数量 当前只支持最大值
:return:
"""
screen = self.screenshot()
area = ScreenSynthesize.NOT_ENOUGH_MATERIAL.value
if self.find_area(screen=screen, area=area):
return self.round_fail(area.status)

area = ScreenSynthesize.NUM_MAX.value
self.ctx.controller.click(area.center)
return self.round_success(wait=0.5)

def click_synthesize(self) -> OperationOneRoundResult:
"""
进行合成
:return:
"""
screen = self.screenshot()
area = ScreenSynthesize.SYNTHESIZE_BTN.value
return self.round_by_find_and_click_area(screen, area, success_wait=1, retry_wait_round=0.5)

def click_confirm(self) -> OperationOneRoundResult:
"""
合成出现的对话框 点击确认
:return:
"""
screen = self.screenshot()
area = ScreenSynthesize.SYNTHESIZE_DIALOG_CONFIRM.value
return self.round_by_find_and_click_area(screen, area, success_wait=5, retry_wait_round=0.5)

def click_empty(self) -> OperationOneRoundResult:
"""
确认后 点击空白关闭
:return:
"""
screen = self.screenshot()
area = ScreenSynthesize.SYNTHESIZE_EMPTY_TO_CLOSE.value
return self.round_by_find_and_click_area(screen, area, success_wait=1, retry_wait_round=0.5)
49 changes: 49 additions & 0 deletions src/sr/synthesize/synthesize_const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from enum import Enum

from basic import Rect
from sr.screen_area import ScreenArea


class ScreenSynthesize(Enum):

TITLE = ScreenArea(pc_rect=Rect(), text='合成') # 左上角标题
CATEGORY_TITLE = ScreenArea(pc_rect=Rect()) # 左上角二级标题

CATEGORY_1_BTN = ScreenArea(pc_rect=Rect()) # 合成类别1 - 消耗品
CATEGORY_2_BTN = ScreenArea(pc_rect=Rect()) # 合成类别2 - 消耗品
CATEGORY_3_BTN = ScreenArea(pc_rect=Rect()) # 合成类别3 - 消耗品
CATEGORY_4_BTN = ScreenArea(pc_rect=Rect()) # 合成类别4 - 消耗品

ITEM_LIST = ScreenArea(pc_rect=Rect()) # 合成物品的列表

NOT_ENOUGH_MATERIAL = ScreenArea(pc_rect=Rect(), text='合成所需材料不足')
NUM_MAX = ScreenArea(pc_rect=Rect()) # 合成数量最大值

SYNTHESIZE_BTN = ScreenArea(pc_rect=Rect(), text='合成') # 合成按钮
SYNTHESIZE_DIALOG_CONFIRM = ScreenArea(pc_rect=Rect(1020, 790, 1330, 844), text='确认') # 合成弹窗的确认
SYNTHESIZE_EMPTY_TO_CLOSE = ScreenArea(pc_rect=Rect(868, 930, 1053, 960), text='点击空白处关闭')


class SynthesizeCategory:

def __init__(self, name: str, area: ScreenArea):
self.name: str = name
self.area: ScreenArea = area


class SynthesizeCategoryEnum(Enum):

CONSUMABLE = SynthesizeCategory('消耗品', ScreenSynthesize.CATEGORY_1_BTN.value)


class SynthesizeItem:

def __init__(self, category_id: str, name: str, template_id: str):
self.category: SynthesizeCategory = SynthesizeCategoryEnum[category_id.upper()].value
self.name: str = name
self.template_id: str = template_id


class SynthesizeItemEnum(Enum):

QUICK_SNACK = SynthesizeItem(SynthesizeCategoryEnum.CONSUMABLE.name, '奇巧零食', 'quick_snack')

0 comments on commit 14dca42

Please sign in to comment.