Files
luoluo/debug_tools.py

297 lines
8.9 KiB
Python

"""
调试工具集
用于开发和调试时的便捷功能
"""
import sys
import time
import json
from pathlib import Path
from datetime import datetime
sys.path.insert(0, str(Path(__file__).parent))
import win32api
import win32gui
import win32con
from src.core.game_window import GameWindowManager
from src.core.input_simulator import InputSimulator
class CoordinateDebugger:
"""坐标调试器 - 实时显示鼠标坐标"""
def __init__(self):
self.window = None
self.running = False
def capture_window(self):
"""捕获游戏窗口"""
self.window = GameWindowManager()
if self.window.capture_window():
print(f"✅ 已捕获窗口: {self.window.window_title}")
print(f" 窗口大小: {self.window.client_size}")
return True
else:
print("❌ 未找到游戏窗口")
return False
def show_realtime_coords(self):
"""实时显示鼠标坐标"""
print("\n" + "="*60)
print("实时坐标显示")
print("="*60)
print("移动鼠标到游戏窗口内查看坐标")
print("按 Ctrl+C 停止\n")
if not self.window:
print("⚠️ 请先捕获窗口 (选项 1)")
return
self.running = True
last_pos = None
try:
while self.running:
# 获取鼠标屏幕坐标
screen_x, screen_y = win32api.GetCursorPos()
# 获取窗口信息
hwnd = self.window.hwnd
if not hwnd:
print("❌ 窗口已关闭")
break
# 获取窗口客户区位置
client_rect = win32gui.GetClientRect(hwnd)
client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1]))
# 计算窗口相对坐标
rel_x = screen_x - client_left
rel_y = screen_y - client_top
# 只在坐标变化时更新显示
current_pos = (rel_x, rel_y)
if current_pos != last_pos:
# 清行并显示新坐标
print(f"\r屏幕坐标: ({screen_x:4d}, {screen_y:4d}) | "
f"窗口相对: ({rel_x:4d}, {rel_y:4d})", end="", flush=True)
last_pos = current_pos
time.sleep(0.05)
except KeyboardInterrupt:
print("\n\n已停止")
self.running = False
def test_click_at_current_pos(self):
"""在当前鼠标位置测试点击"""
print("\n" + "="*60)
print("测试点击 - 当前鼠标位置")
print("="*60)
if not self.window:
print("⚠️ 请先捕获窗口 (选项 1)")
return
print("3秒后将点击当前鼠标位置...")
time.sleep(3)
# 获取当前鼠标位置
screen_x, screen_y = win32api.GetCursorPos()
# 转换为窗口相对坐标
hwnd = self.window.hwnd
client_rect = win32gui.GetClientRect(hwnd)
client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1]))
rel_x = screen_x - client_left
rel_y = screen_y - client_top
print(f"\n点击位置: 屏幕({screen_x}, {screen_y}) | 窗口相对({rel_x}, {rel_y})")
# 执行点击
sim = InputSimulator(self.window)
sim.click(rel_x, rel_y)
print("✅ 点击完成")
def test_click_at_coords(self):
"""在指定坐标测试点击"""
print("\n" + "="*60)
print("测试点击 - 指定坐标")
print("="*60)
if not self.window:
print("⚠️ 请先捕获窗口 (选项 1)")
return
try:
x = int(input("请输入 X 坐标: "))
y = int(input("请输入 Y 坐标: "))
except ValueError:
print("❌ 无效的坐标")
return
print(f"\n将在 ({x}, {y}) 点击")
print("3秒后开始...")
time.sleep(3)
sim = InputSimulator(self.window)
sim.click(x, y)
print("✅ 点击完成")
class CoordinateRecorder:
"""坐标记录器 - 记录并保存常用坐标"""
def __init__(self, save_file: str = "coordinates.json"):
self.save_file = Path(save_file)
self.coordinates = {}
self.load()
def load(self):
"""加载已保存的坐标"""
if self.save_file.exists():
with open(self.save_file, 'r', encoding='utf-8') as f:
self.coordinates = json.load(f)
else:
self.coordinates = {}
def save(self):
"""保存坐标到文件"""
with open(self.save_file, 'w', encoding='utf-8') as f:
json.dump(self.coordinates, f, ensure_ascii=False, indent=2)
print(f"✅ 坐标已保存到 {self.save_file}")
def record_current_pos(self, name: str, window: GameWindowManager):
"""记录当前鼠标位置"""
screen_x, screen_y = win32api.GetCursorPos()
hwnd = window.hwnd
client_rect = win32gui.GetClientRect(hwnd)
client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1]))
rel_x = screen_x - client_left
rel_y = screen_y - client_top
self.coordinates[name] = {
"x": rel_x,
"y": rel_y,
"screen_x": screen_x,
"screen_y": screen_y,
"recorded_at": datetime.now().isoformat()
}
print(f"✅ 已记录 '{name}': ({rel_x}, {rel_y})")
def list_coordinates(self):
"""列出所有记录的坐标"""
if not self.coordinates:
print("⚠️ 没有记录的坐标")
return
print("\n" + "="*60)
print("已记录的坐标:")
print("="*60)
for name, coord in self.coordinates.items():
print(f" {name}: ({coord['x']}, {coord['y']})")
def get_coordinate(self, name: str) -> tuple:
"""获取指定名称的坐标"""
if name in self.coordinates:
coord = self.coordinates[name]
return (coord['x'], coord['y'])
return None
def delete_coordinate(self, name: str):
"""删除指定坐标"""
if name in self.coordinates:
del self.coordinates[name]
print(f"✅ 已删除 '{name}'")
else:
print(f"❌ 未找到 '{name}'")
def show_menu():
"""显示主菜单"""
print("\n" + "="*60)
print("调试工具菜单")
print("="*60)
print("1. 捕获游戏窗口")
print("2. 实时显示鼠标坐标")
print("3. 测试点击 - 当前鼠标位置")
print("4. 测试点击 - 指定坐标")
print("5. 记录当前坐标")
print("6. 查看已记录的坐标")
print("7. 删除坐标记录")
print("8. 保存坐标到文件")
print("0. 退出")
def main():
"""主函数"""
debugger = CoordinateDebugger()
recorder = CoordinateRecorder()
print("="*60)
print("LuoLuoTool 调试工具")
print("="*60)
print("请以管理员权限运行此脚本")
while True:
show_menu()
choice = input("\n请选择功能 (0-8): ").strip()
if choice == '0':
print("\n感谢使用,再见!")
break
elif choice == '1':
debugger.capture_window()
elif choice == '2':
debugger.show_realtime_coords()
elif choice == '3':
debugger.test_click_at_current_pos()
elif choice == '4':
debugger.test_click_at_coords()
elif choice == '5':
if not debugger.window:
print("⚠️ 请先捕获窗口 (选项 1)")
continue
name = input("请输入坐标名称 (如: '主界面按钮', '开始游戏'): ").strip()
if name:
recorder.record_current_pos(name, debugger.window)
else:
print("❌ 名称不能为空")
elif choice == '6':
recorder.list_coordinates()
elif choice == '7':
recorder.list_coordinates()
name = input("请输入要删除的坐标名称: ").strip()
if name:
recorder.delete_coordinate(name)
elif choice == '8':
recorder.save()
else:
print("❌ 无效选项")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n程序被用户中断")
except Exception as e:
print(f"\n❌ 发生错误: {e}")
import traceback
traceback.print_exc()