Теперь кристаллы будут прибавляться после нажатия, а отдых — возвращать энергию. Числа останутся в JavaScript; страница будет показывать их текущие значения. Это первая интерактивная версия кликера, ещё без покупки и проверки запаса энергии.

Попробуй прямо здесь: трижды нажми «Собрать кристалл», затем «Отдохнуть». Получится 3 кристалла и 10 энергии. Ниже разберём, как одно нажатие меняет данные и обновляет страницу.

Для этого урока возьми final/ урока о переменных и числах. В комплекте этого занятия папка start/ совпадает с ним. Своё решение задания из прошлого урока сохрани в отдельной папке.

Открыть эту версию в отдельной вкладке

Исходники урока

Выбирай стартовую версию, промежуточный этап или финал в просмотрщике. Во вкладке «Инструкция» — как запустить проект и чем отличаются версии. Решения самостоятельных заданий открывай после своей попытки.

Скачать ZIP

Распакуй архив целиком. У каждой версии своя папка с index.html, style.css и game.js. Открывай HTML внутри выбранной папки двойным щелчком; после правки сохраняй файл и обновляй браузер. Установка Node.js, аккаунт и сервер здесь не нужны. CSS уже знаком по первому модулю и дан как готовое оформление.

Добавляем кнопки сбора и отдыха

В index.html после блока stats и до поясняющего абзаца добавь:

<div class="actions">
  <button id="gather-button" type="button">Собрать кристалл</button>
  <button id="rest-button" type="button">Отдохнуть</button>
</div>
<p id="status" role="status">Собери кристаллы.</p>

Кнопка выполняет действие в текущей странице. Ссылка, которую ты делал в истории, открывает другой адрес. type="button" явно задаёт обычную кнопку. id — уникальное имя элемента на странице: по нему JS его найдёт. role="status" отмечает обновляемое сообщение о состоянии для вспомогательных технологий. Один id должен принадлежать только одному элементу на странице, иначе скрипт может найти не ту кнопку.

Показываем очки и энергию на странице

Оставь в game.js начальные объявления пяти переменных и двух констант из прошлого урока. Удали временные console.log: они уже помогли проверить подключение. Ниже объявлений добавь:

const scoreElement = document.getElementById('score');
const energyElement = document.getElementById('energy');
const powerElement = document.getElementById('click-power');
const statusElement = document.getElementById('status');
const gatherButton = document.getElementById('gather-button');
const restButton = document.getElementById('rest-button');

function render() {
  scoreElement.textContent = score;
  energyElement.textContent = energy;
  powerElement.textContent = clickPower;
  statusElement.textContent = 'Нажми «Собрать кристалл» или отдохни.';
}

render();

DOM — представление HTML в браузере, с которым может работать скрипт. document даёт доступ к текущей странице. Команда getElementById('score') ищет элемент с таким id; здесь передаём имя без #. Результат сохраняем в scoreElement, чтобы дальше обращаться к найденному элементу. Ссылка на элемент объявлена через const; сам элемент при этом можно изменять.

textContent — текстовое содержимое элемента. Присваивание scoreElement.textContent = score читает число из переменной и показывает его как текст. Счёт храним в переменной — читать его обратно из надписи не нужно. Если удалить надпись, число всё ещё хранится в JS.

function render() { ... } объявляет именованную функцию — набор инструкций, который выполняется по вызову. В фигурных скобках её тело, то есть действия. render — выбранное нами имя со смыслом «покажи состояние». Скобки пусты: пока ей не нужны входные параметры. Объявление само ничего не рисует. Строка render(); внизу вызывает функцию один раз при открытии страницы.

Проверка step-01: временно измени начальное score на 4 и обнови браузер: надпись должна показать 4. Верни 0. Если надпись осталась 0, проверь сохранённый файл и вызов render(). Если в Console ошибка про null, id в JS и HTML не совпал. На этом этапе кнопки видны, но обработчики ещё не зарегистрированы.

Запускаем функцию при нажатии кнопки

Перед последним render(); добавь функцию сбора и подключи её к кнопке. Это версия step-02/:

function handleGather() {
  score = score + clickPower;
  energy = energy - 1;
  render();
}

gatherButton.addEventListener('click', handleGather);

Функция handleGather описывает одно действие игрока. Сначала она изменяет данные, затем вызывает render(), чтобы экран соответствовал новым данным. Сначала меняем число, потом обновляем надпись. Если сделать наоборот, на экране останется значение прошлого хода.

addEventListener просит браузер вызвать указанную функцию, когда произойдёт событие. Первый аргумент 'click' — название события активации кнопки мышью, касанием или клавиатурой. Второй — сама функция handleGather. Здесь нужно её имя без (). Запись handleGather() немедленно запустила бы действие при настройке страницы, вместо передачи функции для будущего нажатия.

Регистрация стоит снаружи функций и выполняется один раз при загрузке. Не добавляй её в render или обработчик. Пока не нужны стрелочные функции или общий обработчик для всех кнопок: по имени сразу видно, какое действие описано.

Проверка: сразу после загрузки 0 кристаллов и 10 энергии. После одного нажатия — 1 и 9; после трёх — 3 и 7. Если очко появилось ещё до нажатия, проверь круглые скобки в регистрации. Отдых пока не подключён.

Самостоятельно: подключи отдых

Сначала сделай собственную попытку в step-02/. Напиши вторую именованную функцию handleRest, которая устанавливает энергию в 10 и обновляет экран. Зарегистрируй её для restButton. Кристаллы и сила при отдыхе не меняются. После отдыха игрок должен снова получить 10 энергии.

Подсказка 1

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

Подсказка 2

Измени переменную energy, затем вызови render(). Снаружи передай имя нового обработчика в addEventListener('click', ...).

Показать функцию отдыха
function handleRest() {
  energy = 10;
  render();
}

restButton.addEventListener('click', handleRest);

Эта версия лежит в final/. Проверь сначала свою функцию: после трёх сборов отдых даёт 3 кристалла, 10 энергии и силу 1.

Проверяем кнопки и запас энергии

Нажми Tab до кнопки сбора, затем Enter. Должно произойти то же действие, что и мышью. Нажми отдых несколько раз: энергия остаётся 10, очки не меняются. Обновление страницы начинает заново с 0/10. Пока нет сохранения.

Если нажать сбор 11 раз без отдыха, энергия станет −1. Пока функция уменьшает энергию при каждом нажатии, даже когда она закончилась. В следующем уроке добавим проверку, которая остановит сбор при нуле. А сейчас проследи на первых трёх нажатиях, как кнопка меняет переменные и надписи на странице.

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

Разбор самостоятельного задания

Сначала попробуй решить задание сам. Затем сравни с примером ту функцию или условие, которые вызвали затруднение. Разбор самостоятельной задачи доступен во вкладке «Решение» в просмотрщике исходников.

Справочник: addEventListener в MDN.