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 |