add 巡逻模式优先上马
This commit is contained in:
@@ -15,7 +15,6 @@ ANGLE_DEADZONE_DEG = 5.0 # 死区,此范围内不按 A/D、只按 W,减
|
||||
# 随机行为:跳跃概率(每帧触发概率,0.005 ≈ 平均 200 帧一次)
|
||||
RANDOM_JUMP_PROB = 0.05
|
||||
|
||||
|
||||
class CoordinatePatrol:
|
||||
"""按航点坐标巡逻,用 pyautogui 按键转向与前进。"""
|
||||
|
||||
@@ -26,6 +25,9 @@ class CoordinatePatrol:
|
||||
angle_threshold_deg=ANGLE_THRESHOLD_DEG,
|
||||
angle_deadzone_deg=ANGLE_DEADZONE_DEG,
|
||||
random_jump_prob=RANDOM_JUMP_PROB,
|
||||
mount_key="x",
|
||||
mount_hold_sec=1.6,
|
||||
mount_retry_after_sec=2.0,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
@@ -33,6 +35,7 @@ class CoordinatePatrol:
|
||||
arrival_threshold: 到达判定距离(游戏坐标单位),默认 0.5
|
||||
angle_threshold_deg: 朝向容差(度),超过此值才按 A/D 转向,默认 ANGLE_THRESHOLD_DEG
|
||||
angle_deadzone_deg: 转向死区(度),此范围内不按 A/D、只按 W,默认 ANGLE_DEADZONE_DEG
|
||||
mount_key / mount_hold_sec / mount_retry_after_sec: 未上马时先上马(与 game_state_config / GUI 一致)
|
||||
"""
|
||||
self.waypoints = waypoints
|
||||
self.current_index = 0
|
||||
@@ -43,6 +46,33 @@ class CoordinatePatrol:
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.last_turn_end_time = 0 # 最近一次结束 A/D 转向的时间,供卡死检测排除原地转向
|
||||
self.stuck_handler = StuckHandler()
|
||||
self._next_mount_allowed = 0.0
|
||||
self.mount_key = str(mount_key).strip() or "x"
|
||||
self.mount_hold_sec = float(mount_hold_sec)
|
||||
self.mount_retry_after_sec = float(mount_retry_after_sec)
|
||||
|
||||
def _ensure_mounted(self, state):
|
||||
"""
|
||||
已上马返回 True。
|
||||
未上马则松开移动键、按住上马键 MOUNT_HOLD_SEC,本帧不走路;返回 False。
|
||||
state 无 mounted 字段时视为无法判断,不拦巡逻(兼容未开 LogicBeacon)。
|
||||
"""
|
||||
if "mounted" not in state:
|
||||
return True
|
||||
if state.get("mounted"):
|
||||
return True
|
||||
self.stop_all()
|
||||
now = time.time()
|
||||
if now < self._next_mount_allowed:
|
||||
return False
|
||||
self.logger.info(
|
||||
f">>> 未上马,先按 {self.mount_key} {self.mount_hold_sec:.1f}s 上马"
|
||||
)
|
||||
pyautogui.keyDown(self.mount_key)
|
||||
time.sleep(self.mount_hold_sec)
|
||||
pyautogui.keyUp(self.mount_key)
|
||||
self._next_mount_allowed = time.time() + self.mount_retry_after_sec
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_distance(p1, p2):
|
||||
@@ -168,6 +198,9 @@ class CoordinatePatrol:
|
||||
self.stop_all()
|
||||
return
|
||||
|
||||
if not self._ensure_mounted(state):
|
||||
return
|
||||
|
||||
# 2. 卡死检测:位移检测逻辑保持在巡逻中
|
||||
if self.stuck_handler.check_stuck(state, self.last_turn_end_time):
|
||||
self.logger.error("!!! 检测到卡死,启动脱困程序 !!!")
|
||||
@@ -250,6 +283,9 @@ class CoordinatePatrol:
|
||||
self.stop_all()
|
||||
return False
|
||||
|
||||
if not self._ensure_mounted(state):
|
||||
return False
|
||||
|
||||
# 1. 卡死检测
|
||||
if self.stuck_handler.check_stuck(state, self.last_turn_end_time):
|
||||
self.stop_all()
|
||||
@@ -311,6 +347,7 @@ class CoordinatePatrol:
|
||||
"""
|
||||
按 path 依次走完所有点后返回。每次调用都必须传入 path。
|
||||
get_state: 可调用对象,每次调用返回当前状态 dict,需包含 'x','y','facing'。
|
||||
若含 'mounted'(LogicBeacon),路径开始前会先上马,每段 navigate_to_point 也会校验。
|
||||
path: [[x,y], ...] 或 [(x,y), ...](如 json.load 得到),本次要走的全部航点。
|
||||
forward: True=正序(0→n),False=倒序(n→0)。
|
||||
阻塞直到走完 path 中所有点或出错,走完返回 True。内含卡死检测。
|
||||
@@ -321,6 +358,17 @@ class CoordinatePatrol:
|
||||
points = [(float(p[0]), float(p[1])) for p in path]
|
||||
if not forward:
|
||||
points = points[::-1]
|
||||
|
||||
# 路径开始前:若 state 含 mounted 且未上马,先完成上马再逐点移动
|
||||
while True:
|
||||
state = get_state()
|
||||
if state is None:
|
||||
self.stop_all()
|
||||
return False
|
||||
if self._ensure_mounted(state):
|
||||
break
|
||||
time.sleep(0.05)
|
||||
|
||||
for i, target in enumerate(points):
|
||||
self.logger.info(f">>> 路径点 {i + 1}/{len(points)}: {target}")
|
||||
while True:
|
||||
|
||||
Reference in New Issue
Block a user