Была пятница вечером, и мне захотелось сделать что-то просто потому что интересно. Без задачи, без продуктового смысла. Я вспомнил, что когда-то в детстве первая игра, в которую я играл, была River Raid — та самая аркада Activision для Atari 2600, 1983 год. И подумал: а почему бы не собрать это в браузере? И раз уж деплоить — то сразу в Telegram.
Через сутки игра работала. Вот что я узнал по пути.
>> СТЕК — ПРОЩЕ ЧЕМ КАЖЕТСЯ:
River Raid — это Canvas. Никакой физики, никаких игровых движков — просто цикл requestAnimationFrame, который рисует пиксели.
Фронтенд я собрал без сборки: React прямо с CDN, Tailwind тоже с CDN. Vite подключил только для dev-сервера — удобно. В продакшене отдаётся один HTML файл.
Бэкенд — Node.js + Fastify. Единственная задача: хранить топ-10 рекордов и отдавать их по запросу. База данных — JSON файл на диске. Для 10 записей это достаточно.
Шрифт — Press Start 2P. Без него ретро-эстетики не было бы.
>> TELEGRAM MINIAPP — ТРИ СЮРПРИЗА:
Первый. Telegram требует HTTPS. Обязательно, без вариантов. Локальный http://localhost не откроется в боте. Нужен реальный домен с сертификатом.
Второй. Идентификация пользователя работает через window.Telegram.WebApp.initDataUnsafe.user. Имя, юзернейм, ID — всё там. Но это поле есть только внутри Telegram. На десктопе в браузере — undefined. Пришлось везде добавить ?. и fallback на "Guest".
Третий. WebApp.ready() нужно вызвать как можно раньше — иначе Telegram показывает лоадер поверх игры. Одна строчка, но без неё UX сломан.
>> УПРАВЛЕНИЕ НА МОБИЛЕ — ИТЕРАЦИИ:
На десктопе управление простое — стрелки и пробел. На мобиле пришлось думать.
Первый вариант: кнопки на экране. Неудобно — пальцы закрывают игру.
Второй: тап по экрану = выстрел, свайп = движение. Лучше, но реакция тупила.
Итоговый вариант: тилт-управление через гироскоп телефона. Наклоняешь устройство — самолёт летит в ту сторону. Тап в любом месте = огонь. Звучит странно, но работает неожиданно хорошо — особенно для аркады где надо лавировать между берегами реки.
>> БАГ: РЕКОРДЫ ПРОПАДАЛИ ПРИ КАЖДОМ ДЕПЛОЕ:
Это был самый обидный момент. Игра работала, Hall of Fame заполнялся — а после следующего docker compose up таблица обнулялась.
Причина: в server.js файл читался из /app/backend/highscores.json, а Docker volume был смонтирован на /app/data. При каждом деплое пересобирался образ — и файл, который лежал внутри контейнера, уходил вместе с ним.
Фикс простой: перенести путь к файлу в /app/data/highscores.json и убедиться, что volume смонтирован именно туда. Один коммит. Два часа отладки до него.
>> ИТОГ:
Игра живёт по адресу t.me/riveraid_bot/game — открывается прямо в Telegram, без установки. Можно поиграть прямо сейчас.
Что мне понравилось в этом проекте: минимум абстракций. Canvas рисует пиксели. Fastify отдаёт JSON. Telegram открывает HTML. Между идеей и рабочим результатом — один день и несколько сотен строк кода.
Иногда лучший способ изучить технологию — просто что-то с ней сделать.