Tower Defence. Часть 1

Tower Defence. Часть 1: Фундамент игры

Ты начинаешь проект, который очень похож на реальную frontend-разработку: есть состояние (state), цикл обновления, рендер на canvas и действия пользователя.

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

Посмотри целевой результат

Ниже встроена демо-игра, к которой мы идем по шагам:

[tower-defense-iframe]

Карта технологий всей линии Tower Defence (части 1-5)

  1. 2D-координаты и сетка ({ x, y }, клетки и пиксели).
  2. Математика движения (направление, расстояние, шаг по времени).
  3. Структуры данных JS (Array, Object, Set).
  4. Игровое состояние и его сброс (state, reset).
  5. Wave-система (очередь врагов, таймер спавна).
  6. События пользователя (click, кнопки).
  7. Выбор целей и приоритеты.
  8. Анимационный цикл (requestAnimationFrame, dt).
  9. Подготовка draw-data для рендера.
  10. Финальные метрики, прогресс, итоговый счет.

Технологии именно этого урока (lesson-10-12)

  1. Координатная сетка 2D и точки маршрута.
  2. Линейный проход по сегментам пути (for, while).
  3. Направление движения по оси через Math.sign.
  4. Хранение клеток маршрута в Set для быстрых проверок.
  5. Инициализация объекта состояния игры.
  6. Перевод клетки в пиксели (toWorld).
  7. Формулы скейлинга врага по волне (hp/speed/reward).
  8. Таймерный спавн в updateWave.
  9. Guard-проверки (ранний return) для стабильной логики.

Фундамент: 2D-пространство простыми словами

Игровое поле делится на клетки. У клетки есть адрес { x, y }:

  • x показывает позицию по горизонтали (влево/вправо);
  • y показывает позицию по вертикали (вверх/вниз);
  • { x: 0, y: 0 } — верхний левый угол.

Пример:

const a = { x: 0, y: 3 };
const b = { x: 3, y: 3 };
const c = { x: 3, y: 1 };

a -> b это движение вправо, b -> c это движение вверх.

Фундамент: как строится маршрут врагов

Маршрут — массив опорных точек path. Враг идет не «по диагонали куда угодно», а по сегментам:

  • от path[0] к path[1],
  • от path[1] к path[2],
  • и так далее.

Направление сегмента:

const dx = Math.sign(to.x - from.x);
const dy = Math.sign(to.y - from.y);
  • dx = 1 значит идем вправо, dx = -1 влево, dx = 0 по x не двигаемся;
  • dy = 1 вниз, dy = -1 вверх, dy = 0 по y не двигаемся.

Что именно ты реализуешь в задачах

  1. createBoardConfig: создаешь конфиг поля (cellSize, cols, rows, width, height).
  2. createPath: возвращаешь 6 точек маршрута в правильном порядке, как в демо-игре.
  3. buildPathCells: проходишь по сегментам и заполняешь Set строками вида "x,y".
  4. createInitialState: задаешь стартовые значения (lives, money, wave, массивы и флаги).
  5. resetGame: полностью возвращаешь state к старту.
  6. toWorld: переводишь координату клетки в центр клетки в пикселях.
  7. spawnEnemy: создаешь врага в начале пути с параметрами, зависящими от wave.
  8. startWave: запускаешь волну только в валидном состоянии.
  9. updateWave: по таймеру спавнишь врагов из очереди.
  10. getModeLabel: собираешь понятный режим для HUD: ожидание/волна/game over.

Почему это важно

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

Эта часть учит тебя главному инженерному принципу: сначала базовые контракты и чистые helper-функции, потом остальная механика.

Мини-примеры из практики урока

function toWorld(cellX, cellY, cellSize) {
  return {
    x: cellX * cellSize + cellSize / 2,
    y: cellY * cellSize + cellSize / 2,
  };
}
function startWave(state) {
  // Guard: не стартуем, если уже game over, волна уже идет или враги еще на поле
  if (state.gameOver || state.waveQueue > 0 || state.enemies.length > 0) return state;
  state.wave += 1;
  state.waveQueue = 5 + state.wave * 2;
  state.spawnTimer = 0;
  return state;
}

Смотри, что важно: в этом уроке waveQueue — это счетчик (сколько врагов еще нужно заспавнить), а spawnTimer — таймер до следующего спавна (обычно в секундах).

Результат после Part 1

У тебя готова основа TD-игры: поле, маршрут, состояние, волны и спавн. Это база для Part 2, где добавим постановку башен.