Загрузка данных
import pygame
import random
import math
import sys
# Инициализация
pygame.init()
# Настройки экрана
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Гонка яблок — 6 игроков")
clock = pygame.time.Clock()
# Цвета
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
APPLE_RED = (220, 30, 30)
GREEN_LEAF = (0, 180, 0)
# Цвета игроков (русские названия)
PLAYER_COLORS = {
"Зелёный": (0, 200, 0),
"Синий": (50, 100, 255),
"Красный": (220, 50, 50),
"Жёлтый": (240, 220, 30),
"Фиолетовый": (170, 60, 220),
"Оранжевый": (255, 140, 0),
}
WIN_SCORE = 500
APPLE_COUNT = 25
APPLE_RADIUS = 8
PLAYER_RADIUS = 10
STEP_LENGTH = 3.0
TURN_ANGLE = 6.0
# Игровая область (с учётом строки счёта сверху)
FIELD_LEFT = 10
FIELD_TOP = 70
FIELD_RIGHT = WIDTH - 10
FIELD_BOTTOM = HEIGHT - 10
# Шрифты
score_font = pygame.font.SysFont("Arial", 16, bold=True)
win_font = pygame.font.SysFont("Arial", 48, bold=True)
scores = {name: 0 for name in PLAYER_COLORS}
class Player:
def __init__(self, name, color, x, y):
self.name = name
self.color = color
self.x = float(x)
self.y = float(y)
# Начальное направление — к центру
cx, cy = WIDTH / 2, (FIELD_TOP + FIELD_BOTTOM) / 2
self.angle = math.degrees(math.atan2(cy - y, cx - x))
self.stuck_frames = 0
def pos(self):
return self.x, self.y
def distance_to(self, other_x, other_y):
return math.hypot(self.x - other_x, self.y - other_y)
class Apple:
def __init__(self, x, y):
self.x = x
self.y = y
# Создание игроков
start_positions = [
(FIELD_LEFT + 100, (FIELD_TOP + FIELD_BOTTOM) / 2),
(FIELD_RIGHT - 100, (FIELD_TOP + FIELD_BOTTOM) / 2),
(WIDTH / 2, FIELD_TOP + 100),
(WIDTH / 2, FIELD_BOTTOM - 100),
(FIELD_LEFT + 150, FIELD_TOP + 150),
(FIELD_RIGHT - 150, FIELD_BOTTOM - 150),
]
players = []
for i, (name, color) in enumerate(PLAYER_COLORS.items()):
x, y = start_positions[i]
players.append(Player(name, color, x, y))
def create_apple():
for _ in range(100):
x = random.randint(FIELD_LEFT + 20, FIELD_RIGHT - 20)
y = random.randint(FIELD_TOP + 20, FIELD_BOTTOM - 20)
too_close = False
for p in players:
if p.distance_to(x, y) < 60:
too_close = True
break
if not too_close:
return Apple(x, y)
return Apple(
random.randint(FIELD_LEFT + 20, FIELD_RIGHT - 20),
random.randint(FIELD_TOP + 20, FIELD_BOTTOM - 20),
)
apples = [create_apple() for _ in range(APPLE_COUNT)]
def find_closest_apple(player):
min_dist = float("inf")
closest = None
for apple in apples:
dist = player.distance_to(apple.x, apple.y)
if dist < min_dist:
min_dist = dist
closest = apple
return closest, min_dist
def get_turn_direction(player, target):
dx = target.x - player.x
dy = target.y - player.y
target_angle = math.degrees(math.atan2(dy, dx))
diff = target_angle - player.angle
while diff > 180:
diff -= 360
while diff < -180:
diff += 360
if abs(diff) < 5:
return 0
return 1 if diff > 0 else -1
def check_wall(player):
return (
player.x < FIELD_LEFT + PLAYER_RADIUS
or player.x > FIELD_RIGHT - PLAYER_RADIUS
or player.y < FIELD_TOP + PLAYER_RADIUS
or player.y > FIELD_BOTTOM - PLAYER_RADIUS
)
def move_player(player):
closest, distance = find_closest_apple(player)
if closest is None:
return
turn = get_turn_direction(player, closest)
if turn == 1:
player.angle += TURN_ANGLE
elif turn == -1:
player.angle -= TURN_ANGLE
rad = math.radians(player.angle)
player.x += math.cos(rad) * STEP_LENGTH
player.y += math.sin(rad) * STEP_LENGTH
# Антизацикливание
player.stuck_frames += 1
if player.stuck_frames > 100 and distance < 50:
player.angle += 30
player.stuck_frames = 0
# Столкновение со стеной — отскок
if check_wall(player):
player.x -= math.cos(rad) * STEP_LENGTH * 2
player.y -= math.sin(rad) * STEP_LENGTH * 2
player.angle += 60
# Проверка съедания яблока
for apple in apples[:]:
if player.distance_to(apple.x, apple.y) < PLAYER_RADIUS + APPLE_RADIUS:
apples.remove(apple)
scores[player.name] += 1
apples.append(create_apple())
break
def draw_arrow(surface, player):
"""Рисует стрелку (треугольник) в направлении движения."""
rad = math.radians(player.angle)
size = 12
tip = (player.x + math.cos(rad) * size,
player.y + math.sin(rad) * size)
left = (player.x + math.cos(rad + 2.5) * size,
player.y + math.sin(rad + 2.5) * size)
right = (player.x + math.cos(rad - 2.5) * size,
player.y + math.sin(rad - 2.5) * size)
pygame.draw.polygon(surface, player.color, [tip, left, right])
pygame.draw.polygon(surface, WHITE, [tip, left, right], 1)
def draw_apple(surface, apple):
pygame.draw.circle(surface, APPLE_RED,
(int(apple.x), int(apple.y)), APPLE_RADIUS)
pygame.draw.circle(surface, GREEN_LEAF,
(int(apple.x) + 2, int(apple.y) - APPLE_RADIUS),
3)
def draw_score(surface):
parts = [f"{name}: {scores[name]}" for name in PLAYER_COLORS]
text = " | ".join(parts) + f" | До победы: {WIN_SCORE}"
surf = score_font.render(text, True, WHITE)
surface.blit(surf, (10, 10))
def draw_field_border(surface):
pygame.draw.rect(
surface, (80, 80, 80),
(FIELD_LEFT, FIELD_TOP,
FIELD_RIGHT - FIELD_LEFT, FIELD_BOTTOM - FIELD_TOP),
2,
)
# Основной цикл
running = True
winner = None
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if winner is None:
for p in players:
move_player(p)
# Проверка победы
for name in PLAYER_COLORS:
if scores[name] >= WIN_SCORE:
winner = name
break
# Отрисовка
screen.fill(BLACK)
draw_field_border(screen)
for apple in apples:
draw_apple(screen, apple)
for p in players:
draw_arrow(screen, p)
draw_score(screen)
if winner is not None:
text = win_font.render(f"{winner.upper()} ПОБЕДИЛ!", True,
PLAYER_COLORS[winner])
rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2))
# Полупрозрачный фон
overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 160))
screen.blit(overlay, (0, 0))
screen.blit(text, rect)
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()