188 lines
6.3 KiB
Python
188 lines
6.3 KiB
Python
import pygame
|
||
import sys
|
||
import random
|
||
import math
|
||
|
||
# Инициализация Pygame
|
||
pygame.init()
|
||
|
||
# Константы
|
||
WIDTH, HEIGHT = 1920, 1080
|
||
PADDLE_WIDTH, PADDLE_HEIGHT = 30, 200
|
||
BALL_SIZE = 30
|
||
WHITE = (255, 255, 255)
|
||
BLACK = (0, 0, 0)
|
||
GREEN = (50, 168, 82)
|
||
LIGHT_GREEN = (100, 200, 100)
|
||
FPS = 120 # Увеличили FPS для плавности на высоких скоростях
|
||
|
||
# Создание окна
|
||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||
pygame.display.set_caption("Pong - ХЕРАЧЬ Edition v2.0")
|
||
clock = pygame.time.Clock()
|
||
|
||
# Загрузка шрифтов
|
||
try:
|
||
pixel_font = pygame.font.Font("PressStart2P-Regular.ttf", 120)
|
||
except:
|
||
pixel_font = pygame.font.SysFont('arial', 120)
|
||
|
||
# Игровые объекты
|
||
player_paddle = pygame.Rect(100, HEIGHT // 2 - PADDLE_HEIGHT // 2, PADDLE_WIDTH, PADDLE_HEIGHT)
|
||
ai_paddle = pygame.Rect(WIDTH - 100 - PADDLE_WIDTH, HEIGHT // 2 - PADDLE_HEIGHT // 2, PADDLE_WIDTH, PADDLE_HEIGHT)
|
||
ball = pygame.Rect(WIDTH // 2 - BALL_SIZE // 2, HEIGHT // 2 - BALL_SIZE // 2, BALL_SIZE, BALL_SIZE)
|
||
|
||
# Физика мяча
|
||
base_speed = 3
|
||
max_speed = 35 # Увеличили максимальную скорость
|
||
speed_increase = 0.7 # Увеличили ускорение после удара
|
||
ball_speed = base_speed
|
||
ball_dx = ball_speed * random.choice((1, -1))
|
||
ball_dy = ball_speed * random.choice((1, -1))
|
||
|
||
# Скорости
|
||
player_speed = 0
|
||
ai_speed = 0
|
||
|
||
# Счет
|
||
player_score = 0
|
||
ai_score = 0
|
||
font = pygame.font.Font(None, 72)
|
||
|
||
def draw_field():
|
||
"""Рисует поле с разметкой"""
|
||
screen.fill(GREEN)
|
||
|
||
# Полупрозрачная надпись
|
||
text_surface = pixel_font.render("ХЕРАЧЬ!", True, LIGHT_GREEN)
|
||
text_surface.set_alpha(30)
|
||
screen.blit(text_surface, (WIDTH//2 - text_surface.get_width()//2, HEIGHT//2 - text_surface.get_height()//2))
|
||
|
||
# Разметка
|
||
for y in range(0, HEIGHT, 40):
|
||
pygame.draw.rect(screen, WHITE, (WIDTH // 2 - 5, y, 10, 20))
|
||
pygame.draw.rect(screen, WHITE, (0, 0, WIDTH, HEIGHT), 10)
|
||
|
||
def reset_ball():
|
||
"""Сбрасывает мяч в центр"""
|
||
global ball_speed, ball_dx, ball_dy
|
||
ball.center = (WIDTH // 2, HEIGHT // 2)
|
||
ball_speed = base_speed
|
||
angle = math.radians(random.uniform(30, 60))
|
||
direction = random.choice((-1, 1))
|
||
ball_dx = direction * ball_speed * math.cos(angle)
|
||
ball_dy = ball_speed * math.sin(angle) * random.choice((-1, 1))
|
||
|
||
def handle_collision():
|
||
"""Обрабатывает все столкновения"""
|
||
global ball_dx, ball_dy, ball_speed
|
||
|
||
# Жесткие границы (мяч не может вылететь)
|
||
if ball.top < 0:
|
||
ball.top = 0
|
||
ball_dy = abs(ball_dy) * 0.95 # Небольшая потеря энергии
|
||
if ball.bottom > HEIGHT:
|
||
ball.bottom = HEIGHT
|
||
ball_dy = -abs(ball_dy) * 0.95
|
||
|
||
# Обработка ударов о ракетки с более сильным ускорением
|
||
if ball.colliderect(player_paddle) and ball_dx < 0:
|
||
# Сильное ускорение + случайный угол
|
||
relative_intersect = (player_paddle.centery - ball.centery) / (PADDLE_HEIGHT / 2)
|
||
ball_dx = abs(ball_dx) * 1.25 # Увеличили ускорение
|
||
ball_dy = -relative_intersect * ball_speed * 2
|
||
# Добавляем случайности
|
||
ball_dx += random.uniform(-0.5, 0.5)
|
||
ball_dy += random.uniform(-1, 1)
|
||
|
||
elif ball.colliderect(ai_paddle) and ball_dx > 0:
|
||
relative_intersect = (ai_paddle.centery - ball.centery) / (PADDLE_HEIGHT / 2)
|
||
ball_dx = -abs(ball_dx) * 1.25
|
||
ball_dy = -relative_intersect * ball_speed * 2
|
||
ball_dx += random.uniform(-0.5, 0.5)
|
||
ball_dy += random.uniform(-1, 1)
|
||
|
||
# Нормализация скорости
|
||
speed = math.sqrt(ball_dx**2 + ball_dy**2)
|
||
if speed > max_speed:
|
||
ball_dx = (ball_dx / speed) * max_speed
|
||
ball_dy = (ball_dy / speed) * max_speed
|
||
ball_speed = speed
|
||
|
||
def ai_movement():
|
||
"""Упрощенный ИИ с ошибками"""
|
||
global ai_speed
|
||
|
||
# Простое следование за мячом с задержкой и ошибками
|
||
target_y = ball.centery + random.uniform(-50, 50) # Добавляем ошибку
|
||
|
||
# Замедляем ИИ на высоких скоростях
|
||
reaction_speed = max(3, 8 - ball_speed * 0.2)
|
||
|
||
if ai_paddle.centery < target_y:
|
||
ai_speed = min(reaction_speed, target_y - ai_paddle.centery)
|
||
else:
|
||
ai_speed = max(-reaction_speed, target_y - ai_paddle.centery)
|
||
|
||
ai_paddle.y += ai_speed
|
||
|
||
# Границы
|
||
if ai_paddle.top < 0:
|
||
ai_paddle.top = 0
|
||
if ai_paddle.bottom > HEIGHT:
|
||
ai_paddle.bottom = HEIGHT
|
||
|
||
# Основной цикл
|
||
while True:
|
||
for event in pygame.event.get():
|
||
if event.type == pygame.QUIT:
|
||
pygame.quit()
|
||
sys.exit()
|
||
|
||
if event.type == pygame.KEYDOWN:
|
||
if event.key == pygame.K_DOWN:
|
||
player_speed = 15
|
||
if event.key == pygame.K_UP:
|
||
player_speed = -15
|
||
if event.key == pygame.K_ESCAPE:
|
||
pygame.quit()
|
||
sys.exit()
|
||
if event.type == pygame.KEYUP:
|
||
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
|
||
player_speed = 0
|
||
|
||
# Движение
|
||
player_paddle.y += player_speed
|
||
if player_paddle.top < 0:
|
||
player_paddle.top = 0
|
||
if player_paddle.bottom > HEIGHT:
|
||
player_paddle.bottom = HEIGHT
|
||
|
||
ai_movement()
|
||
|
||
# Физика мяча
|
||
ball.x += ball_dx
|
||
ball.y += ball_dy
|
||
handle_collision()
|
||
|
||
# Голы
|
||
if ball.left <= 0:
|
||
ai_score += 1
|
||
reset_ball()
|
||
if ball.right >= WIDTH:
|
||
player_score += 1
|
||
base_speed = min(15, base_speed + speed_increase)
|
||
reset_ball()
|
||
|
||
# Отрисовка
|
||
draw_field()
|
||
pygame.draw.rect(screen, WHITE, player_paddle, border_radius=10)
|
||
pygame.draw.rect(screen, WHITE, ai_paddle, border_radius=10)
|
||
pygame.draw.ellipse(screen, WHITE, ball)
|
||
|
||
# Счет
|
||
screen.blit(font.render(f"{player_score}", True, WHITE), (WIDTH//4, 50))
|
||
screen.blit(font.render(f"{ai_score}", True, WHITE), (3*WIDTH//4 - 50, 50))
|
||
|
||
pygame.display.flip()
|
||
clock.tick(FPS) |