Загрузка данных
import pyautogui
import keyboard
import time
import threading
import random
# Отключаем защитный механизм pyautogui (чтобы мышь могла уходить в край экрана)
pyautogui.FAILSAFE = False
class ParkourBot:
def __init__(self):
self.running = False
self.block_found = False
self.current_pitch = 0 # Текущий наклон головы (вниз)
self.min_pitch = 15 # Максимальный наклон вниз (в пикселях движения мыши)
self.step_down = 2 # Шаг опускания головы за раз
self.scan_speed = 20 # Скорость горизонтального сканирования (пикселей за шаг)
# Цвета блоков для детекции:
# 1. Темно-красный/бордовый (143, 58, 47)
# 2. Кирпичный/красный (178, 74, 58)
# 3. Близкие оттенки (добавлены похожие цвета)
self.block_colors = [
(143, 58, 47), # Основной темный красный
(178, 74, 58), # Основной кирпичный
(150, 60, 50), # Промежуточный темный
(170, 70, 55), # Промежуточный светлый
(160, 65, 52), # Средний оттенок
(185, 80, 60), # Более светлый
(140, 55, 45), # Более темный
(190, 75, 62), # Светлый вариант
]
def find_block(self):
"""Сканирует экран на наличие блока"""
try:
screenshot = pyautogui.screenshot()
width, height = screenshot.size
# Ищем в центральной области экрана (крест прицела)
center_x = width // 2
center_y = height // 2
search_radius = 80 # Радиус поиска вокруг центра
# Сначала проверяем центр (самое вероятное место)
pixel = screenshot.getpixel((center_x, center_y))
for block_color in self.block_colors:
if self.color_similar(pixel, block_color, 25):
return True, (center_x, center_y)
# Затем сканируем область вокруг
for y in range(center_y - search_radius, center_y + search_radius, 8):
for x in range(center_x - search_radius, center_x + search_radius, 8):
try:
pixel = screenshot.getpixel((x, y))
for block_color in self.block_colors:
if self.color_similar(pixel, block_color, 25):
return True, (x, y)
except:
continue
return False, None
except Exception as e:
print(f"Ошибка при поиске блока: {e}")
return False, None
def color_similar(self, color1, color2, tolerance):
"""Проверяет схожесть цветов"""
return (abs(color1[0] - color2[0]) < tolerance and
abs(color1[1] - color2[1]) < tolerance and
abs(color1[2] - color2[2]) < tolerance)
def rotate_head_horizontal(self):
"""Плавный поворот головы по горизонтали на 360 градусов"""
print("Сканирую по горизонтали...")
# В Minecraft чувствительность обычно такая, что 50 пикселей = ~360 градусов
# Делаем несколько проходов вправо
for _ in range(3): # 3 полных оборота
if not self.running:
break
# Двигаем мышь вправо плавно
for i in range(0, 180, self.scan_speed):
if not self.running:
break
# Используем moveTo с абсолютными координатами для более точного контроля
pyautogui.moveRel(self.scan_speed, 0, duration=0.02)
time.sleep(0.01)
# Проверяем блок во время движения
found, block_pos = self.find_block()
if found:
self.block_found = True
print(f"Блок обнаружен при сканировании!")
return True
return False
def look_down(self):
"""Опускает голову немного вниз"""
if self.current_pitch < self.min_pitch:
pyautogui.moveRel(0, self.step_down, duration=0.05)
self.current_pitch += self.step_down
print(f"Опускаю голову. Наклон: {self.current_pitch}")
def reset_head_position(self):
"""Возвращает голову в исходное положение"""
if self.current_pitch > 0:
pyautogui.moveRel(0, -self.current_pitch, duration=0.1)
self.current_pitch = 0
print("Голова возвращена в исходное положение")
def calculate_jump(self, block_pos):
"""Рассчитывает тип прыжка в зависимости от высоты блока"""
screen_center_y = pyautogui.size()[1] // 2
block_y = block_pos[1]
# Определяем высоту блока относительно центра экрана
height_diff = screen_center_y - block_y
if height_diff > 80: # Блок высоко
return "high_jump"
elif height_diff > 30: # Блок на средней высоте
return "medium_jump"
else: # Блок близко или ниже
return "low_jump"
def perform_jump(self, jump_type):
"""Выполняет прыжок с движением вперед"""
print(f"Прыжок типа: {jump_type}")
# Начинаем движение вперед
keyboard.press('w')
time.sleep(0.05)
if jump_type == "high_jump":
# Прыжок с удержанием для большей высоты
keyboard.press('space')
time.sleep(0.15) # Держим прыжок дольше для высоты
keyboard.release('space')
time.sleep(0.1)
# Дополнительный прыжок если нужно (для двойных прыжков)
keyboard.press('space')
time.sleep(0.1)
keyboard.release('space')
elif jump_type == "medium_jump":
# Обычный прыжок
keyboard.press('space')
time.sleep(0.1)
keyboard.release('space')
else: # low_jump
# Быстрый прыжок
keyboard.press('space')
time.sleep(0.05)
keyboard.release('space')
# Продолжаем движение вперед после прыжка
time.sleep(0.15)
keyboard.release('w')
time.sleep(0.1)
def parkour_cycle(self):
"""Основной цикл паркура"""
print("Запуск цикла паркура...")
while self.running:
try:
# Проверяем наличие блока перед собой
found, block_pos = self.find_block()
if found:
print("Блок найден перед игроком!")
self.block_found = True
# Рассчитываем и выполняем прыжок
jump_type = self.calculate_jump(block_pos)
self.perform_jump(jump_type)
# Пауза после прыжка
time.sleep(0.2)
self.block_found = False
else:
print("Блок не найден, начинаю сканирование...")
# Сначала пробуем найти блок, вращая голову
if not self.rotate_head_horizontal():
# Если не нашли после полного оборота, опускаем голову
self.look_down()
# Если голова слишком низко, возвращаем в исходное положение
if self.current_pitch >= self.min_pitch:
self.reset_head_position()
else:
# Если нашли блок при сканировании, выполняем прыжок
found_again, block_pos = self.find_block()
if found_again:
jump_type = self.calculate_jump(block_pos)
self.perform_jump(jump_type)
self.reset_head_position()
time.sleep(0.05)
except Exception as e:
print(f"Ошибка в цикле: {e}")
time.sleep(0.1)
def start(self):
"""Запуск бота"""
self.running = True
print("=" * 50)
print("БОТ ПАРКУРА ЗАПУЩЕН!")
print("=" * 50)
print("Управление:")
print(" F8 - Пауза/Продолжение")
print(" F9 - Полная остановка")
print("=" * 50)
# Запускаем основной цикл в отдельном потоке
bot_thread = threading.Thread(target=self.parkour_cycle)
bot_thread.daemon = True
bot_thread.start()
# Ожидаем команды пользователя
while True:
if keyboard.is_pressed('F9'):
self.running = False
print("\nБот остановлен!")
break
elif keyboard.is_pressed('F8'):
self.running = not self.running
state = "ПРОДОЛЖЕН" if self.running else "ПРИОСТАНОВЛЕН"
print(f"\nСтатус: {state}")
time.sleep(0.5) # Защита от двойного нажатия
time.sleep(0.1)
# Дополнительный класс с калибровкой
class CalibratedParkourBot(ParkourBot):
def __init__(self):
super().__init__()
self.calibrate_sensitivity()
def calibrate_sensitivity(self):
"""Калибровка чувствительности мыши"""
print("Калибровка чувствительности...")
print("Убедитесь, что чувствительность мыши в игре минимальная!")
# Тестовое движение мыши
pyautogui.moveRel(100, 0, duration=0.5)
time.sleep(0.5)
pyautogui.moveRel(-100, 0, duration=0.5)
print("Калибровка завершена!")
# Основная программа
if __name__ == "__main__":
print("\n" + "=" * 50)
print("БОТ ДЛЯ ПАРКУРА В MINECRAFT")
print("=" * 50)
print("\nИНСТРУКЦИЯ:")
print("1. Встаньте прямо перед началом паркура")
print("2. Убедитесь, что окно Minecraft активно")
print("3. Чувствительность мыши в игре = МИНИМУМ")
print("4. FOV (угол обзора) = 90")
print("\nЦВЕТА БЛОКОВ ДЛЯ ПОИСКА:")
print(" • Темно-красный: RGB(143, 58, 47)")
print(" • Кирпичный: RGB(178, 74, 58)")
print(" • И близкие оттенки")
print("\n" + "=" * 50)
# Создаем и запускаем бота
bot = ParkourBot()
# Даем время переключиться на окно Minecraft
print("\nЗапуск через 3 секунды... Переключитесь на Minecraft!")
for i in range(3, 0, -1):
print(f"{i}...")
time.sleep(1)
print("СТАРТ!")
bot.start()