Задать вопрос
Sterrist
@Sterrist
Python Junior Developer

Как наводить прицел точно на персонажа?

У меня есть код аимбота на Python с YOLOv11 для Fortnite, но у меня не получается сделать позиционирование прицела, прицел прыгает вокруг цели

моя модель

Вот мой код

import cv2
import numpy as np
from ultralytics import YOLO
import torch
import ctypes
from ctypes.wintypes import DWORD, WORD
import keyboard
import mss
import win32api
import win32gui
import vgamepad as vg

# Инициализация виртуального геймпада (DualShock4)
gamepad = vg.VDS4Gamepad()

# Чувствительность для джойстика
sensitivity = 150.0

model = YOLO('runs/detect/train/weights/best.pt')
sct = mss.mss()
TARGET_CLASS = "player"
screen_width = win32api.GetSystemMetrics(0)
screen_height = win32api.GetSystemMetrics(1)
center_point = (screen_width // 2, screen_height // 2)
print(f"Screen resolution: {screen_width}x{screen_height}")

device = 'cuda' if torch.cuda.is_available() else 'cpu'

print("Используется:", device) # cuda - видеокарта, cpu - процессор (Лучше cuda)

# Структуры для мыши (оставлены для справки, но не используются с геймпадом)
emptyLong = ctypes.c_ulong()

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", DWORD),
                ("dwFlags", DWORD),
                ("time", DWORD),
                ("dwExtraInfo", ctypes.POINTER(ctypes.c_ulong))]

class KeybdInput(ctypes.Structure):
    _fields_ = [("wVk", WORD),
                ("wScan", WORD),
                ("dwFlags", DWORD),
                ("time", DWORD),
                ("dwExtraInfo", ctypes.POINTER(ctypes.c_ulong))]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", DWORD),
                ("wParamL", WORD),
                ("wParamH", WORD)]

class InputList(ctypes.Union):
    _fields_ = [("mi", MouseInput),
                ("ki", KeybdInput),
                ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("inputList", InputList)]

MOUSEEVENTF_MOVE = 0x0001
MOUSEEVENTF_ABSOLUTE = 0x8000

# Получение позиции и размера окна игры
game_window_title = "Fortnite"
hwnd = win32gui.FindWindow(None, game_window_title)
if hwnd:
    rect = win32gui.GetWindowRect(hwnd)
    window_x, window_y, window_width, window_height = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
    client_rect = win32gui.GetClientRect(hwnd)
    client_width, client_height = client_rect[2] - client_rect[0], client_rect[3] - client_rect[1]
else:
    print("Окно игры не найдено!")
    window_x, window_y, client_width, client_height = 0, 0, 1920, 1080


# Определение параметров геймпада
if isinstance(gamepad, vg.VX360Gamepad):
    GAMEPAD_TYPE = "X360"
    CENTER = 0
    MIN_VAL = -32768
    MAX_VAL = 32767
    SIGN_Y = -1
    SCALE_FACTOR = 1
elif isinstance(gamepad, vg.VDS4Gamepad):
    GAMEPAD_TYPE = "DS4"
    CENTER = 128
    MIN_VAL = 0
    MAX_VAL = 255
    SIGN_Y = 1  # Исправлено для DualShock4
    SCALE_FACTOR = 127.5 / 32767.5
else:
    raise ValueError("Unsupported gamepad type")


MOUSEEVENTF_MOVE = 0x0001
MOUSEEVENTF_ABSOLUTE = 0x8000

# Получение позиции и размера окна игры
game_window_title = "Fortnite"
hwnd = win32gui.FindWindow(None, game_window_title)
if hwnd:
    rect = win32gui.GetWindowRect(hwnd)
    window_x, window_y, window_width, window_height = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
    client_rect = win32gui.GetClientRect(hwnd)
    client_width, client_height = client_rect[2] - client_rect[0], client_rect[3] - client_rect[1]
else:
    print("Окно игры не найдено!")
    window_x, window_y, client_width, client_height = 0, 0, 1920, 1080

# Параметры для DualShock4
CENTER = 128
MIN_VAL = 0
MAX_VAL = 255
STICK_OFFSET = 250  # Начальное значение для отклонения джойстика (подстройте под игру)

def real_time_detect(image):
    # Получаем результаты детекции
    results = model(image)[0]
    
    # Исходное изображение
    image = results.orig_img
    
    # Словарь классов и цвета для визуализации
    classes_names = results.names
    colors = np.random.uniform(0, 255, size=(len(classes_names), 3))
    
    # Сбор детекций
    detections = []
    
    # Обрабатываем каждую детекцию
    for box, cls, conf in zip(results.boxes.xyxy.cpu().numpy(), 
                             results.boxes.cls.cpu().numpy(), 
                             results.boxes.conf.cpu().numpy()):
        class_id = int(cls)
        class_name = classes_names[class_id]
        box = box.astype(np.int32)
        confidence = float(conf)
        
        # Добавляем детекцию в список
        detections.append((class_name, confidence, box, class_id))
        
        # Визуализация (опционально)
        color = colors[class_id % len(colors)]
        x1, y1, x2, y2 = box
        cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
        cv2.putText(image, f"{class_name} {confidence:.2f}", 
                   (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, color, 2)

    # Отображение общего количества объектов
    cv2.putText(image, f'Total objects: {len(detections)}', 
               (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

    return image, detections

# Функция для поиска ближайшей цели
def find_closest_target(detections, center_point):
    target_detections = [d for d in detections if d['class_name'] == TARGET_CLASS]
    if not target_detections:
        return None
    closest = None
    min_distance = float('inf')
    for detection in target_detections:
        x, y, w, h = detection['bbox']
        target_center_x = (x + w / 2).item()
        target_center_y = (y + h / 2).item()
        distance = ((target_center_x - center_point[0]) ** 2 + (target_center_y - center_point[1]) ** 2) ** 0.5
        if distance < min_distance:
            min_distance = distance
            closest = (int(target_center_x), int(target_center_y))
    return closest

def check_pgup():
    return keyboard.is_pressed('pgup')

def capture_screen(img):
    """Захват всего экрана"""
    img = np.array(img)
    return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)

# Основной цикл
cap = cv2.VideoCapture(0)
cap.set(3, screen_width)
cap.set(4, screen_height)

# Проверка разрешения захвата
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"Capture resolution: {w}x{h}")
if w != screen_width or h != screen_height:
    print("Warning: Capture resolution does not match screen resolution! Adjust OBS settings.")

while True:
    ret, frame = cap.read()
    if not ret:
        continue

    # Выполнение детекции
    results = model(frame, agnostic_nms=True)
    detections = []
    for r in results:
        boxes = r.boxes
        for box in boxes:
            x1, y1, x2, y2 = box.xyxy[0]
            x, y, w, h = x1, y1, x2 - x1, y2 - y1
            conf = box.conf[0]
            cls = int(box.cls[0])
            class_name = model.names[cls]
            detections.append({'bbox': (x, y, w, h), 'conf': conf, 'class_name': class_name})

    # Визуализация детекций
    for det in detections:
        x, y, w, h = det['bbox']
        cv2.rectangle(frame, (int(x), int(y)), (int(x+w), int(y+h)), (0, 255, 0), 2)
        cv2.putText(frame, f"{det['class_name']} {det['conf']:.2f}", (int(x), int(y-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
    cv2.imshow('YOLO Vision', frame)

    # Проверка нажатия 'Page Up' для активации аимбота
    if keyboard.is_pressed('page up'):  # Используем 'page up' для надежности
        if detections:
            target = find_closest_target(detections, center_point)
            if target:
                # Вычисляем смещение до цели
                offset_x = target[0] - center_point[0]
                offset_y = target[1] - center_point[1]
                
                # Определяем направление движения
                dir_x = 1 if offset_x > 0 else -1 if offset_x < 0 else 0
                dir_y = 1 if offset_y > 0 else -1 if offset_y < 0 else 0
                
                # Устанавливаем небольшое отклонение джойстика
                stick_x = CENTER + dir_x * STICK_OFFSET
                stick_y = CENTER + dir_y * STICK_OFFSET
                
                # Ограничиваем значения в диапазоне 0-255
                stick_x = max(min(stick_x, MAX_VAL), MIN_VAL)
                stick_y = max(min(stick_y, MAX_VAL), MIN_VAL)
                
                # Устанавливаем положение джойстика
                gamepad.right_joystick(int(stick_x), int(stick_y))
                gamepad.update()
                print(f"Moving to {target} with joystick values: x={stick_x}, y={stick_y}")
        else:
            # Возвращаем джойстик в нейтральное положение
            gamepad.right_joystick(int(CENTER), int(CENTER))
            gamepad.update()

    # Выход из цикла при нажатии 'q'
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Освобождение ресурсов
cap.release()
cv2.destroyAllWindows()
gamepad.reset()


я пытался сделать наводку но прицел не наводится на персонажа а прыгает туда сюда
  • Вопрос задан
  • 105 просмотров
Подписаться 2 Средний 2 комментария
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы