Files
wow/stuck_handler.py
2026-03-23 09:50:08 +08:00

91 lines
2.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import math
import time
import random
import pyautogui
class StuckHandler:
# 针对 0.xxxx 坐标系优化
DEFAULT_MIN_MOVE = 0.002 # 极其微小的位移也算移动
DEFAULT_STUCK_DURATION = 2.5 # 减少等待时间,提高效率
TURN_GRACE_SEC = 1.0 # 缩短宽限期,边走边转不需要 5 秒
def __init__(self, min_move_threshold=None, stuck_duration_sec=None):
self.last_pos = None
self.stuck_start_time = 0
self.min_move = min_move_threshold or self.DEFAULT_MIN_MOVE
self.stuck_duration = stuck_duration_sec or self.DEFAULT_STUCK_DURATION
def check_stuck(self, state, last_turn_time):
"""
检测卡死:
只有在正在前进按住W且坐标长时间不刷新时触发。
"""
current_pos = (state['x'], state['y'])
now = time.time()
# 1. 初始化
if self.last_pos is None:
self.last_pos = current_pos
return False
# 2. 计算位移
dist = math.sqrt(
(current_pos[0] - self.last_pos[0]) ** 2 +
(current_pos[1] - self.last_pos[1]) ** 2
)
# 3. 核心判定:
# 如果位移足够大,重置所有计数
if dist > self.min_move:
self.stuck_start_time = 0
self.last_pos = current_pos
return False
# 4. 位移不足时的处理
# 宽限期优化:只有在非频繁转向时才开始计时
# (避免边走边转的短脉冲把卡死计时器刷掉)
if last_turn_time and (now - last_turn_time) < 0.2:
# 如果刚刚那一瞬间正在转向脉冲中,本帧跳过,不重置计数也不判定
return False
if self.stuck_start_time == 0:
self.stuck_start_time = now
elif (now - self.stuck_start_time) >= self.stuck_duration:
return True
return False
def resolve_stuck(self):
"""增强版脱困针对血DK挂机环境"""
print(">>> [警告] 检测到撞墙,正在执行脱困动作...")
# 1. 全停
for k in ("w", "a", "d", "s"):
pyautogui.keyUp(k)
# 2. 倒车并转向(组合动作更有效)
pyautogui.keyDown("s")
turn_key = random.choice(["a", "d"])
pyautogui.keyDown(turn_key)
# 倒车时间稍长一点,离开障碍物
time.sleep(0.5)
# 3. 尝试跳跃脱离地形卡位
pyautogui.press("space")
time.sleep(0.5)
pyautogui.keyUp(turn_key)
pyautogui.keyUp("s")
# 4. 往前稍微走一步,重新锁定坐标
pyautogui.keyDown("w")
time.sleep(0.5)
pyautogui.keyUp("w")
self.reset()
print(">>> 脱困尝试结束")
def reset(self):
self.last_pos = None
self.stuck_start_time = 0