Загрузка данных


import pygame
from random import randint
import random
import math
import sys

pygame.init()
pygame.mixer.init(frequency=22050, size=-16, channels=1)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

def get_random_color():
    return (random.randint(70, 255), random.randint(70, 255), random.randint(70, 255))

def generate_sound(freq, duration, volume=0.3):
    sample_rate = 22050
    n_samples = int(sample_rate * duration)
    samples = []
    for i in range(n_samples):
        t = i / sample_rate
        value = volume * 32767 * math.sin(2 * math.pi * freq * t)
        samples.append(int(value))
    sound = pygame.sndarray.make_sound(pygame.sndarray.array(pygame.sndarray.samples(samples, 1)))
    return sound

bounce_sound = generate_sound(880, 0.05)
score_sound = generate_sound(440, 0.2)

class Paddle(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.width = width
        self.height = height
        self.image = pygame.Surface([width, height])
        self.image.fill(BLACK)
        self.image.set_colorkey(BLACK)
        pygame.draw.rect(self.image, color, [0, 0, width, height])
        self.rect = self.image.get_rect()
        self.color = color

    def moveUp(self, pixels):
        self.rect.y -= pixels
        if self.rect.y < 0:
            self.rect.y = 0

    def moveDown(self, pixels):
        self.rect.y += pixels
        if self.rect.y > 400:
            self.rect.y = 400

    def change_color(self, new_color):
        self.color = new_color
        self.image.fill(BLACK)
        pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height])

class Ball(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.width = width
        self.height = height
        self.image = pygame.Surface([width, height])
        self.image.fill(BLACK)
        self.image.set_colorkey(BLACK)
        pygame.draw.rect(self.image, color, [0, 0, width, height])
        self.reset_speed()
        self.rect = self.image.get_rect()
        self.color = color

    def reset_speed(self):
        self.velocity = [randint(4, 8), randint(-8, 8)]
        while self.velocity[1] == 0:
            self.velocity[1] = randint(-8, 8)
        self.base_speed = abs(self.velocity[0])
        self.max_speed = 15

    def update(self):
        self.rect.x += self.velocity[0]
        self.rect.y += self.velocity[1]

    def bounce(self):
        self.velocity[0] = -self.velocity[0]
        self.velocity[1] = randint(-8, 8)
        self.velocity[0] = self.base_speed * (1 if self.velocity[0] > 0 else -1)
        if self.base_speed < self.max_speed:
            self.base_speed += 0.2
            self.velocity[0] = self.base_speed * (1 if self.velocity[0] > 0 else -1)

    def change_color(self, new_color):
        self.color = new_color
        self.image.fill(BLACK)
        pygame.draw.rect(self.image, self.color, [0, 0, self.width, self.height])

size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Ping Pong")
clock = pygame.time.Clock()

paddleA = Paddle(WHITE, 10, 100)
paddleA.rect.x = 20
paddleA.rect.y = 200

paddleB = Paddle(WHITE, 10, 100)
paddleB.rect.x = 670
paddleB.rect.y = 200

ball = Ball(WHITE, 10, 10)
ball.rect.x = 345
ball.rect.y = 195

all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(paddleA, paddleB, ball)

scoreA = 0
scoreB = 0
game_state = "MENU"
game_mode = 2
selected_menu_option = 0
paused = False

def reset_game():
    global scoreA, scoreB
    scoreA = 0
    scoreB = 0
    paddleA.rect.y = 200
    paddleB.rect.y = 200
    paddleA.change_color(WHITE)
    paddleB.change_color(WHITE)
    ball.rect.x = 345
    ball.rect.y = 195
    ball.reset_speed()
    ball.change_color(WHITE)

def draw_text(text, font, color, x, y):
    surface = font.render(text, True, color)
    screen.blit(surface, (x - surface.get_width() // 2, y))

while True:
    if game_state == "MENU":
        screen.fill(BLACK)
        font_title = pygame.font.Font(None, 64)
        font_menu = pygame.font.Font(None, 40)
        draw_text("ПИНГ ПОНГ", font_title, WHITE, 350, 80)
        options = ["1 Игрок", "2 Игрока", "Выход"]
        for i, opt in enumerate(options):
            color = (255, 255, 0) if i == selected_menu_option else WHITE
            prefix = "> " if i == selected_menu_option else "  "
            draw_text(prefix + opt, font_menu, color, 350, 220 + i * 60)
        pygame.display.flip()
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif e.type == pygame.KEYDOWN:
                if e.key == pygame.K_UP:
                    selected_menu_option = (selected_menu_option - 1) % 3
                elif e.key == pygame.K_DOWN:
                    selected_menu_option = (selected_menu_option + 1) % 3
                elif e.key == pygame.K_RETURN:
                    if selected_menu_option == 0:
                        game_mode = 1
                        game_state = "GAME"
                        reset_game()
                    elif selected_menu_option == 1:
                        game_mode = 2
                        game_state = "GAME"
                        reset_game()
                    else:
                        pygame.quit()
                        sys.exit()
        clock.tick(60)
        continue

    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif e.type == pygame.KEYDOWN:
            if e.key == pygame.K_ESCAPE:
                game_state = "MENU"
            elif e.key == pygame.K_p:
                paused = not paused
            elif e.key == pygame.K_r:
                reset_game()

    if not paused:
        keys = pygame.key.get_pressed()
        if keys[pygame.K_w]:
            paddleA.moveUp(6)
        if keys[pygame.K_s]:
            paddleA.moveDown(6)
        if game_mode == 2:
            if keys[pygame.K_UP]:
                paddleB.moveUp(6)
            if keys[pygame.K_DOWN]:
                paddleB.moveDown(6)
        else:
            # Улучшенный AI: предугадывает направление мяча, но с задержкой
            target_y = ball.rect.y + ball.velocity[1] * 6
            target_y = max(0, min(400, target_y - 50))
            if paddleB.rect.centery < target_y - 10:
                paddleB.moveDown(5)
            elif paddleB.rect.centery > target_y + 10:
                paddleB.moveUp(5)

        all_sprites_list.update()

        # Отскок от стен (верх/низ)
        if ball.rect.y >= 490 and ball.velocity[1] > 0:
            ball.velocity[1] = -ball.velocity[1]
            ball.rect.y = 490
            ball.change_color(get_random_color())
            bounce_sound.play()
        elif ball.rect.y <= 0 and ball.velocity[1] < 0:
            ball.velocity[1] = -ball.velocity[1]
            ball.rect.y = 0
            ball.change_color(get_random_color())
            bounce_sound.play()

        # Очки за выход за левый/правый край
        if ball.rect.x >= 690:
            scoreA += 1
            ball.reset_speed()
            ball.rect.x = 345
            ball.rect.y = 195
            ball.change_color(get_random_color())
            score_sound.play()
        elif ball.rect.x <= 0:
            scoreB += 1
            ball.reset_speed()
            ball.rect.x = 345
            ball.rect.y = 195
            ball.change_color(get_random_color())
            score_sound.play()

        # Столкновение с ракетками
        if pygame.sprite.collide_mask(ball, paddleA) and ball.velocity[0] < 0:
            ball.bounce()
            ball.rect.left = paddleA.rect.right
            ball.change_color(get_random_color())
            paddleA.change_color(get_random_color())
            bounce_sound.play()
        if pygame.sprite.collide_mask(ball, paddleB) and ball.velocity[0] > 0:
            ball.bounce()
            ball.rect.right = paddleB.rect.left
            ball.change_color(get_random_color())
            paddleB.change_color(get_random_color())
            bounce_sound.play()

    # Отрисовка
    screen.fill(BLACK)
    pygame.draw.line(screen, WHITE, (349, 0), (349, 500), 5)
    all_sprites_list.draw(screen)
    font_score = pygame.font.Font(None, 74)
    draw_text(str(scoreA), font_score, WHITE, 250, 10)
    draw_text(str(scoreB), font_score, WHITE, 450, 10)
    if paused:
        font_pause = pygame.font.Font(None, 48)
        draw_text("ПАУЗА (P - продолжить)", font_pause, WHITE, 350, 250)
    pygame.display.flip()
    clock.tick(60)