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.3) # 3. 尝试跳跃脱离地形卡位 pyautogui.press("space") time.sleep(0.3) 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