6 Star 93 Fork 21

LanRenZhiNeng/MingChaoAI

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
wayfinding.py 69.36 KB
一键复制 编辑 原始数据 按行查看 历史
老大哥 提交于 2024-09-10 12:21 . 更新到1.48
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
# -*- coding: utf-8 -*-
#opencv 必须 4.8.1.78
from pynput import keyboard
from pynput.keyboard import Key
from screenshot import *
from lanrentools.findimg import *
from lanrentools.hookkeymose import HookKeyMose
from auto import *
def units_to_seconds(units):
"""
将单位数转换为秒数
参数:
units: 单位数
返回:
对应的秒数
"""
# 每60个单位等于2秒,所以每个单位等于2/60秒
seconds_per_unit = 1 / 14.5
seconds = units * seconds_per_unit
if seconds<0.5:
seconds=0.5
if seconds>15:
seconds=15
if state.状态_在水面:
time.sleep(2)
return seconds
class MingChaoAutoMap(HookKeyMose):
def __init__(self):
HookKeyMose.__init__(self, hookKey=True)
pyautogui.PAUSE = 0.01
pyautogui.FAILSAFE=False
self.on_rec=False
self.map_matrix = []
self.now_point=(0,0)#当前的位置
self.old_point=(0,0)#上一次的位置
self.isRunRec=False
self.小地图区域=(36,30,222,216)#(64,57,193,186) 36,30,222,216
# 让yolov接手的兴趣点用来存可能出现怪物,或者需要捡东西的地方
self.interest_point = []
def run_rec(self, image_path,image_path_lujin,is_daditu=False):
'''
录制路径
:param image_path_map: 地图路径 有障碍物的
:param image_path: 原图
:return:
'''
self.on_rec = True
self.isRunRec=True
self.interest_point=[]
# 获取窗口句柄
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
if is_daditu:
left, top, right, bottom = 960 - 200, 540 - 200, 960 + 200, 540 + 200
else:
left, top, right, bottom = self.小地图区域 # 替换成你实际的区域坐标
roi = None
result_post=(0,0)
big_img = cv2.imdecode(np.fromfile(file=image_path, dtype=np.uint8), cv2.IMREAD_COLOR) # 加载大图
big_height, big_width, big_td = big_img.shape
# if big_td==3:
# # # 将24位彩色图片转换为32位彩色图片
# big_img = cv2.cvtColor(big_img, cv2.COLOR_BGR2BGRA)#BGRA COLOR_BGR2BGRA
big_img_yt = big_img.copy()
logger.info("载入地图成功")
while True:
if get_window_handle_at_mouse_position() != hwnd:
logger.info("鼠标离开游戏了!")
time.sleep(0.5)
continue
# #time.sleep(interval)
if state.开关_是否展预测结果:
#cv2.waitKey(100)
pass
if self.on_rec == False:
# 分割路径为目录和文件名
dir_path, filename = os.path.split(image_path)
# 分割文件名和后缀
name, extension = os.path.splitext(filename)
new_file=image_path_lujin
cv2.circle(big_img, result_post, 2, (0,0, 255), -1)
for point in self.interest_point:
cv2.circle(big_img, point, 2, (0, 255, 0), -1)
# 保存图像
with open(new_file, 'wb') as f:
f.write( cv2.imencode(extension, big_img)[1].tobytes())
logger.info("录制完成! 保存在了:"+new_file)
state.QT_信号.mysig_tishi.emit("录制完成! 保存在了:"+new_file)
return
if is_daditu:
tili_img = cv2.imdecode(np.fromfile(file="datas/体力图标.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED)
#tili_mask = tili_img[:, :, 3]
if template_matching(screenshot(hwnd, 1415,21,1573,114, None, is_top=True), tili_img, mask=None)==[]:
continue
# big_img = big_img_bk.copy()
small_img = screenshot(hwnd, left, top, right, bottom, None,is_top=True)
ret = find_img_all_sift(big_img_yt, small_img,roi)
try:
for result in ret:
result_post = [result["result"][0], result["result"][1]]
sm_width,sm_height= result["rectangle"][2][0]-result["rectangle"][0][0],result["rectangle"][2][1]-result["rectangle"][0][1]
cv2.circle(big_img, result_post, 2, (255, 0, 0), -1)
roi = [result["rectangle"][0][0]-40 ,result["rectangle"][0][1]-40, sm_width+80 , sm_height+80 ]
if roi[0] < 0:
roi[0] = 0
if roi[1] < 0:
roi[1] = 0
if roi[2] > big_width:
roi[0] = big_width - roi[2]
if roi[3] > big_height:
roi[1] = big_height - roi[3]
self.now_point = result_post
# 显示匹配结果
break
except :
roi=None
if state.开关_是否展预测结果:
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
#cv2.imshow('Genshin navigation'+sj, big_img)
if state.开关_是否展预测结果:
pass
#cv2.destroyAllWindows()
return True
def run_chuansong(self, image_path,maodian_path=""):
'''
传送
:param image_path_map: 地图路径 有障碍物的
:param image_path: 原图
:return:
'''
# 获取窗口句柄
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
rect = win32gui.GetWindowRect(hwnd)
w_p, h_p = (rect[2] - rect[0]) - 1920, (rect[3] - rect[1]) - 1080
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
left, top, right, bottom =0,0,1920,1080 # 替换成你实际的区域坐标
p_left = rect[0] + w_p
p_top = rect[1] + h_p
roi = None
moban_img = cv2.imdecode(np.fromfile(file=image_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
if maodian_path!="":
moban_maodian_img = cv2.imdecode(np.fromfile(file=maodian_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
else:
moban_maodian_img=None
chuangsong_img=cv2.imdecode(np.fromfile(file="./datas/传送按钮.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED)
chuangsong1_img = cv2.imdecode(np.fromfile(file="./datas/传送按钮1.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED)
def ddd():
paimeng_img = cv2.imdecode(np.fromfile(file="datas/背包图标.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED)
for _ in range(20):
time.sleep(1)
big_img = screenshot(hwnd,1428,972,1557,1061, None)
res = template_matching(big_img, paimeng_img, mask=None)
if state.状态_循环开关 == False:
logger.info("强制退出!")
state.状态_需重新传送 = False
return False
for result in res:
result_post = [result["result"][0], result["result"][1]]
logger.info("传送完成!")
# 转换为 NumPy 数组
pts = np.array(
(
result['rectangle'][0], result['rectangle'][1], result['rectangle'][3], result['rectangle'][2]),
np.int32)
# 将数组从行向量转换为列向量
# pts = pts.reshape((-1, 1, 2))
if state.开关_是否展预测结果:
cv2.circle(big_img, result_post, 10, (0, 0, 255), -1)
cv2.polylines(big_img, [pts], True, (0, 255, 0), 5)
# cv2.imshow('Genshin navigation' , big_img)
cv2.imwrite("./output.jpg", big_img)
state.QT_信号.mysig_show_xunlu.emit()
state.状态_传送中 = False
state.状态_需重新传送 = False
return True
state.状态_需重新传送 = True
logger.info("需要重新传送! (注意检查一下 T键是不是被你改了!!以及桌面缩放是否为100% 或者游戏刚更新新版本UI布局变了)")
return False
big_img = screenshot(hwnd, left, top, right, bottom, None)
res = find_img_all_sift(big_img, moban_img,roi)
time.sleep(1)
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
set_window_activate(hwnd)
time.sleep(0.2)
if state.状态_循环开关== False:
logger.info("强制退出!")
state.状态_需重新传送 = False
return False
try:
if len(res) == 0:
logger.info(f"没定位到传送模板")
state.状态_需重新传送 = True
return False
for result in res:
logger.info("找到了传送位置")
result_post = [result["result"][0], result["result"][1]]
if state.开关_是否展预测结果:
cv2.circle(big_img, result_post, 10, (0, 0, 255), -1)
cv2.polylines(big_img, result['dst_pot'], True, (0, 255, 0), 5)
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
#cv2.waitKey(100)
# 显示匹配结果
mouse_move(p_left +result_post[0], p_top + result_post[1])
time.sleep(0.1)
mouse_left_down()
time.sleep(0.1)
mouse_left_up()
time.sleep(0.5)
break
except Exception as err:
logger.info(f"没找到传送位置{err}")
state.状态_需重新传送 = True
return False
time.sleep(0.5)
if state.状态_循环开关 == False:
state.状态_需重新传送 = False
logger.info("强制退出!")
return False
big_img = screenshot(hwnd, left, top, right, bottom, None)
res=template_matching(big_img, chuangsong_img, mask=None)
if res==[]:
res = template_matching(big_img, chuangsong1_img, mask=None)
ret = False
try:
for result in res:
result_post = [result["result"][0], result["result"][1]]
logger.info(f"找到了传送按钮1{result_post} {result['confidence']}")
# 转换为 NumPy 数组
pts = np.array((result['rectangle'][0], result['rectangle'][1], result['rectangle'][3], result['rectangle'][2]), np.int32)
# 将数组从行向量转换为列向量
#pts = pts.reshape((-1, 1, 2))
if state.开关_是否展预测结果:
cv2.circle(big_img, result_post, 10, (0, 0, 255), -1)
cv2.polylines(big_img, [pts], True, (0, 255, 0), 5)
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
# cv2.waitKey(100)
# 显示匹配结果
mouse_move(p_left + result_post[0], p_top + result_post[1])
time.sleep(0.1)
mouse_left_down()
time.sleep(0.1)
mouse_left_up()
time.sleep(0.5)
return ddd()
except Exception as err:
logger.info(f"没有找到传送按钮{err}")
state.状态_需重新传送 = True
return False
if ret != True:
time.sleep(0.5)
if state.状态_循环开关== False:
state.状态_需重新传送 = False
logger.info("强制退出!")
return False
big_img = screenshot(hwnd, left, top, right, bottom, None)
res = find_img_all_sift(big_img, moban_maodian_img, None)
ret = False
try:
if res == []:
logger.info("传送失败")
state.状态_需重新传送 = True
return False
for result in res:
result_post = [result["result"][0], result["result"][1]]
if result["result"][0]<581 and result["result"][1]<401:
ret = False
continue
if result['confidence']<0.8:
ret = False
continue
logger.info(f"找到了锚点选项 {result_post} {result['confidence']}")
if state.开关_是否展预测结果:
cv2.circle(big_img, result_post, 10, (0, 0, 255), -1)
cv2.polylines(big_img, result['dst_pot'], True, (0, 255, 0), 5)
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
# cv2.waitKey(100)
# 显示匹配结果
mouse_move(p_left + result_post[0], p_top + result_post[1])
time.sleep(0.1)
mouse_left_down()
time.sleep(0.1)
mouse_left_up()
time.sleep(0.5)
ret = True
break
except Exception as err:
logger.info(f"没找到锚点选项{err}" )
state.状态_需重新传送 = True
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
time.sleep(1)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
return False
if ret == True:
big_img = screenshot(hwnd, left, top, right, bottom, None)
res = template_matching(big_img, chuangsong_img, mask=None)
if res == []:
res = template_matching(big_img, chuangsong1_img, mask=None)
if state.状态_循环开关 == False:
logger.info("强制退出!")
state.状态_需重新传送 = False
return False
try:
if res==[]:
logger.info("传送失败")
state.状态_需重新传送 = True
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
time.sleep(1)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
return False
for result in res:
result_post = [result["result"][0], result["result"][1]]
logger.info(f"找到了传送按钮2{result_post} {result['confidence']}" )
# 转换为 NumPy 数组
pts = np.array((result['rectangle'][0], result['rectangle'][1], result['rectangle'][3],
result['rectangle'][2]), np.int32)
# 将数组从行向量转换为列向量
# pts = pts.reshape((-1, 1, 2))
if state.开关_是否展预测结果:
cv2.circle(big_img, result_post, 10, (0, 0, 255), -1)
cv2.polylines(big_img, [pts], True, (0, 255, 0), 5)
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
# cv2.waitKey(100)
# 显示匹配结果
mouse_move(p_left + result_post[0]+100, p_top + result_post[1])
time.sleep(0.1)
mouse_left_down()
time.sleep(0.1)
mouse_left_up()
time.sleep(0.5)
return ddd()
except Exception as err:
logger.info(f"传送失败{err}" )
state.状态_需重新传送 = True
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
time.sleep(1)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
return False
else:
logger.info("传送失败")
state.状态_需重新传送 = True
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
time.sleep(1)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
return False
#cv2.destroyAllWindows()
return True
def run_playback(self, image_path_map, image_path,wakuang=False):
'''
执行寻路 直到移动到目标为止
:param image_path_map: 地图路径 有障碍物的
:param image_path: 原图
:param isShow: 是否显示地图
[{"probability":0.1,"keys":[ {"key":"1","time":0.2 }, {"key":"e","time":0.5}]}]
代表概率10%(100毫秒一次判断) 按1 0.2秒 然后 按E 1秒 支持无数组合
:return:
'''
try:
self.isRunRec = False
state.状态_循环开关 = True
state.状态_已经有寻路了 = True
state.状态_寻路中 = True
self.load_map(image_path_map)
self.map_matrix_copy = self.map_matrix.copy()
state.计次_定位失败=0
# 获取窗口句柄
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
# 设定保存截图的文件夹路径和文件名前缀
#folder_path = "./datas/img/"
# 设定定时器间隔(秒)
roi=None
big_img_bk = cv2.imdecode(np.fromfile(file=image_path, dtype=np.uint8),cv2.IMREAD_UNCHANGED) # 加载大图
big_height, big_width, big_td = big_img_bk.shape
if big_td==3:
# # 将24位彩色图片转换为32位彩色图片
big_img_bk = cv2.cvtColor(big_img_bk, cv2.COLOR_BGR2BGRA)#BGRA COLOR_BGR2BGRA
template = cv2.imdecode(np.fromfile(file=r"./datas/小图.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED) # 加载透明图
mask = template[:, :, 3] # 提取透明度通道作为掩码
result_old = {"result": [0, 0]}
state.计数_卡主次数=0
state.状态_在爬墙=False
interest_coordinate2=None
interest_coordinate=None
state.游戏_打怪前坐标 = [0, 0]
state.游戏_当前目标坐标 = [0, 0]
state.计次_误差过大=0
self.old_point= [0, 0]
state.计次_识别次数=0
state.计次_移动停滞 =0
is_star=True
except :
logger.info("寻路发生异常"+traceback.format_exc())
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
while True:
#old_time = time.time()
try:
time.sleep(0.05)
if state.状态_循环开关 == False:
logger.info("强制退出!")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return False
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
left, top, right, bottom = self.小地图区域 # 替换成你实际的区域坐标
if state.状态_全局暂停:
time.sleep(1)
continue
if state.计次_定位失败== 999:
logger.info("全军覆没了!寻路退出!")
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计次_误差过大 == 20:
self.old_point = copy.copy(state.游戏_当前目标坐标)
if state.计次_误差过大>= 30:
logger.info("误差过大了30次,重新运行这个任务")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计次_移动停滞>=20:
logger.info("移动停滞了20次,重新运行这个任务")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计次_定位失败>=30:
logger.info("定位失败次数超过30次,重新运行这个任务")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if not state.状态_YOLOV :
time.sleep(1)
continue
big_img = big_img_bk.copy()
#filename = f"{folder_path}{int(time.time())}.png"
height = bottom - top
width = right - left
small_img = screenshot(hwnd, left, top, right, bottom, filename=None,is_top=True)#RGBA
if type(small_img)==bool:
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
time.sleep(1)
continue
# 识别方向
_, max_similarity, best_angle, best_rotated_template = pyramid_template_matching(
small_img[int(height / 2) - 30:int(height / 2) + 30, int(width / 2) - 30:int(width / 2) + 30],
template,
mask=mask)
best_angle = int(best_angle)
#cv2.imwrite(filename,small_img)
#cv2.imwrite(f"{folder_path}{int(time.time())}_111.png",small_img[int(height / 2) - 30:int(height / 2) + 30, int(width / 2) - 30:int(width / 2) + 30])
state.游戏_当前视野角度=best_angle
state.游戏_当前导航角度=best_angle
#print(state.游戏_当前视野角度,state.游戏_当前导航角度)
# 裁剪图像,去除Alpha通道
# small_img=small_img[:, :, :3]
#识别定位
ret = find_img_all_sift(big_img, small_img,roi)
if ret==None or ret == []:
logger.info(f"定位失败{state.计次_定位失败} {ret}" )
state.计数_卡主次数 +=1
state.计次_定位失败 += 1
if state.计次_定位失败>=10:
pyautogui.keyDown("w")
time.sleep(0.3)
pyautogui.keyUp("w")
# 如果定位失败,判断派蒙是否存在
#如果派蒙不在 并且不是在连招过程中,则说明现在 在不明界面中,尝试按ESC键和点击指定位置跳过对话
if best_angle==-1 and state.状态_是否回放中==False:
logger.info("发现不明界面,尝试按ESC键和点击指定位置跳过对话")
rect = win32gui.GetWindowRect(hwnd)
w_p, h_p = (rect[2] - rect[0]) - 1920, (rect[3] - rect[1]) - 1080
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
p_left = rect[0] + w_p
p_top = rect[1] + h_p
mouse_move(p_left + 1431, p_top + 717)
time.sleep(0.2)
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
time.sleep(0.2)
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
if random.randint(0,2)==1:
time.sleep(0.2)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
if state.状态_寻路中:
if roi==None:
if result_old!={"result": [0, 0]}:
ret = [result_old]
else:
roi = None
continue
else:
roi = None
continue
roi=None
if is_star:
threading.Thread(target=跑步).start()
is_star=False
for result in ret:
if result["result"] !=result_old["result"] :
state.计次_定位失败 = 0
sm_width,sm_height= result["rectangle"][2][0]-result["rectangle"][0][0],result["rectangle"][2][1]-result["rectangle"][0][1]
state.游戏_当前坐标 = [result["result"][0], result["result"][1]]
roi = [result["rectangle"][0][0]-40 ,result["rectangle"][0][1]-40, sm_width+80 , sm_height+80 ]
if roi[0]<0:
roi[0]=0
if roi[1]<0:
roi[1]=0
if roi[2]>big_width:
roi[0]=big_width-roi[2]
if roi[3] > big_height:
roi[1] = big_height - roi[3]
self.update_map_show(big_img)
#cv2.imwrite(f'./output.jpg', big_img)
if state.状态_寻路中:
if state.游戏_当前坐标[0] < 0 or state.游戏_当前坐标[1] < 0:
roi = None
break
if state.计次_定位失败>10 or state.计次_误差过大>10:
if abs(state.游戏_当前坐标[0] - self.end[0]) <=60 and abs(state.游戏_当前坐标[1] - self.end[1]) <= 60:
logger.info("已经到达目的地")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
else:
if abs(state.游戏_当前坐标[0] - self.end[0]) <= 10 and abs(state.游戏_当前坐标[1] - self.end[1]) <= 10:
logger.info("已经到达目的地")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
state.计次_识别次数+=1
if state.计次_识别次数>=8:
if state.状态_是否回放中==False and state.状态_寻路中:
if abs(state.游戏_当前坐标[0] - result_old["result"][0]) <=3 and abs(
state.游戏_当前坐标[1] - result_old["result"][1]) <= 3 :
state.计次_移动停滞 += 1
state.计数_卡主次数+=1
if state.计数_卡主次数 >= 6:
if abs(state.游戏_当前坐标[0] - self.end[0]) <= 60 and abs(
state.游戏_当前坐标[1] - self.end[1]) <= 60:
logger.info("非常接近目的地了!但是遇到意外,因此跳过这个任务!")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
if random.randint(0, 1):
pyautogui.keyDown('a')
aaa = -90
else:
pyautogui.keyDown('d')
aaa = 90
pyautogui.keyUp('w')
mouse_moveR(6 * aaa, 0)
state.计数_卡主次数 = 0
logger.info("卡主太多次,尝试按X")
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
time.sleep(1)
pyautogui.keyUp('d')
pyautogui.keyUp('a')
pyautogui.keyDown('w')
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
time.sleep(5)
pyautogui.keyUp('w')
mouse_middle_down()
time.sleep(0.1)
mouse_middle_up()
else:
logger.info("尝试脱困")
pyautogui.keyDown('w')
pyautogui.keyDown('space')
time.sleep(0.2)
pyautogui.keyUp('space')
rrrr = random.randint(1, 20)
if rrrr == 3:
pyautogui.keyDown('a')
time.sleep(1)
pyautogui.keyUp('a')
elif rrrr == 1:
pyautogui.keyDown('d')
time.sleep(1)
pyautogui.keyUp('d')
elif rrrr == 2:
pyautogui.keyUp('w')
pyautogui.keyDown('d')
pyautogui.keyDown('s')
time.sleep(1)
pyautogui.keyUp('s')
pyautogui.keyUp('d')
time.sleep(2)
pyautogui.keyDown('w')
elif rrrr == 4:
pyautogui.keyUp('w')
pyautogui.keyDown('a')
pyautogui.keyDown('s')
time.sleep(1)
pyautogui.keyUp('s')
pyautogui.keyUp('a')
time.sleep(2)
pyautogui.keyDown('w')
time.sleep(0.2)
pyautogui.keyUp('w')
mouse_middle_down()
time.sleep(0.1)
mouse_middle_up()
else:
state.计次_移动停滞 -=1
if state.计次_移动停滞 <= 0:
state.计次_移动停滞=0
state.计数_卡主次数=0
if state.计次_识别次数 >= 8:
result_old = result.copy()
state.计次_识别次数=0
if state.开关_是否展预测结果:
#cv2.polylines(big_img, result['dst_pot'], True, (0, 255, 0), 5)
# 获取小图的宽度和高度
small_height, small_width, small_channels = best_rotated_template.shape
best_rotated_template = cv2.resize(best_rotated_template,
(int(small_width * 2), int(small_height * 2)))
small_height, small_width, small_channels = best_rotated_template.shape
# 计算放置小图像的左上角坐标,使其居中在result位置
x = state.游戏_当前坐标[0] - int(small_width / 2)
y = state.游戏_当前坐标[1] - int(small_height / 2)
# 将小图叠加到大图上
for c in range(small_channels):
big_img[y:y + small_height, x:x + small_width, c] = \
best_rotated_template[:, :, c] * (best_rotated_template[:, :, 3] / 255.0) + \
big_img[y:y + small_height, x:x + small_width, c] * (
1.0 - best_rotated_template[:, :, 3] / 255.0)
if state.状态_寻路中:
# 如果刚刚打完怪.需要回到原位
if state.游戏_打怪前坐标 != [0, 0]:
state.游戏_当前目标坐标 = copy.copy(state.游戏_打怪前坐标)
try:
if abs(state.游戏_当前坐标[0] - state.游戏_打怪前坐标[0]) <= 80 and abs(
state.游戏_当前坐标[1] - state.游戏_打怪前坐标[1]) <= 80:
state.游戏_打怪前坐标 = [0, 0]
logger.info("回到之前的位置了")
continue
except:
state.游戏_打怪前坐标 = [0, 0]
logger.info("回到之前的位置了")
continue
else:
state.游戏_当前目标坐标,interest_coordinate = self.find_nearest_coordinate(self.map_matrix_copy, state.游戏_当前坐标,100,distance_min=15)
if state.游戏_当前目标坐标 == None:
state.游戏_当前目标坐标,interest_coordinate = self.find_nearest_coordinate(self.map_matrix_copy,state.游戏_当前坐标, None, distance_min=15)
if state.游戏_当前目标坐标 == None:
state.游戏_当前目标坐标 = copy.copy(self.old_point)
if self.old_point!=[0,0] and state.游戏_当前目标坐标!=[0,0]:
if abs(state.游戏_当前坐标[0]-self.old_point[0])>=150 or abs(state.游戏_当前坐标[1]-self.old_point[1])>=150:
state.游戏_当前坐标=copy.copy(self.old_point )
logger.info("定位误差过大!!")
state.计次_误差过大+=1
else:
state.计次_误差过大=0
if state.计次_误差过大==0:
self.old_point = copy.copy(state.游戏_当前坐标)
if interest_coordinate!=None:
interest_coordinate2=copy.copy(interest_coordinate)
if interest_coordinate2!=None:
if abs(state.游戏_当前坐标[0] - interest_coordinate2[0]) <= 15 and abs(state.游戏_当前坐标[1] - interest_coordinate2[1]) <= 15:
logger.info("附近有兴趣点!")
state.计时_未寻路 = int(time.time())
state.状态_寻路中 = False
state.游戏_打怪前坐标 = copy.copy(state.游戏_当前目标坐标)
state.计数_没找到任何目标 = 0
state.计数_没找到怪物 = 0
pyautogui.keyUp('w')
state.计数_卡主次数 = 0
state.计次_识别次数 = 0
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
if wakuang :
logger.info("在连招中....")
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
state.状态_是否回放中 = True
tangbaowss.send_msg( "脚本执行#@@#2")
time.sleep(1)
self.remove_coordinates_in_range_map(self.map_matrix_copy, interest_coordinate2, 15,state.游戏_当前目标坐标)
if self.map_matrix_copy[interest_coordinate2[0]][interest_coordinate2[1]]==-1:
interest_coordinate=None
interest_coordinate2=None
self.map_matrix_copy = self.remove_coordinates_in_range_map(self.map_matrix_copy,state.游戏_当前坐标,8, state.游戏_当前目标坐标)
if state.状态_在爬墙==False:
if state.游戏_当前目标坐标 == None:
rettt=set_angle(state.游戏_当前视野角度, self.get_next_angle(state.游戏_当前坐标, self.end))
else:
rettt=set_angle(state.游戏_当前视野角度, self.get_next_angle(state.游戏_当前坐标, state.游戏_当前目标坐标))
if rettt:
time.sleep(0.1)
pyautogui.keyDown('w')
if state.开关_是否展预测结果:
#cv2.circle(big_img, result_post, 5, (0, 0, 255), -1)
cv2.circle(big_img, state.游戏_当前目标坐标, 10, (255, 24, 255), -1)
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
# # 显示匹配结果
# cv2.imshow('Genshin navigation', big_img)
#print(f"识别时间:{time.time() - old_time}")
break
except :
time.sleep(0.3)
state.计数_卡主次数 += 1
state.计次_定位失败 += 1
if state.计次_定位失败 >= 3:
pyautogui.keyDown("w")
time.sleep(0.3)
pyautogui.keyUp("w")
roi = None
logger.info(f"定位失败{state.计次_定位失败} ")
#traceback.print_exc()
def run_playback_daditu(self, image_path_map, image_path,wakuang=False):
'''
执行寻路 直到移动到目标为止 按大地图
:param image_path_map: 地图路径 有障碍物的
:param image_path: 原图
:param isShow: 是否显示地图
[{"probability":0.1,"keys":[ {"key":"1","time":0.2 }, {"key":"e","time":0.5}]}]
代表概率10%(100毫秒一次判断) 按1 0.2秒 然后 按E 1秒 支持无数组合
:return:
'''
try:
self.isRunRec = False
state.状态_循环开关 = True
state.状态_寻路中 = True
state.状态_已经有寻路了 = True
self.load_map(image_path_map)
self.map_matrix_copy = self.map_matrix.copy()
state.计次_定位失败=0
# 获取窗口句柄
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
# 设定保存截图的文件夹路径和文件名前缀
#folder_path = "./datas/img/"
# 设定定时器间隔(秒)
big_img_bk = cv2.imdecode(np.fromfile(file=image_path, dtype=np.uint8),cv2.IMREAD_UNCHANGED) # 加载大图
big_height, big_width, big_td = big_img_bk.shape
if big_td==3:
# # 将24位彩色图片转换为32位彩色图片
big_img_bk = cv2.cvtColor(big_img_bk, cv2.COLOR_BGR2BGRA)#BGRA COLOR_BGR2BGRA
template = cv2.imdecode(np.fromfile(file=r"./datas/小图.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED) # 加载透明图
mask = template[:, :, 3] # 提取透明度通道作为掩码
result_old = {"result": [0, 0]}
state.计数_卡主次数=0
state.状态_在爬墙=False
interest_coordinate2=None
state.游戏_打怪前坐标 = [0, 0]
state.游戏_当前目标坐标 = [0, 0]
self.old_point= [0, 0]
state.计次_识别次数=0
state.计次_移动停滞 =0
old = time.time()
distance=0
延迟中=False
except :
logger.info("寻路2发生异常"+traceback.format_exc())
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
while True:
time.sleep(0.05)
state.状态_开了地图=False
#old_time = time.time()
try:
if state.状态_循环开关 == False:
logger.info("强制退出!")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return False
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
left, top, right, bottom =self.小地图区域# 替换成你实际的区域坐标
if state.状态_全局暂停:
time.sleep(1)
continue
if not state.状态_YOLOV :
logger.info("等待YOLOV识别启动")
time.sleep(1)
continue
if state.计次_定位失败== 999:
logger.info("全军覆没了!寻路退出!")
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计数_卡主次数>=6:
logger.info("卡主次数6次,重新运行这个任务")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计次_定位失败>=15:
logger.info("定位失败次数超过15次,重新运行这个任务")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if not state.状态_寻路中:
延迟中 = False
time.sleep(0.2)
continue
big_img = big_img_bk.copy()
#filename = f"{folder_path}{int(time.time())}.png"
height = bottom - top
width = right - left
small_img = screenshot(hwnd, left, top, right, bottom, filename=None,is_top=True)#RGBA
if type(small_img)==bool:
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
time.sleep(1)
logger.info("截图失败!")
continue
# 识别方向
_, max_similarity, best_angle, best_rotated_template = pyramid_template_matching(
small_img[int(height / 2) - 30:int(height / 2) + 30, int(width / 2) - 30:int(width / 2) + 30],
template,
mask=mask)
best_angle = int(best_angle)
#cv2.imwrite(filename,small_img)
#cv2.imwrite(f"{folder_path}{int(time.time())}_111.png",small_img[int(height / 2) - 30:int(height / 2) + 30, int(width / 2) - 30:int(width / 2) + 30])
state.游戏_当前视野角度=best_angle
state.游戏_当前导航角度=best_angle
#print(state.游戏_当前视野角度,state.游戏_当前导航角度)
# 裁剪图像,去除Alpha通道
# small_img=small_img[:, :, :3]
if not 延迟中 and state.状态_寻路中:
pyautogui.keyUp('d')
pyautogui.keyUp('a')
pyautogui.keyUp('s')
pyautogui.keyUp('w')
state.状态_开了地图 = True
pyautogui.keyDown('m')
time.sleep(0.2)
pyautogui.keyUp('m')
pyautogui.keyUp('w')
time.sleep(1)
small_img = screenshot(hwnd, 960 - 100, 540 - 100, 960 + 100, 540 + 100, filename=None,
is_top=True) # RGBA
if type(small_img) == bool:
logger.info("截图失败!")
hwnd = win32gui.FindWindow(state.GAME_CLASS, state.GAME_TITLE) # 替换成你实际的窗口句柄
time.sleep(1)
continue
#识别定位MW
ret = find_img_all_sift(big_img, small_img)
pyautogui.keyDown('m')
time.sleep(0.2)
pyautogui.keyUp('m')
time.sleep(1)
state.状态_开了地图 = False
if ret==None or ret == []:
logger.info(f"定位失败{state.计次_定位失败} {ret}" )
state.计数_卡主次数 += 1
state.计次_定位失败 += 1
if state.计次_定位失败>=2:
pyautogui.keyDown("w")
time.sleep(0.3)
pyautogui.keyUp("w")
# 如果定位失败
if best_angle==-1 and state.状态_是否回放中==False:
logger.info("发现不明界面,尝试按ESC键和点击指定位置跳过对话")
rect = win32gui.GetWindowRect(hwnd)
w_p, h_p = (rect[2] - rect[0]) - 1920, (rect[3] - rect[1]) - 1080
# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)
p_left = rect[0] + w_p
p_top = rect[1] + h_p
mouse_move(p_left + 1431, p_top + 717)
time.sleep(0.2)
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
time.sleep(0.2)
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
if random.randint(0,2)==1:
time.sleep(0.2)
pyautogui.keyDown("esc")
time.sleep(0.2)
pyautogui.keyUp("esc")
continue
result=ret[0]
if result["result"] !=result_old["result"] :
state.计次_定位失败 = 0
state.游戏_当前坐标 = [result["result"][0], result["result"][1]]
if state.状态_寻路中:
if state.游戏_当前坐标[0] < 0 or state.游戏_当前坐标[1] < 0:
logger.info("坐标异常,重新定位 "+str(state.游戏_当前坐标))
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = True
return False
if state.计次_定位失败>14 :
if abs(state.游戏_当前坐标[0] - self.end[0]) <=30 and abs(state.游戏_当前坐标[1] - self.end[1]) <= 30:
logger.info("已经接近目的地")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
else:
if abs(state.游戏_当前坐标[0] - self.end[0]) <= 10 and abs(state.游戏_当前坐标[1] - self.end[1]) <= 10:
logger.info("已经到达目的地")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
if state.状态_是否回放中==False :
if abs(state.游戏_当前坐标[0] - result_old["result"][0]) <=3 and abs(
state.游戏_当前坐标[1] - result_old["result"][1]) <= 3 :
state.计数_卡主次数+=1
if state.计数_卡主次数 >= 4:
if abs(state.游戏_当前坐标[0] - self.end[0]) <= 30 and abs(
state.游戏_当前坐标[1] - self.end[1]) <= 30:
logger.info("非常接近目的地了!但是遇到意外,因此跳过这个任务!")
pyautogui.keyUp('w')
state.状态_已经有寻路了 = False
state.状态_需重新传送 = False
return True
if random.randint(0, 1):
pyautogui.keyDown('a')
aaa = -90
else:
pyautogui.keyDown('d')
aaa = 90
pyautogui.keyUp('w')
mouse_moveR(6 * aaa, 0)
logger.info("卡主太多次,尝试按X"+str(state.计数_卡主次数))
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
time.sleep(1)
pyautogui.keyUp('d')
pyautogui.keyUp('a')
pyautogui.keyDown('w')
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
time.sleep(5)
pyautogui.keyUp('w')
time.sleep(0.2)
else:
if random.randint(0, 1):
pyautogui.keyDown('a')
aaa = -20
else:
pyautogui.keyDown('d')
aaa = 20
pyautogui.keyUp('w')
mouse_moveR(6 * aaa, 0)
logger.info("尝试脱困"+str(state.计数_卡主次数))
pyautogui.keyDown('w')
pyautogui.keyDown('space')
time.sleep(0.2)
pyautogui.keyUp('space')
rrrr = random.randint(1, 20)
if rrrr == 3:
pyautogui.keyDown('a')
time.sleep(1)
pyautogui.keyUp('a')
elif rrrr == 1:
pyautogui.keyDown('d')
time.sleep(1)
pyautogui.keyUp('d')
elif rrrr == 2:
pyautogui.keyUp('w')
pyautogui.keyDown('d')
pyautogui.keyDown('s')
time.sleep(1)
pyautogui.keyUp('s')
pyautogui.keyUp('d')
time.sleep(2)
pyautogui.keyDown('w')
elif rrrr == 4:
pyautogui.keyUp('w')
pyautogui.keyDown('a')
pyautogui.keyDown('s')
time.sleep(1)
pyautogui.keyUp('s')
pyautogui.keyUp('a')
time.sleep(2)
pyautogui.keyDown('w')
time.sleep(0.2)
pyautogui.keyUp('s')
pyautogui.keyUp('a')
pyautogui.keyUp('w')
time.sleep(0.2)
else:
state.计数_卡主次数-=1
if state.计数_卡主次数<0:
state.计数_卡主次数=0
result_old = result.copy()
state.游戏_当前目标坐标,interest_coordinate = self.find_nearest_coordinate(self.map_matrix_copy,state.游戏_当前坐标, None, distance_min=15)
if state.游戏_当前目标坐标 == None:
state.游戏_当前目标坐标 = copy.copy(self.old_point)
self.old_point = copy.copy(state.游戏_当前坐标)
if interest_coordinate!=None:
interest_coordinate2=copy.copy(interest_coordinate)
if interest_coordinate2!=None:
if abs(state.游戏_当前目标坐标[0] - interest_coordinate2[0]) <= 10 and abs(state.游戏_当前目标坐标[1] - interest_coordinate2[1]) <= 10 and abs(state.游戏_当前目标坐标[0] - state.游戏_当前坐标[0]) <= 30 and abs(state.游戏_当前目标坐标[1] - state.游戏_当前坐标[1]) <= 30:
logger.info("附近有兴趣点!")
state.计时_未寻路 = int(time.time())
state.状态_寻路中 = False
state.游戏_打怪前坐标 = copy.copy(state.游戏_当前目标坐标)
state.计数_没找到任何目标 = 0
state.计数_没找到怪物 = 0
pyautogui.keyUp('w')
state.计数_卡主次数 = 0
state.计次_识别次数 = 0
mouse_left_down()
time.sleep(0.2)
mouse_left_up()
if wakuang :
logger.info("在连招中....")
pyautogui.keyDown('x')
time.sleep(0.2)
pyautogui.keyUp('x')
state.状态_是否回放中 = True
tangbaowss.send_msg( "脚本执行#@@#2")
time.sleep(1)
self.remove_coordinates_in_range_map(self.map_matrix_copy, interest_coordinate2, 10,state.游戏_当前目标坐标)
if self.map_matrix_copy[interest_coordinate2[0]][interest_coordinate2[1]]==-1:
interest_coordinate2=None
self.map_matrix_copy = self.remove_coordinates_in_range_map(self.map_matrix_copy,state.游戏_当前坐标,30, state.游戏_当前目标坐标)
if state.状态_寻路中:
pyautogui.keyDown('w')
if state.状态_在爬墙 == False:
if state.游戏_当前目标坐标 == None:
state.游戏_当前目标坐标=self.end
set_angle(state.游戏_当前视野角度, self.get_next_angle(state.游戏_当前坐标, state.游戏_当前目标坐标))
if state.计次_定位失败 == 0 and 延迟中==False:
延迟中 = True
old=time.time()
distance = math.sqrt((state.游戏_当前目标坐标[0] - state.游戏_当前坐标[0]) ** 2 + (
state.游戏_当前目标坐标[1] - state.游戏_当前坐标[1]) ** 2)
# print(units_to_seconds(distance))
else:
if time.time()-old>units_to_seconds(distance):
延迟中 = False
if state.开关_是否展预测结果:
self.update_map_show(big_img)
try:
#cv2.polylines(big_img, result['dst_pot'], True, (0, 255, 0), 5)
# 获取小图的宽度和高度
small_height, small_width, small_channels = best_rotated_template.shape
best_rotated_template = cv2.resize(best_rotated_template,
(int(small_width * 2), int(small_height * 2)))
small_height, small_width, small_channels = best_rotated_template.shape
# 计算放置小图像的左上角坐标,使其居中在result位置
x = state.游戏_当前坐标[0] - int(small_width / 2)
y = state.游戏_当前坐标[1] - int(small_height / 2)
# 将小图叠加到大图上
for c in range(small_channels):
big_img[y:y + small_height, x:x + small_width, c] = \
best_rotated_template[:, :, c] * (best_rotated_template[:, :, 3] / 255.0) + \
big_img[y:y + small_height, x:x + small_width, c] * (
1.0 - best_rotated_template[:, :, 3] / 255.0)
cv2.circle(big_img, state.游戏_当前目标坐标, 10, (255, 24, 255), -1)
except:
pass
if big_img.shape[2] == 4:
state.图片_找图 = cv2.cvtColor(big_img, cv2.COLOR_BGRA2BGR)
else:
state.图片_找图 = big_img
state.QT_信号.mysig_show_xunlu.emit()
# # 显示匹配结果
# cv2.imshow('Genshin navigation', big_img)
#print(f"识别时间:{time.time() - old_time}")
except :
time.sleep(0.3)
state.计数_卡主次数 +=1
state.计次_定位失败 += 1
if state.计次_定位失败 >= 10:
pyautogui.keyDown("w")
time.sleep(0.3)
pyautogui.keyUp("w")
#roi = None
logger.info(f"定位失败{state.计次_定位失败} ")
traceback.print_exc()
def update_map_show(self,big_img):
for rdex, rowitem in enumerate(self.map_matrix_copy):
for cdex, column in enumerate(rowitem):
# 只判断符合范围内的 并且是 >1则是路线范围的坐标
if column > 0:
point=(rdex,cdex)
if column==1:
cv2.circle(big_img, point, 2, (255, 0, 0), -1)
elif column==2:
cv2.circle(big_img, point, 4, (0, 255, 0), -1)
elif column==3:
cv2.circle(big_img, point, 4, (0, 0, 255), -1)
def get_next_angle(self, start_pos, next_pos):
# 计算方向向量
direction_x = next_pos[0] - start_pos[0]
direction_y = next_pos[1] - start_pos[1]
# 使用反正切函数计算弧度角度值
angle_rad = math.atan2(direction_y, direction_x)
# 将弧度角度值转换为以北方向为0度的角度
angle_deg = math.degrees(angle_rad)
# 将角度值转换为顺时针方向
angle_deg = int((angle_deg + 360 + 90) % 360)
return angle_deg
def find_nearest_coordinate(self,coordinates, my_position,range_limit=100,distance_min=0):
'''
寻找当前位置最近的坐标点 顺便返回最近的兴趣点
:param coordinates:
:param my_position:
:param range_limit: # 搜索范围半径为50 提高效率
:return:
'''
min_distance_coordinate = float('inf')
nearest_coordinate =None
interest_coordinate=None
for rdex,rowitem in enumerate(coordinates) :
for cdex,column in enumerate(rowitem):
#只判断符合范围内的 并且是 >1则是路线范围的坐标
if column>0:
#x 附近 range_limit 范围的点 y 附近 range_limit 范围的点
if range_limit!=None:
if abs(my_position[0]-rdex)<=range_limit and abs(my_position[1]-cdex)<=range_limit :
#计算两个坐标点之间的距离 但是不要判断和自己一样的坐标.那没意义
if (my_position[0],my_position[1])!=(rdex,cdex):
distance = math.sqrt((my_position[0] - rdex) ** 2 + (my_position[1] - cdex) ** 2)
if distance>=distance_min:#要比最近小距离大.这样走位才不会老歪歪扭扭
if distance < min_distance_coordinate:
min_distance_coordinate = distance
if column==2:
interest_coordinate=[rdex,cdex]
nearest_coordinate = [rdex,cdex]
else:
# 计算两个坐标点之间的距离 但是不要判断和自己一样的坐标.那没意义
if (my_position[0], my_position[1]) != (rdex, cdex):
distance = math.sqrt((my_position[0] - rdex) ** 2 + (my_position[1] - cdex) ** 2)
if distance >= distance_min: # 要比最近小距离大.这样走位才不会老歪歪扭扭
if distance < min_distance_coordinate:
min_distance_coordinate = distance
if column == 2:
interest_coordinate = [rdex, cdex]
nearest_coordinate = [rdex, cdex]
return nearest_coordinate,interest_coordinate
def on_release(self, key: keyboard.KeyCode):
"""定义释放时候的响应"""
if key == Key.f9:#停止
state.状态_循环开关= False
state.状态_全局暂停=True
state.状态_已经有寻路了 = False
state.状态_是否禁止录制=True
self.on_rec = False
logger.info(f"按了F9")
elif key == Key.f8:
self.on_rec = False
if state.状态_是否禁止录制:
if state.状态_循环开关== False:
return
state.状态_全局暂停=not state.状态_全局暂停
logger.info(f"state.状态_全局暂停{state.状态_全局暂停}")
if state.状态_全局暂停:
time.sleep(0.3)
pyautogui.keyUp('w')
elif key ==Key.f10:
if self.isRunRec:
self.interest_point.append(self.now_point)
logger.info(f"标记坐标{self.now_point}")
def load_map(self, image_path):
'''
加载地图 这个地图要障碍物地图
:param image_path:
:return:
'''
logger.info("加载地图中...")
# 读取图片
self.image = Image.open(image_path)
# 获取图片尺寸
self.width, self.height = self.image.size
# 定义地图
self.map_matrix = []
# 根据像素颜色生成地图数据
for x in range(self.width):
row=[]
for y in range(self.height):
pixel = self.image.getpixel((x, y))
if pixel[2] >= 230 and pixel[0] < 20 and pixel[1] < 20: # 蓝色
row.append(1)
elif pixel[0] >= 230 and pixel[1] < 20 and pixel[2] < 20: # 红色
self.end = (x, y)
row.append(3)
elif pixel[1] >= 230 and pixel[0] < 20 and pixel[2] < 20: # 绿色
row.append(2)
else:
row.append(0)
self.map_matrix.append(row)
logger.info("地图加载完毕!")
def remove_coordinates_in_range_map(self, coordinates, center, range_limit,nex_pos):
new_coordinates=coordinates.copy()
for rdex, rowitem in enumerate(new_coordinates):
for cdex, column in enumerate(rowitem):
# 只判断符合范围内的 并且是 >1则是路线范围的坐标
if column > 0:
if (rdex,cdex) == self.end: # 终点不能删除
continue
#将附近的点标记为走过了
elif abs(center[0]-rdex)<=range_limit and abs(center[1]-cdex)<=range_limit:
new_coordinates[rdex][cdex]=-1# 将该点标记为已经走过的,标记为-1
elif abs(center[0] - rdex) <= range_limit*2 and abs(center[1] - cdex) <= range_limit*2:
angle_target = self.get_next_angle(center, nex_pos) # 当前位置对准兴趣点的角度
angle_coordinate = self.get_next_angle(center, (rdex,cdex)) # 当前成员位置对准结束点的角度
angle_diff = abs(angle_target - angle_coordinate)
if angle_diff > 160 and angle_diff<=220 :
new_coordinates[rdex][cdex]=-1# 将该点标记为已经走过的,标记为-1
return new_coordinates
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/LanRenZhiNeng/ming-chao-ai.git
git@gitee.com:LanRenZhiNeng/ming-chao-ai.git
LanRenZhiNeng
ming-chao-ai
MingChaoAI
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385