Как создать игры на JavaScript: от простых концепций к реализации

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Новички в программировании, интересующиеся разработкой игр
  • Студенты, изучающие JavaScript и веб-разработку
  • Люди, желающие получить практические навыки в создании интерактивных приложений и игр

    Создание игр — это удивительное сочетание логики, творчества и технических навыков. JavaScript стал мощным инструментом для разработки браузерных игр, позволяя новичкам без специальных программ создавать интерактивные проекты. Когда я создал свою первую игру-платформер на чистом JS, я был поражен, как несколько сотен строк кода могут оживить персонажей и создать целый мир. Поэтому если вы мечтаете о создании собственных игр, но не знаете с чего начать — я расскажу, как JavaScript может стать вашим проводником в мир игровой разработки. 🎮

Хотите не просто изучить JavaScript, но научиться создавать с его помощью реальные проекты? Обучение веб-разработке от Skypro даст вам не только теоретическую базу, но и практические навыки создания интерактивных приложений и игр. Вы пройдете путь от основ языка до разработки полноценных проектов под руководством опытных менторов, работающих в индустрии. Станьте разработчиком, который умеет воплощать идеи в коде!

Основы JavaScript для создания игр: что нужно знать

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

Игорь Петров, разработчик игр с 8-летним стажем

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

Ключевым моментом для него стало понимание того, как работает игровой цикл — концепция, о которой я всегда говорю новичкам в первую очередь. Максим обнаружил, что его игра работает медленно на некоторых устройствах. Мы переписали код с использованием requestAnimationFrame вместо setInterval, и производительность значительно выросла. Этот опыт показал ему, насколько важно не просто знать синтаксис языка, но и понимать специфику его применения именно в игровой разработке.

Для разработки игр на JavaScript вам понадобятся следующие базовые концепции:

  • Переменные и типы данных — для хранения игрового состояния, координат объектов, очков игрока
  • Функции — для организации логики игры и повторного использования кода
  • Условные операторы — для проверки столкновений, выигрыша/проигрыша
  • Циклы — для обновления состояния множества игровых объектов
  • Объекты и массивы — для создания игровых сущностей и управления коллекциями объектов

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

Подход Преимущества Недостатки Лучше для
Canvas API Высокая производительность, полный контроль над рендерингом Более сложная работа с интерфейсом, всё нужно рисовать вручную Динамичных игр, требующих частой перерисовки (платформеры, шутеры)
DOM-манипуляции Проще для новичков, легче создавать UI Ниже производительность при большом количестве элементов Простых казуальных игр (карточные, головоломки)

Помимо этого, полезно познакомиться с современными возможностями ES6+, которые значительно упрощают разработку:

  • Стрелочные функции — для более компактного кода игровых обработчиков
  • Шаблонные строки — для динамического создания игровых сообщений
  • Деструктуризация — для удобной работы с игровыми объектами
  • Классы — для создания чётких шаблонов игровых сущностей

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

Пошаговый план для смены профессии

Синтаксис и структуры данных JS для игровой разработки

Для эффективной разработки игр необходимо не просто знать базовый синтаксис JavaScript, но и уметь правильно применять его специфические конструкции для решения игровых задач. Эти знания позволят вам создавать чистый, поддерживаемый код и избежать типичных "подводных камней". 📝

Начнем с основополагающей структуры любой игры — игрового объекта. В JavaScript игровые объекты обычно представляются как объекты или экземпляры классов:

JS
Скопировать код
// Игровой объект с использованием простого объекта
const player = {
x: 100,
y: 200,
width: 32,
height: 48,
speed: 5,
health: 100,
move: function(direction) {
if (direction === 'left') this.x -= this.speed;
if (direction === 'right') this.x += this.speed;
// и т.д.
}
};

// Более современный подход с использованием классов
class GameObject {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

update() {
// Логика обновления объекта
}

render(context) {
// Отрисовка объекта на canvas
}
}

class Player extends GameObject {
constructor(x, y) {
super(x, y, 32, 48);
this.speed = 5;
this.health = 100;
}

move(direction) {
// Реализация движения
}
}

Использование классов для игровых объектов дает несколько преимуществ:

  • Инкапсуляция — вся логика, связанная с объектом, находится в одном месте
  • Наследование — позволяет создавать иерархии игровых объектов (враги, препятствия и т.д.)
  • Полиморфизм — различные объекты могут иметь разное поведение при вызове одинаковых методов

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

JS
Скопировать код
const enemies = [];

// Создание нескольких врагов
for (let i = 0; i < 5; i++) {
enemies.push(new Enemy(Math.random() * canvas.width, 0));
}

// Обновление всех врагов в игровом цикле
function updateEnemies() {
for (const enemy of enemies) {
enemy.update();
// Проверка коллизий
if (checkCollision(player, enemy)) {
player.takeDamage(enemy.damage);
}
}
// Удаление "мертвых" врагов
enemies = enemies.filter(enemy => enemy.isAlive);
}

Для реализации игровой логики ключевую роль играют следующие структуры данных:

Структура данных Применение в играх Пример использования
Объекты Представление игровых сущностей Игрок, враги, предметы, уровни
Массивы Коллекции игровых объектов Список врагов, препятствий, пуль
Map Хранение ключ-значение с произвольными ключами Кэширование ресурсов, состояний игровых объектов
Set Хранение уникальных значений Отслеживание активных клавиш, коллизий
Очереди Обработка событий в порядке поступления Очередь звуков, анимаций, действий игрока

Одной из наиболее полезных техник для игр является использование "состояний" для управления различными фазами игры:

JS
Скопировать код
const GameState = {
LOADING: 'loading',
MENU: 'menu',
PLAYING: 'playing',
PAUSED: 'paused',
GAME_OVER: 'gameOver'
};

let currentState = GameState.LOADING;

function gameLoop() {
switch (currentState) {
case GameState.LOADING:
loadAssets();
break;
case GameState.MENU:
renderMenu();
break;
case GameState.PLAYING:
updateGame();
renderGame();
break;
case GameState.PAUSED:
renderPauseScreen();
break;
case GameState.GAME_OVER:
renderGameOver();
break;
}
requestAnimationFrame(gameLoop);
}

Теперь, когда мы разобрались с основными структурами данных, давайте перейдем к изучению Canvas API и DOM-манипуляций для создания визуальной составляющей наших игр. 🎨

Canvas API и DOM-манипуляции в игровых проектах

Когда дело доходит до визуализации игры, у JavaScript-разработчиков есть два основных подхода: использование Canvas API для рисования и манипулирование DOM-элементами. Каждый из них имеет свои уникальные преимущества и особенности применения. Рассмотрим их подробнее. 🖌️

Canvas API: рисуем игровой мир

Canvas API представляет собой низкоуровневый интерфейс для рисования 2D-графики. Это фактически холст, на котором вы можете рисовать с помощью JavaScript:

JS
Скопировать код
// Создание canvas элемента
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// Настройка размера
canvas.width = 800;
canvas.height = 600;

// Отрисовка игрока
function drawPlayer(x, y, width, height) {
ctx.fillStyle = 'blue';
ctx.fillRect(x, y, width, height);

// Добавим глаза для персонажа
ctx.fillStyle = 'white';
ctx.fillRect(x + 5, y + 5, 5, 5);
ctx.fillRect(x + width – 10, y + 5, 5, 5);
}

// Отрисовка врага
function drawEnemy(x, y, radius) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}

// Очистка экрана и отрисовка всего
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer(playerX, playerY, 30, 30);

// Отрисовка нескольких врагов
enemies.forEach(enemy => {
drawEnemy(enemy.x, enemy.y, enemy.radius);
});

requestAnimationFrame(render);
}

Преимущества Canvas API:

  • Высокая производительность при большом количестве объектов
  • Полный контроль над каждым пикселем
  • Отлично подходит для динамичных игр с постоянной перерисовкой
  • Поддержка сложных графических эффектов (тени, градиенты, трансформации)
  • Упрощенная работа со спрайтами и анимацией

DOM-манипуляции: строим игры с помощью HTML и CSS

Альтернативный подход — использование DOM-элементов (div, img и т.д.) для представления игровых объектов:

JS
Скопировать код
// Создание игрового поля
const gameContainer = document.getElementById('game-container');
gameContainer.style.width = '800px';
gameContainer.style.height = '600px';
gameContainer.style.position = 'relative';

// Создание игрока
function createPlayer(x, y) {
const player = document.createElement('div');
player.className = 'player';
player.style.width = '30px';
player.style.height = '30px';
player.style.backgroundColor = 'blue';
player.style.position = 'absolute';
player.style.left = x + 'px';
player.style.top = y + 'px';

gameContainer.appendChild(player);
return player;
}

// Обновление позиции игрока
function updatePlayerPosition(playerElement, x, y) {
playerElement.style.left = x + 'px';
playerElement.style.top = y + 'px';
}

// Создаем игрока и управляем им
const player = createPlayer(100, 100);

document.addEventListener('keydown', (e) => {
let x = parseInt(player.style.left);
let y = parseInt(player.style.top);

if (e.key === 'ArrowRight') x += 5;
if (e.key === 'ArrowLeft') x -= 5;
if (e.key === 'ArrowUp') y -= 5;
if (e.key === 'ArrowDown') y += 5;

updatePlayerPosition(player, x, y);
});

Преимущества DOM-манипуляций:

  • Проще для начинающих разработчиков
  • Естественная интеграция с HTML/CSS (можно использовать CSS-анимации, трансформации)
  • Легче создавать и стилизовать UI-элементы (меню, счетчики)
  • Отлично работает для пошаговых или более статичных игр
  • Более простая обработка событий (кликов, наведений)

Анна Соколова, ведущий разработчик браузерных игр

В 2019 году я работала над образовательной игрой "Код Героя" для детей, изучающих программирование. Изначально мы планировали использовать Canvas для всего проекта, но быстро столкнулись с проблемой: нам нужно было интегрировать сложные интерактивные элементы интерфейса — редактор кода с подсветкой синтаксиса, drag-and-drop блоков кода и мгновенную обратную связь.

Решение пришло, когда мы применили гибридный подход: основное игровое поле с персонажем и уровнями реализовали на Canvas для производительности, а весь интерфейс — через DOM-манипуляции. Для взаимодействия между этими двумя мирами мы создали систему событий, которая синхронизировала состояние игры.

Самым сложным было научиться правильно разделять ответственность: что должно обрабатываться в Canvas-мире, а что — в DOM. Но когда мы нашли баланс, производительность игры значительно выросла, а интерфейс стал гораздо удобнее. Этот опыт научил меня главному: не бывает универсального инструмента — успех приходит, когда вы умеете комбинировать подходы.

Выбор подхода для вашей первой игры

Для начинающих разработчиков игр я рекомендую руководствоваться следующими критериями при выборе технологии:

Характеристика игры Canvas API DOM-манипуляции
Динамичные игры (платформеры, шутеры) ✅ Оптимальный выбор ⚠️ Возможны проблемы с производительностью
Головоломки, карточные игры ⚠️ Избыточно для простых элементов ✅ Отлично подходит
Сложные графические эффекты ✅ Встроенная поддержка ⚠️ Требует CSS-трюков
Сложные UI с формами, вводом ❌ Требует ручной реализации ✅ Нативная поддержка
Оптимально для новичков ⚠️ Требует понимания графики ✅ Проще освоить

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

Игровой цикл и обработка событий на JavaScript

Сердцем любой игры является игровой цикл — механизм, который обновляет состояние игры и перерисовывает экран с определенной частотой. Именно он создает иллюзию движения и обеспечивает отзывчивость игры на действия пользователя. 💓

Классический игровой цикл в JavaScript состоит из трех основных этапов:

  1. Update (обновление) — обновление состояния всех игровых объектов
  2. Render (отрисовка) — визуализация текущего состояния игры
  3. Repeat (повторение) — запуск следующего кадра

Давайте реализуем базовый игровой цикл:

JS
Скопировать код
// Состояние игры
const game = {
player: {
x: 100,
y: 100,
speed: 5,
width: 32,
height: 32
},
enemies: [
{ x: 200, y: 150, speed: 2, width: 32, height: 32 },
{ x: 300, y: 250, speed: 3, width: 32, height: 32 }
],
keysPressed: {},
score: 0,
isGameOver: false
};

// Обработка нажатий клавиш
document.addEventListener('keydown', (e) => {
game.keysPressed[e.code] = true;
});

document.addEventListener('keyup', (e) => {
game.keysPressed[e.code] = false;
});

// Функция обновления состояния игры
function update(deltaTime) {
if (game.isGameOver) return;

// Обновление позиции игрока на основе нажатых клавиш
if (game.keysPressed['ArrowRight']) {
game.player.x += game.player.speed;
}
if (game.keysPressed['ArrowLeft']) {
game.player.x -= game.player.speed;
}
if (game.keysPressed['ArrowUp']) {
game.player.y -= game.player.speed;
}
if (game.keysPressed['ArrowDown']) {
game.player.y += game.player.speed;
}

// Обновление врагов
game.enemies.forEach(enemy => {
// Простая логика движения врага к игроку
if (enemy.x < game.player.x) enemy.x += enemy.speed;
else enemy.x -= enemy.speed;

if (enemy.y < game.player.y) enemy.y += enemy.speed;
else enemy.y -= enemy.speed;

// Проверка столкновений
if (checkCollision(game.player, enemy)) {
game.isGameOver = true;
}
});

// Увеличение счета со временем
game.score += deltaTime / 1000;
}

// Функция проверки столкновений (простая реализация AABB)
function checkCollision(obj1, obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}

// Функция отрисовки
function render() {
// Очистка canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Отрисовка игрока
ctx.fillStyle = 'blue';
ctx.fillRect(game.player.x, game.player.y, game.player.width, game.player.height);

// Отрисовка врагов
ctx.fillStyle = 'red';
game.enemies.forEach(enemy => {
ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
});

// Отрисовка счета
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText(`Счет: ${Math.floor(game.score)}`, 20, 30);

// Отрисовка экрана окончания игры
if (game.isGameOver) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = '36px Arial';
ctx.textAlign = 'center';
ctx.fillText('ИГРА ОКОНЧЕНА', canvas.width/2, canvas.height/2);
ctx.font = '24px Arial';
ctx.fillText(`Ваш счет: ${Math.floor(game.score)}`, canvas.width/2, canvas.height/2 + 40);
}
}

// Время последнего кадра
let lastTime = 0;

// Основной игровой цикл
function gameLoop(timestamp) {
// Расчет времени, прошедшего с предыдущего кадра
const deltaTime = timestamp – lastTime;
lastTime = timestamp;

update(deltaTime);
render();

// Запрос следующего кадра
requestAnimationFrame(gameLoop);
}

// Запуск игрового цикла
requestAnimationFrame(gameLoop);

Важно отметить, что в современном JavaScript для создания игрового цикла используется функция requestAnimationFrame вместо устаревших setInterval или setTimeout, поскольку она:

  • Синхронизируется с частотой обновления экрана (обычно 60 кадров в секунду)
  • Приостанавливается в неактивных вкладках, экономя ресурсы
  • Обеспечивает более плавную анимацию
  • Автоматически учитывает высокие частоты обновления экранов (120Hz+)

Обработка пользовательского ввода

Одной из ключевых частей интерактивной игры является обработка действий пользователя. JavaScript предлагает несколько способов получения ввода:

Тип ввода События Применение в играх
Клавиатура keydown, keyup, keypress Управление персонажем, горячие клавиши
Мышь mousedown, mouseup, mousemove, click Прицеливание, выбор объектов, UI взаимодействие
Сенсорный ввод touchstart, touchmove, touchend Мобильное управление, жесты
Геймпад gamepadconnected, gamepaddisconnected Консольное управление для более сложных игр

Современный подход к обработке ввода в играх — создание системы состояния ввода, которая регистрирует все нажатия и отпускания клавиш:

JS
Скопировать код
// Объект для отслеживания состояния ввода
const input = {
keys: {},
mouse: {
x: 0,
y: 0,
pressed: false
},
touches: []
};

// Обработчики клавиатуры
window.addEventListener('keydown', (e) => {
input.keys[e.code] = true;
});

window.addEventListener('keyup', (e) => {
input.keys[e.code] = false;
});

// Обработчики мыши
canvas.addEventListener('mousemove', (e) => {
// Получаем координаты относительно canvas
const rect = canvas.getBoundingClientRect();
input.mouse.x = e.clientX – rect.left;
input.mouse.y = e.clientY – rect.top;
});

canvas.addEventListener('mousedown', () => {
input.mouse.pressed = true;
});

canvas.addEventListener('mouseup', () => {
input.mouse.pressed = false;
});

// Обработчики сенсорного ввода
canvas.addEventListener('touchstart', (e) => {
e.preventDefault(); // Предотвращаем зум и другие действия браузера
const rect = canvas.getBoundingClientRect();
input.touches = Array.from(e.touches).map(touch => ({
id: touch.identifier,
x: touch.clientX – rect.left,
y: touch.clientY – rect.top
}));
});

// В функции update используем состояние ввода
function update() {
// Проверка нажатий клавиш
if (input.keys['ArrowRight']) {
player.x += player.speed;
}

// Проверка нажатия мыши
if (input.mouse.pressed) {
// Создание выстрела в направлении курсора
createBullet(player.x, player.y, input.mouse.x, input.mouse.y);
}

// и так далее...
}

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

Первая игра на JavaScript: от концепции к реализации

Настало время объединить все полученные знания и создать простую, но полноценную игру. В качестве примера мы разработаем мини-игру "Космический защитник" — классический шутер, где игрок управляет космическим кораблем и уничтожает приближающихся врагов. 🚀

Давайте разобьем процесс создания на логические этапы и посмотрим, как воплотить нашу игру в коде:

Шаг 1: Структура проекта и базовая настройка

Начнем с создания базовой структуры HTML и подключения JavaScript:

HTML
Скопировать код
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Космический защитник</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
canvas {
border: 2px solid #333;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script src="game.js"></script>
</body>
</html>

Далее создадим базовую структуру JavaScript файла:

JS
Скопировать код
// game.js
// 1. Инициализация canvas и контекста
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;

// 2. Создание основных объектов игры
const game = {
isRunning: true,
score: 0
};

const player = {
x: canvas.width / 2,
y: canvas.height – 50,
width: 50,
height: 30,
speed: 5,
color: '#0F0'
};

const enemies = [];
const bullets = [];
const particles = [];

// 3. Система управления
const input = {
keys: {},
mouse: { x: 0, y: 0, pressed: false }
};

// Обработчики событий
window.addEventListener('keydown', (e) => {
input.keys[e.code] = true;
});

window.addEventListener('keyup', (e) => {
input.keys[e.code] = false;
});

canvas.addEventListener('click', () => {
// Создаем пулю при клике
fireBullet();
});

// 4. Инициализация игрового цикла
let lastTime = 0;
requestAnimationFrame(gameLoop);

Шаг 2: Реализация основных игровых механик

Теперь добавим основные функции для работы игры:

JS
Скопировать код
// Создание нового врага
function spawnEnemy() {
const enemy = {
x: Math.random() * (canvas.width – 40),
y: -30,
width: 40,
height: 30,
speed: 1 + Math.random() * 3,
color: 'red'
};
enemies.push(enemy);
}

// Создание пули
function fireBullet() {
const bullet = {
x: player.x + player.width / 2 – 2.5,
y: player.y,
width: 5,
height: 15,
speed: 7,
color: '#FFF'
};
bullets.push(bullet);
}

// Создание эффекта взрыва
function createExplosion(x, y) {
for (let i = 0; i < 20; i++) {
const particle = {
x: x,
y: y,
size: 2 + Math.random() * 3,
speed: 1 + Math.random() * 3,
angle: Math.random() * Math.PI * 2,
color: `hsl(${Math.random() * 30 + 10}, 100%, 50%)`,
lifespan: 30 + Math.random() * 30,
age: 0
};
particles.push(particle);
}
}

// Проверка столкновений
function checkCollision(obj1, obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}

// Функция обновления состояния игры
function update(deltaTime) {
// Обработка управления
if (input.keys['ArrowLeft'] && player.x > 0) {
player.x -= player.speed;
}
if (input.keys['ArrowRight'] && player.x < canvas.width – player.width) {
player.x += player.speed;
}

// Периодическое создание врагов
if (Math.random() < 0.02) {
spawnEnemy();
}

// Обновление положения пуль
bullets.forEach((bullet, bulletIndex) => {
bullet.y -= bullet.speed;

// Удаление пуль, вышедших за границы
if (bullet.y < 0) {
bullets.splice(bulletIndex, 1);
}
});

// Обновление положения врагов
enemies.forEach((enemy, enemyIndex) => {
enemy.y += enemy.speed;

// Проверка столкновений с пулями
bullets.forEach((bullet, bulletIndex) => {
if (checkCollision(bullet, enemy)) {
// Удаляем пулю и врага
bullets.splice(bulletIndex, 1);
enemies.splice(enemyIndex, 1);

// Создаем эффект взрыва
createExplosion(enemy.x + enemy.width / 2, enemy.y + enemy.height / 2);

// Увеличиваем счет
game.score += 100;
}
});

// Проверка столкновения с игроком или выхода за границу
if (enemy.y > canvas.height) {
enemies.splice(enemyIndex, 1);
game.score -= 50; // Штраф за пропуск врага
} else if (checkCollision(enemy, player)) {
game.isRunning = false; // Игра окончена
}
});

// Обновление частиц эффектов
particles.forEach((particle, index) => {
particle.x += Math.cos(particle.angle) * particle.speed;
particle.y += Math.sin(particle.angle) * particle.speed;
particle.age++;

if (particle.age > particle.lifespan) {
particles.splice(index, 1);
}
});
}

// Функция отрисовки
function render() {
// Очистка экрана
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Отрисовка игрока
ctx.fillStyle = player.color;
ctx.fillRect(player.x, player.y, player.width, player.height);

// Отрисовка кабины
ctx.fillStyle = '#007';
ctx.fillRect(player.x + player.width / 2 – 5, player.y – 5, 10, 10);

// Отрисовка пуль
ctx.fillStyle = '#FFF';
bullets.forEach(bullet => {
ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
});

// Отрисовка врагов
enemies.forEach(enemy => {
ctx.fillStyle = enemy.color;
ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
});

// Отрисовка частиц
particles.forEach(particle => {
ctx.fillStyle = particle.color;
ctx.globalAlpha = 1 – (particle.age / particle.lifespan);
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
});

// Отрисовка счета
ctx.fillStyle = '#FFF';
ctx.font = '20px Arial';
ctx.fillText(`Счет: ${game.score}`, 20, 30);

// Экран окончания игры
if (!game.isRunning) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#FFF';
ctx.font = '36px Arial';
ctx.textAlign = 'center';
ctx.fillText('ИГРА ОКОНЧЕНА', canvas.width / 2, canvas.height / 2);
ctx.font = '24px Arial';
ctx.fillText(`Ваш счет: ${game.score}`, canvas.width / 2, canvas.height / 2 + 50);
ctx.font = '18px Arial';
ctx.fillText('Кликните, чтобы начать заново', canvas.width / 2, canvas.height / 2 + 100);
}
}

Шаг 3: Завершение игрового цикла и рестарт игры

Наконец, завершим наш код, добавив игровой цикл и функцию рестарта:

JS
Скопировать код
// Игровой цикл
function gameLoop(timestamp) {
// Расчет времени между кадрами
const deltaTime = timestamp – lastTime;
lastTime = timestamp;

if (game.isRunning) {
update(deltaTime);
}

render();
requestAnimationFrame(gameLoop);
}

// Рестарт игры
canvas.addEventListener('click', () => {
if (!game.isRunning) {
// Сбрасываем состояние игры
game.isRunning = true;
game.score = 0;
player.x = canvas.width / 2;
enemies.length = 0;
bullets.length = 0;
particles.length = 0;
} else {
// Стреляем, если игра идет
fireBullet();
}
});

Вот и всё! У нас получилась простая, но функциональная игра "Космический защитник", которая демонстрирует все основные принципы игровой разработки на JavaScript, которые мы изучили:

  • Инициализацию и настройку игрового окружения
  • Создание и управление игровыми объектами
  • Реализацию игрового цикла с обновлением состояния и отрисовкой
  • Обработку пользовательского ввода
  • Систему столкновений и игровых событий
  • Визуальные эффекты и отображение игрового интерфейса

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

JavaScript открывает перед вами целую вселенную возможностей для создания игр – от простых головоломок до сложных многопользовательских проектов. Ключ к успеху лежит не в сложности кода, а в последовательном применении базовых принципов. Начните с малого, создайте свою первую игру, пусть даже самую простую. С каждым новым проектом вы будете расширять свои навыки и понимание. Как говорил знаменитый геймдизайнер Сид Мейер: "Игра — это серия интересных решений". И теперь вы можете создавать эти решения сами, превращая строки кода в интерактивные миры, которыми будут наслаждаться другие люди.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой язык программирования используется для разработки интерактивных игр в браузере?
1 / 5

Загрузка...