Пошаговое руководство для начинающих

Шаг 1. Настройка вашего игрового холста

Прежде чем мы сможем начать создавать нашу игру, нам нужно создать элемент холста, который мы можем использовать для рисования наших игровых объектов. Элемент canvas — это элемент HTML5, предоставляющий пространство, на котором мы можем рисовать графику с помощью JavaScript.

Чтобы настроить холст, нам сначала нужно создать тег «холст» в нашем HTML-файле. Мы можем дать элементу холста идентификатор, чтобы мы могли ссылаться на него в нашем коде JavaScript. Например:

<canvas id="gameCanvas"></canvas>

Далее нам нужно определить размер нашего холста. Мы можем сделать это, установив атрибуты width и height элемента canvas, например:

<canvas id="gameCanvas" width="800" height="600"></canvas>

В этом примере мы установили ширину холста на 800 пикселей и высоту на 600 пикселей. Вы можете настроить размер холста в соответствии с требованиями вашей игры.

Мы также можем добавить на холст несколько стилей CSS, чтобы придать ему границу или изменить цвет фона, например:

#gameCanvas {
  border: 1px solid black;
  background-color: #f0f0f0;
}

Это придаст холсту черную рамку и светло-серый цвет фона.

После того, как мы настроили наш элемент холста, мы готовы начать рисовать на нем с помощью JavaScript. На следующем шаге мы создадим несколько игровых объектов и добавим их на холст.

Шаг 2: Создание игровых объектов

Теперь, когда мы настроили холст, мы можем приступить к созданию игровых объектов. В этом уроке мы создадим простую игру, в которой игрок управляет квадратом, который может двигаться влево и вправо и избегать препятствия, которые падают с верхней части экрана.

Чтобы создать наши игровые объекты, мы будем использовать JavaScript для создания объектов, представляющих каждый из игровых элементов. Например, мы можем создать объект Player, представляющий квадрат, которым управляет игрок, и объект Obstacle, представляющий падающие препятствия.

// define the Player object
let Player = function(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
};

// define the Obstacle object
let Obstacle = function(x, y, width, height, speed) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
  this.speed = speed;
};

В этом примере мы определили два объекта с помощью функций-конструкторов. Объект Player имеет четыре свойства: x, y, width и height, которые представляют положение и размер клетки игрока. Объект Obstacle имеет пять свойств: x, y, width, height и speed, которые представляют положение, размер и скорость падающих препятствий.

Далее мы создадим экземпляры этих объектов и добавим их на холст. Мы сделаем это, создав метод draw() для каждого объекта, который будет рисовать объект на холсте, используя контекст холста.

// define the draw() method for the Player object
Player.prototype.draw = function() {
  context.fillStyle = '#000';
  context.fillRect(this.x, this.y, this.width, this.height);
};

// define the draw() method for the Obstacle object
Obstacle.prototype.draw = function() {
  context.fillStyle = '#f00';
  context.fillRect(this.x, this.y, this.width, this.height);
};

В этом примере мы определили метод draw() для каждого объекта, который использует контекст холста для рисования прямоугольника на холсте с указанными позицией и размером.

Наконец, мы создадим экземпляры этих объектов и добавим их на холст. Мы можем сделать это, создав новый экземпляр объекта Player и вызвав его метод draw(), а также создав массив объектов Obstacle и вызвав их методы draw() в цикле.

// create a new instance of the Player object
let player = new Player(380, 550, 40, 40);

// create an array of Obstacle objects
let obstacles = [];
for (let i = 0; i < 5; i++) {
  let obstacle = new Obstacle(Math.random() * 760, -50, 40, 40, Math.random() * 2 + 1);
  obstacles.push(obstacle);
}
// call the draw() method for each object
player.draw();
for (let i = 0; i < obstacles.length; i++) {
  obstacles[i].draw();
}

В этом примере мы создали новый экземпляр объекта Player с начальной позицией (380, 550) и размером 40x40 пикселей. Мы также создали массив из 5 объектов Obstacle со случайными позициями и скоростями и добавили их в массив obstacles.

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

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

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

Шаг 3: Добавление пользовательского ввода

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

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

// add an event listener for the keydown event
document.addEventListener('keydown', function(event) {
  if (event.keyCode === 37) { // left arrow key
    player.x -= 10;
  } else if (event.keyCode === 39) { // right arrow key
    player.x += 10;
  }
});

В этом примере мы добавили прослушиватель событий для события keydown с помощью метода addEventListener(). Когда событие запускается, мы проверяем свойство keyCode объекта события, чтобы определить, какая клавиша была нажата. Если нажата клавиша со стрелкой влево, мы вычитаем 10 из свойства x объекта игрока, чтобы сдвинуть его влево. Если нажата клавиша со стрелкой вправо, мы добавляем 10 к свойству x объекта игрока, чтобы переместить его вправо.

Нам также потребуется обновить метод draw() объекта Player, чтобы перерисовать квадрат игрока с его новой позицией.

// update the draw() method for the Player object to include the new position
Player.prototype.draw = function() {
  context.fillStyle = '#000';
  context.fillRect(this.x, this.y, this.width, this.height);
};

Теперь, когда игрок перемещает квадрат влево или вправо, квадрат будет перерисовываться в новой позиции на холсте.

На следующем шаге мы добавим движение падающим препятствиям и обнаружим столкновения между игроком и препятствиями.

Шаг 4: Добавление обнаружения движения и столкновений

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

Чтобы добавить движения препятствиям, мы будем обновлять их y положение в каждом кадре, используя функцию setInterval().

// add a setInterval() function to update the position of the obstacles
setInterval(function() {
  for (var i = 0; i < obstacles.length; i++) {
    obstacles[i].y += 5;
  }
}, 50);

В этом примере мы добавили функцию setInterval(), которая будет запускаться каждые 50 миллисекунд. Внутри функции мы перебираем все препятствия и обновляем их y позицию, добавляя к ней 5. Это заставит препятствия падать с верхней части холста с постоянной скоростью.

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

// add a checkCollision() function to check for collisions between the player square and obstacles
function checkCollision(player, obstacles) {
  for (var i = 0; i < obstacles.length; i++) {
    var obstacle = obstacles[i];
    if (player.x < obstacle.x + obstacle.width &&
        player.x + player.width > obstacle.x &&
        player.y < obstacle.y + obstacle.height &&
        player.y + player.height > obstacle.y) {
      // collision detected
      return true;
    }
  }
  return false;
}

В этом примере мы создали функцию checkCollision(), которая принимает объект player и массив препятствий в качестве аргументов. Внутри функции мы перебираем все препятствия и проверяем, пересекаются ли какие-либо из них с квадратом игрока, используя следующую формулу:

player.x < obstacle.x + obstacle.width &&
player.x + player.width > obstacle.x &&
player.y < obstacle.y + obstacle.height &&
player.y + player.height > obstacle.y

Если обнаружено столкновение, функция возвращает true. Если столкновения не обнаружено, функция возвращает false.

Теперь нам нужно вызвать функцию checkCollision() внутри метода update() нашего игрового цикла, чтобы проверять наличие коллизий в каждом кадре.

// add collision detection to the update() method of our game loop
function update() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  player.draw();
    for (var i = 0; i < obstacles.length; i++) {
      obstacles[i].draw();
    }
    if (checkCollision(player, obstacles)) {
      console.log('Game over!');
      return;
    }
    requestAnimationFrame(update);
  }

В этом примере мы добавили вызов функции checkCollision() внутри метода update() нашего игрового цикла. Если обнаружено столкновение, мы записываем сообщение в консоль и возвращаемся из функции, чтобы остановить игровой цикл.

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

Шаг 5. Добавление экранов подсчета очков и окончания игры

Наконец, давайте добавим в нашу игру несколько экранов подсчета очков и окончания игры. Мы упростим задачу, отображая счет как количество препятствий, которые игрок успешно избежал. Когда игрок сталкивается с препятствием, мы показываем экран завершения игры с окончательным счетом.

Чтобы отслеживать счет, мы создадим переменную score и будем увеличивать ее каждый раз, когда препятствие выходит за нижнюю часть холста, не будучи пораженным игроком.

// add a score variable to keep track of the player's score
var score = 0;
// inside the setInterval() function that updates the position of the obstacles
setInterval(function() {
  for (var i = 0; i < obstacles.length; i++) {
    obstacles[i].y += 5;
    if (obstacles[i].y > canvas.height) {
      // obstacle has gone off the bottom of the canvas without being hit
      score++;
      obstacles.splice(i, 1);
      i--;
    }
  }
  // add a new obstacle every 2 seconds
  if (frames % 120 === 0) {
    obstacles.push(new Obstacle());
  }
  frames++;
}, 50);

В этом примере мы добавили переменную score, которая начинается с 0. Внутри функции setInterval(), которая обновляет положение препятствий, мы проверяем, не ушло ли препятствие за нижнюю часть холста без удара игрока. Если это так, мы увеличиваем переменную score и удаляем препятствие из массива obstacles. Мы также добавляем новое препятствие каждые 2 секунды, чтобы сделать игру сложной.

Теперь давайте добавим экран завершения игры, который отображает окончательный счет, когда игрок сталкивается с препятствием. Мы сделаем это, создав функцию gameOver(), которая останавливает игровой цикл и отображает счет.

// add a gameOver() function to stop the game loop and display the final score
function gameOver() {
  context.fillStyle = '#000';
  context.fillRect(0, 0, canvas.width, canvas.height);
  context.font = '30px Arial';
  context.fillStyle = '#fff';
  context.textAlign = 'center';
  context.fillText('Game over!', canvas.width/2, canvas.height/2 - 50);
  context.fillText('Final score: ' + score, canvas.width/2, canvas.height/2);
}
// inside the update() method of our game loop
function update() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  player.draw();
  for (var i = 0; i < obstacles.length; i++) {
    obstacles[i].draw();
  }
  if (checkCollision(player, obstacles)) {
    gameOver();
    return;
  }
  context.font = '20px Arial';
  context.fillStyle = '#000';
  context.fillText('Score: ' + score, 10, 30);
  requestAnimationFrame(update);
}

В этом примере мы создали функцию gameOver(), которая останавливает игровой цикл и отображает окончательный счет. Внутри метода update() нашего игрового цикла мы добавили вызов функции gameOver() при обнаружении столкновения между игроком и препятствием. Мы также добавили код для отображения текущего счета в верхнем левом углу холста.

Шаг 6: Добавление звуковых эффектов

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

Во-первых, давайте добавим несколько аудиофайлов в наш HTML-файл.

<audio id="move-sound" src="move.wav"></audio>
<audio id="collision-sound" src="collision.wav"></audio>

Мы добавили два аудиоэлемента с ids «звука движения» и «звука столкновения». Мы также указали атрибут src, указывающий на аудиофайлы «move.wav» и «collision.wav», которые мы создадим на следующем шаге.

Далее давайте обновим метод move() нашего проигрывателя, чтобы воспроизводить звуковой эффект, когда проигрыватель перемещается вверх или вниз.

// add audio elements to HTML file
<audio id="move-sound" src="move.wav"></audio>
<audio id="collision-sound" src="collision.wav"></audio>
// inside the Player class
function Player() {
  this.x = 50;
  this.y = canvas.height/2;
  this.width = 20;
  this.height = 20;
  // add variables for the player's movement and sound effects
  this.dy = 0;
  this.moveSound = new Audio('move.wav');
  this.draw = function() {
    context.fillStyle = '#fff';
    context.fillRect(this.x, this.y, this.width, this.height);
  }
  // add code to play a sound effect when the player moves up or down
  this.move = function() {
    if (keys.up && this.y > 0) {
      this.dy = -5;
      this.moveSound.currentTime = 0;
      this.moveSound.play();
    } else if (keys.down && this.y < canvas.height - this.height) {
      this.dy = 5;
      this.moveSound.currentTime = 0;
      this.moveSound.play();
    } else {
      this.dy = 0;
    }
    this.y += this.dy;
  }
}

В этом примере мы добавили две новые переменные в наш класс Player: this.dy для хранения вертикальной скорости игрока и this.moveSound для хранения звукового эффекта движения игрока. В метод move() мы добавили код для воспроизведения звукового эффекта при перемещении игрока вверх или вниз.

// add audio elements to HTML file
<audio id="move-sound" src="move.wav"></audio>
<audio id="collision-sound" src="collision.wav"></audio>
// inside the update() method of our game loop
function update() {
  // ...
  if (checkCollision(player, obstacles)) {
    collisionSound.currentTime = 0;
    collisionSound.play();
    gameOver();
    return;
  }
  // ...
}
// at the end of our script, create a collisionSound object
var collisionSound = new Audio('collision.wav');

В этом примере мы добавили код для воспроизведения звукового эффекта «collision.wav» при обнаружении столкновения между игроком и препятствием. Мы также создали объект collisionSound в конце нашего скрипта для хранения звукового эффекта.

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

Шаг 7: Публикация игры

Теперь, когда мы создали нашу игру, пришло время поделиться ею со всем миром! На этом этапе мы покажем вам, как опубликовать игру в Интернете с помощью GitHub Pages.

Во-первых, давайте создадим новый репозиторий на GitHub для хранения кода нашей игры. Перейдите на сайт GitHub и войдите в систему (или создайте учетную запись, если у вас ее нет). Затем щелкните значок «+» в правом верхнем углу экрана и выберите «Новый репозиторий» в раскрывающемся меню.

На странице «Создать новый репозиторий» введите имя репозитория (например, «простая игра»), добавьте описание, если хотите, и убедитесь, что выбран вариант «Общедоступный». Оставьте для всех остальных параметров значения по умолчанию и нажмите кнопку «Создать репозиторий».

Затем давайте загрузим наши игровые файлы в репозиторий. Откройте терминал или командную строку на своем компьютере, перейдите в папку, в которой находятся ваши игровые файлы, и выполните следующие команды:

git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/<your-username>/simple-game.git
git push -u origin master

Замените <your-username> своим именем пользователя GitHub и введите пароль GitHub при появлении запроса.

Эти команды инициализируют новый репозиторий Git в папке с игрой, добавляют все файлы в репозиторий, фиксируют изменения с сообщением «Начальная фиксация» и отправляют изменения в удаленный репозиторий на GitHub.

Теперь давайте опубликуем нашу игру с помощью GitHub Pages. На странице вашего репозитория на GitHub перейдите на вкладку «Настройки», прокрутите вниз до раздела «Страницы GitHub» и выберите «основную ветку» в качестве источника. Нажмите кнопку «Сохранить» и подождите несколько секунд, пока GitHub создаст и развернет ваш сайт.

После завершения развертывания вы увидите зеленое сообщение с URL-адресом вашего сайта (например, «https://‹your-username›.github.io/simple-game/»). Щелкните URL-адрес, чтобы открыть игру в новой вкладке и убедиться, что она работает должным образом.

Поздравляем! Вы только что опубликовали свою первую игру JavaScript в Интернете с помощью GitHub Pages. Не стесняйтесь поделиться URL-адресом с друзьями, добавить в игру дополнительные функции или создать новые игры, используя те же методы. Возможности безграничны!

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.