297 lines
8.9 KiB
Python
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()
|