В этой статье я покажу вам, как создать классическую игру Pong для двух игроков с помощью JavaScript, используя библиотеку 2D-игр под названием qKit.

Но что такое qKit?

qKit - это библиотека JavaScript, которую я создал, чтобы помочь мне легко и быстро создавать 2D-видеоигры.

Также стоит отметить, что он работает только с квадратными формами (квадратами и прямоугольниками). Вы также можете проверять наличие коллизий, обнаруживать входы с клавиатуры / мыши и звуки, а также многие другие утилиты, которые делают разработку 2D-игр плавной, простой и быстрой. Не волнуйтесь, документация библиотеки охватывает большинство вещей, которые вы можете делать с ней в репозитории GitHub.

Кроме того, есть масса примеров.

История?

Из Википедии Pong - спортивная игра для настольного тенниса с простой двухмерной графикой, разработанная A tari и первоначально выпущенная в 1972 году. A rcade видеоигры и созданы Алланом Алкорном в качестве тренировочного упражнения, назначенного ему соучредителем Atari Ноланом Бушнеллом.

Что мы собираемся построить?

Игра для двух игроков с двумя пэдами (прямоугольной формы) на обоих концах экрана и объектом Pong, который будет отражаться каждый раз, когда он ударяет по одной из пэдов. Каждый раз, когда Pong выходит за пределы одной из площадок, счет будет увеличиваться для игрока (Pad) на противоположной стороне.

Кроме того, объект Pong будет отражать свое направление при ударе об пол или наземные объекты.

Начнем…

Давайте создадим каталог и вложим в него два файла:

  1. index.html
  2. pong.js

index.html будет выглядеть так

<!DOCTYPE html>
<html>
  <head>
    <title>Pong with qKit</title>
  </head>
  <body>
    <script src="https://cdn.jsdelivr.net/gh/fahadhaidari/qkit/qkit.js"></script>
    <script src="pong.js"></script>
  </body>
</html>

Нам просто нужно сослаться на библиотеку в первом теге <script>, а затем мы ссылаемся на pong.js в теге <script> скрипта.

Примечание: вы также можете загрузить файл qkit.js из репозитория и ссылаться на него локально.

Теперь давайте рассмотрим саму игру в файле pong.js, который будет содержать всю необходимую игровую логику.

Сначала нам нужно инициализировать и запустить qKit с помощью функции init.

qKit.init({
  width: 320,
  height: 480,
  color: "#EEE",
  border: { width: 10, color: "#222", radius: 10 }
});

Это простой вызов функции; установить ширину / высоту, цвет и границу для игрового экрана.

Затем давайте объявим и инициализируем некоторые константы и переменные.

const PAD_WIDTH = 10;
const PAD_HEIGHT = 60;
const PONG_SIZE = 15;
let leftPadScore = 0;
let rightPadScore = 0;

Выше мы настроили некоторые константы и переменные для объектов Pads для ширины / высоты и инициализировали оценки для обоих игроков / пэдов.

Далее мы собираемся создать и визуализировать некоторые визуальные эффекты (квадраты и текстовое представление).

  1. leftPad: панель слева (player1). Управляется мышью.
  2. rightPad: панель справа (player2). Управляется любой клавишей на клавиатуре.
  3. земля: наземный объект будет использоваться в качестве нижней границы, так что когда объект понг будет отражаться, когда он ударяется о него.
  4. крыша: объект крыши будет использоваться как нижняя граница, чтобы объект pong отражался при ударе.
  5. pong: настоящий мяч для понга (будет квадратной формы).
  6. scoresText: визуальный текст, содержащий счет обоих игроков.

Теперь давайте посмотрим, как визуализировать объекты с помощью qKit.

const leftPad = qKit.draw.quad({
  x: 0,
  y: qKit.screen.height / 2 - PAD_HEIGHT / 2,
  width: PAD_WIDTH,
  height: PAD_HEIGHT,
  color: 'orange',
  extension: { vel: { x: 0, y: 4 } }
});
const rightPad = qKit.draw.quad({
  x: qKit.screen.width - PAD_WIDTH,
  y: qKit.screen.height / 2 - 30,
  width: PAD_WIDTH,
  height: PAD_HEIGHT,
  color: '#4488FF',
  extension: { vel: { x: 0, y: 4 }}
});
const ground = qKit.draw.quad({
  x: 0,
  y: qKit.screen.height - 20,
  width:  qKit.screen.width,
  height: 20,
  color: '#111',
});
const roof = qKit.draw.quad({
  x: 0,
  y: 0,
  width:  qKit.screen.width,
  height: 20,
  color: '#111',
});
const pong = qKit.draw.quad({
  x: qKit.screen.width / 2,
  y: qKit.screen.height / 2,
  width: pong_SIZE,
  height: pong_SIZE,
  color: 'teal',
  extension: {
    dir: {
      x: [-1, 1][qKit.util.randomInt(0, 2)],
      y: [-1, 1][qKit.util.randomInt(0, 2)]
    },
    vel: {
      x: qKit.util.randomInt(3, 5),
      y: qKit.util.randomInt(3, 5)
    }
  }
});
const scoresText = qKit.draw.text({
  text: '0:0',
  x: qKit.screen.width / 2 - 30,
  y: 30,
  color: '#555',
  size: 30,
  family: 'Courier New'
});

Вкратце, чтобы нарисовать четырехугольник, мы вызываем эту функцию: qKit.draw.quad(config)

Но эта функция принимает объект с множеством свойств, как вы можете видеть, и снова документы в репозитории содержат все, что вы можете передать в этом объекте.

Кроме того, я хотел бы объяснить, что такое extension prop, который я передал этому объекту ... по умолчанию вы не можете передать настраиваемые свойства этому объекту конфигурации, и если мы это сделаем, будет выдана ошибка, поэтому, чтобы передать тот, который вам нужно обернуть в опору extension. Например, в объекте, переданном в эту функцию, нет dir или vel prop, но для этого мы использовали extension. Вот и все.

Другая вещь, которую мы создали и отрендерили, - это scoresText, и снова вы просто вызываете его так qKit.draw.text(config), затем вы передаете некоторые аргументы в объекте этой функции, чтобы настроить наш текст.

Затем мы слушаем вводы с помощью мыши и клавиатуры, чтобы управлять двумя пэдами, как это

qKit.input.click(() => {
  leftPad.extension.vel.y *= -1;
});
qKit.input.keyUp(() => {
  rightPad.extension.vel.y *= -1;
});

Итак, каждый раз, когда мы нажимаем на игровую область, левая панель будет отражать свое движение по оси Y, и каждый раз, когда мы нажимаем любую клавишу на клавиатуре, одно и то же действие будет применен к правой панели.

Затем мы создадим bounce функцию.

const bounce = function(entity) {
  const isCollideBorders =
    qKit.collision.test(entity, ground) ||
    qKit.collision.test(entity, roof);
if (isCollideBorders)
    entity.extension.vel.y *= -1;
};

Так, что происходит?

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

Но также обратите внимание, что мы использовали qKit.collision.test(quad1, quad2), чтобы проверить, столкнулись ли эти два квадрата в пределах верхней / нижней границ.

Затем мы создадим функцию resetPong, которая будет полезна, когда нам нужно сбросить объект Pong, когда он превышает одну из правой / левой границ, и увеличить счет для одного из игроков.

const resetPong = function() {
  pong.center();
  pong.extension.dir.x = [-1, 1][qKit.util.randomInt(0, 2)];
  pong.extension.dir.y = [-1, 1][qKit.util.randomInt(0, 2)];
  pong.extension.vel.x = qKit.util.randomInt(3, 5);
  pong.extension.vel.y = qKit.util.randomInt(3, 5);
};

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

Далее, это будет ядро ​​игрового процесса, это функция update, которая будет бесконечно зацикливаться, чтобы содержать логику игрового процесса.

qKit.update(() => {
  pong.x += pong.extension.vel.x * pong.extension.dir.x;
  pong.y += pong.extension.vel.y * pong.extension.dir.y;
  leftPad.y += leftPad.extension.vel.y;
  rightPad.y += rightPad.extension.vel.y;
  const isCollideWithPad =
    qKit.collision.test(pong, leftPad) ||
    qKit.collision.test(pong, rightPad);
  if (isCollideWithPad)
    pong.extension.vel.x *= -1;
  if (pong.x < leftPad.getLeft().x) {
    rightPadScore ++;
    scoresText.text = `${leftPadScore}:${rightPadScore}`;
    resetPong();
  } else
  if (pong.x > rightPad.getLeft().x) {
    leftPadScore ++;
    scoresText.text = `${leftPadScore}:${rightPadScore}`;
    resetPong();
  }
  bounce(leftPad);
  bounce(rightPad);
  bounce(pong);
});

Мы вызываем функцию update: qKit.update(callback)

Мы помещаем всю логику в функцию обратного вызова.

Тогда, вообще говоря; мы обновляем положение квадроциклов pong, leftPad и rightPad в зависимости от их скорости.

Затем мы проверяем, есть ли столкновение между Pong и каждой из подушек, чтобы отразить направление Pong после столкновения.

Затем мы проверяем, не превышено ли значение Pong quad на площадках, затем мы увеличиваем счет для соответствующего игрока, обновляем счет, затем сбрасываем Pong.

Затем мы вызываем функцию bounce для каждого из leftPad, rightPad и pong.

Заключительное примечание: я думаю, есть некоторые крайние случаи, когда объект Pong может застревать в верхней / нижней позиции на каждой панели в некоторых сценариях, и это можно легко решить с помощью некоторого математического обнаружения столкновений. / разрешение решения. Но ради того, чтобы сосредоточиться только на цели этой статьи - показать вам, как использовать qKit для создания Pong для двух игроков, я не собираюсь останавливаться на этом.

Вот и все! У вас есть классическая игра в понг для двух игроков, в которую можно играть на одной машине :)

Надеюсь, вам понравилось это путешествие!

qKit на GitHub

Свяжитесь со мной в LinkedIn

Следуйте за мной в Twitter

Подпишитесь на мой канал на YouTube: Game Code Bites