91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
|
|
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
|