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


const canvas = document.getElementById("pongCanvas");
const ctx = canvas.getContext("2d");

// Ракетка игрока (слева)
const player = {
    x: 10,
    y: canvas.height / 2 - 50,
    width: 10,
    height: 100,
    score: 0,
    speed: 8
};

// Ракетка бота (справа)
const ai = {
    x: canvas.width - 20,
    y: canvas.height / 2 - 50,
    width: 10,
    height: 100,
    score: 0,
    speed: 4.5 // Сделай больше (например 6), если бот слишком тупой
};

// Мяч
const ball = {
    x: canvas.width / 2,
    y: canvas.height / 2,
    radius: 7,
    speedX: 5,
    speedY: 5,
    baseSpeed: 5
};

// Отслеживание нажатых клавиш
const keys = {};
window.addEventListener("keydown", e => keys[e.key] = true);
window.addEventListener("keyup", e => keys[e.key] = false);

// Сброс мяча в центр после гола
function resetBall() {
    ball.x = canvas.width / 2;
    ball.y = canvas.height / 2;
    // Меняем направление полета и сбрасываем скорость к начальной
    ball.speedX = -ball.speedX > 0 ? ball.baseSpeed : -ball.baseSpeed;
    ball.speedY = (Math.random() > 0.5 ? 1 : -1) * ball.baseSpeed;
}

// Проверка столкновения мяча с ракеткой
function collision(b, p) {
    return b.x + b.radius > p.x && 
           b.x - b.radius < p.x + p.width && 
           b.y + b.radius > p.y && 
           b.y - b.radius < p.y + p.height;
}

// Обновление физики и позиций объектов
function update() {
    // 1. Управление игроком (Стрелки Вверх / Вниз или W / S)
    if ((keys["ArrowUp"] || keys["w"] || keys["W"]) && player.y > 0) {
        player.y -= player.speed;
    }
    if ((keys["ArrowDown"] || keys["s"] || keys["S"]) && player.y < canvas.height - player.height) {
        player.y += player.speed;
    }

    // 2. Простой ИИ для бота (он плавно двигается за мячом)
    let aiTargetY = ball.y - ai.height / 2;
    ai.y += (aiTargetY - ai.y) * 0.12; // Коэффициент плавной погони
    
    // Ограничиваем бота рамками экрана
    if (ai.y < 0) ai.y = 0;
    if (ai.y > canvas.height - ai.height) ai.y = canvas.height - ai.height;

    // 3. Движение мяча
    ball.x += ball.speedX;
    ball.y += ball.speedY;

    // Отскок от верхней и нижней стен
    if (ball.y - ball.radius < 0 || ball.y + ball.radius > canvas.height) {
        ball.speedY = -ball.speedY;
    }

    // Определяем, с чьей стороны мяч, чтобы проверить столкновение
    let paddle = (ball.x < canvas.width / 2) ? player : ai;

    if (collision(ball, paddle)) {
        // Меняем направление по X
        ball.speedX = -ball.speedX;
        
        // Немного ускоряем мяч при каждом ударе для азарта
        ball.speedX += ball.speedX > 0 ? 0.3 : -0.3;
        ball.speedY += ball.speedY > 0 ? 0.3 : -0.3;
    }

    // 4. Подсчет очков (выход за левую/правую границу)
    if (ball.x - ball.radius < 0) {
        ai.score++;
        resetBall();
    } else if (ball.x + ball.radius > canvas.width) {
        player.score++;
        resetBall();
    }
}

// Отрисовка графики
function draw() {
    // Чистим экран черным цветом
    ctx.fillStyle = "#000";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Рисуем сетку посередине поля
    ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
    ctx.setLineDash([10, 10]);
    ctx.beginPath();
    ctx.moveTo(canvas.width / 2, 0);
    ctx.lineTo(canvas.width / 2, canvas.height);
    ctx.stroke();
    ctx.setLineDash([]); // сброс пунктира

    // Рисуем счет игрока и бота
    ctx.fillStyle = "#fff";
    ctx.font = "45px Arial";
    ctx.fillText(player.score, canvas.width / 4, 60);
    ctx.fillText(ai.score, 3 * canvas.width / 4, 60);

    // Рисуем ракетки
    ctx.fillRect(player.x, player.y, player.width, player.height);
    ctx.fillRect(ai.x, ai.y, ai.width, ai.height);

    // Рисуем мяч кругом
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
    ctx.fill();
}

// Главный игровой цикл
function gameLoop() {
    update();
    draw();
    requestAnimationFrame(gameLoop);
}

// Запуск
gameLoop();