Найти в Дзене
Журнал «Код»

Пинг-понг против компьютера на JavaScript

Оглавление

Лёгкая версия

В одном из наших проектов мы делали игру в пинг-понг на JavaScript, где нужно было играть вдвоём. Один игрок управлял одной ракеткой, второй — другой ракеткой, а мячик летал по написанным нами законам физики.

Следующий шаг: научим компьютер играть против человека. Сегодня реализуем самый простой вариант.

Что нам понадобится

Для работы нужен только исходный код старой игры и немного новой логики. Скопируйте код из выпадайки в новый документ, сохраните как HTML и откройте в браузере.

Исходный код

Новая логика игры

Для игры с компьютером нужно сделать так, чтобы одна из платформ двигалась сама — пусть это будет левая платформа. Так как у нас лёгкая версия игры, то движение будет очень простым: платформа будет двигаться от края до края без остановок. Если повезёт — отобьёт мяч, если нет — значит, не повезло.

Чтобы у компьютера были хоть какие-то шансы на выигрыш, сделаем его платформу в два раза больше, чем наша — так ему будет проще отбивать мяч.

Последнее, что можно сделать, — замедлить мяч, чтобы игрок успевал его постоянно отбивать.

Начнём с мяча.

Замедляем мяч

Это самое простое изменение — достаточно поменять одну цифру в коде, как игра становится более понятной и управляемой:

// Скорость мяча
var ballSpeed = 4;

Если 4 для вас всё равно слишком быстро — поставьте 3, а если хотите занять детей — то 2.

Увеличиваем левую платформу

Находим код, который отвечает за левую платформу. За размер отвечает параметр высоты. Просто умножаем её на 2:

// Описываем левую платформу const leftPaddle = {   // Ставим её по центру   x: grid * 2,   y: canvas.height / 2 - paddleHeight / 2,   // Ширина — одна клетка   width: grid,   // Удваиваем размер платформы  height: paddleHeight * 2,   // Платформа на старте никуда не движется   dy: 0};

Пока ничего никуда не движется, но сейчас мы это исправим.

Запускаем платформу

Для этого нам нужно добавить одну строчку сразу после предыдущего раздела. Она задаёт платформе начальную скорость, которая у нас прописана в константе paddleSpeed:

leftPaddle.dy = paddleSpeed;

Но сразу после запуска игры платформа доезжает до края платформы, немного проваливается вниз, несмотря на свой размер, и останавливается. Нужно это исправить:

-2

Делаем отскок от границ

Находим блок, который проверяет, вышли платформы за границы или нет. Правую пока не трогаем, нас интересует только левая, за которую играет компьютер. 

Наша задача — поменять условия так, чтобы они заставляли платформу саму двигаться вверх и вниз:

 // Если левая платформа пытается вылезти за игровое поле вниз,
      if (leftPaddle.y < grid) {
          // то оставляем её на месте
          leftPaddle.y = grid;
leftPaddle.dy = paddleSpeed;
      }
      // Проверяем то же самое сверху
      else if (leftPaddle.y > maxPaddleY) {
          leftPaddle.y = maxPaddleY;
leftPaddle.dy = -paddleSpeed;
      }

Мы добавили смену скорости левой платформы при касании границ. Посмотрим, как это сработало: платформа движется как нам нужно, но полностью игнорирует свой новый размер, когда уезжает вниз.

-3

Исправляем баг с размером

Штука в том, что код не знает, что у левой платформы изменилась длина, несмотря на то, что мы это явно прописали в самом начале. Всё дело в том, что этот блок сравнения, который мы только что правили, оперирует другой константой: maxPaddleY. В исходной версии игры платформы были одинакового размера, поэтому всё было в порядке, но теперь у нас две разных длины.

Чтобы исправить этот баг с размером, нам нужно будет завести две отдельные константы — с длиной левой и правой платформ по отдельности. Немного модифицируем правую и добавим левую:

    const LeftmaxPaddleY = canvas.height - grid - paddleHeight * 2;
    const RightmaxPaddleY = canvas.height - grid - paddleHeight;

Теперь видно, что левая платформа в 2 раза больше правой, и координаты крайней точки тоже изменились. Теперь нам нужно просмотреть весь код и найти все места, где используется старая константа maxPaddleY и заменить её на новую, учитывая сторону платформы.

На наше счастье, это нужно сделать только в блоке проверки границ при движении. Сразу исправим:

// Если левая платформа пытается вылезти за игровое поле вниз,
  if (leftPaddle.y < grid) {
        // то оставляем её на месте
    leftPaddle.y = grid;
    leftPaddle.dy = paddleSpeed;
  }
  // Проверяем то же самое сверху
  else if (leftPaddle.y >
LeftmaxPaddleY) {
    leftPaddle.y =
LeftmaxPaddleY;
    leftPaddle.dy = -paddleSpeed;
  }
  // Если правая платформа пытается вылезти за игровое поле вниз,
  if (rightPaddle.y < grid) {
 // то оставляем её на месте
    rightPaddle.y = grid;
  }
  // Проверяем то же самое сверху
  else if (rightPaddle.y >
RightmaxPaddleY) {
    rightPaddle.y =
RightmaxPaddleY;
  }

Теперь всё как нужно. Можно играть против роботизированной ракетки и, наверное, довольно часто выигрывать. 

Готовый код

Что дальше

В следующей серии мы сделаем непобедимый пинг-понг: платформа всегда будет двигаться за мячом, чтобы отбить его. Вам останется только продержаться как можно дольше. 

Но это потом. А сейчас — обыграйте глупую платформу.