71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
"""
|
||
战斗状态检测模块,通过模板匹配判断角色是否处于战斗中
|
||
"""
|
||
import os
|
||
import logging
|
||
import cv2
|
||
import numpy as np
|
||
import pyautogui
|
||
from config import GameConfig
|
||
|
||
|
||
class CombatDetector:
|
||
"""通过截图与模板匹配判断当前是否处于战斗状态"""
|
||
|
||
TEMPLATES = [
|
||
'images/1.png',
|
||
'images/2.png',
|
||
'images/3.png',
|
||
'images/4.png',
|
||
]
|
||
SCREENSHOT_PATH = 'screenshot/combat_screenshot.png'
|
||
|
||
def __init__(self, config: GameConfig):
|
||
self.config = config
|
||
self.screen_width, self.screen_height = pyautogui.size()
|
||
self.logger = logging.getLogger(__name__)
|
||
os.makedirs(os.path.dirname(self.SCREENSHOT_PATH), exist_ok=True)
|
||
|
||
def is_in_combat(self) -> bool:
|
||
"""判断是否处于战斗中。
|
||
|
||
截取屏幕左上半区域,逐一与模板图片做归一化相关系数匹配,
|
||
任一模板匹配值超过阈值即视为处于战斗状态。
|
||
|
||
Returns:
|
||
bool: 处于战斗中返回 True,否则返回 False
|
||
"""
|
||
try:
|
||
region_width = self.screen_width // 2
|
||
region_height = self.screen_height // 2
|
||
screenshot = pyautogui.screenshot(region=(0, 0, region_width, region_height))
|
||
screenshot.save(self.SCREENSHOT_PATH)
|
||
|
||
screenshot_cv = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
|
||
|
||
for template_file in self.TEMPLATES:
|
||
if not os.path.exists(template_file):
|
||
self.logger.warning(f"模板文件不存在,跳过: {template_file}")
|
||
continue
|
||
|
||
template = cv2.imread(template_file)
|
||
result = cv2.matchTemplate(
|
||
screenshot_cv,
|
||
template,
|
||
cv2.TM_CCOEFF_NORMED
|
||
)
|
||
_, max_val, _, _ = cv2.minMaxLoc(result)
|
||
|
||
if max_val > self.config.recognition_threshold:
|
||
self.logger.info(
|
||
f"战斗状态: 是(模板: {template_file},匹配值: {max_val:.2f})"
|
||
)
|
||
return True
|
||
|
||
self.logger.info("战斗状态: 否(所有模板均未匹配)")
|
||
return False
|
||
|
||
except Exception as e:
|
||
self.logger.error(f"判断战斗状态失败: {str(e)}")
|
||
return False
|