Браузерная «Змейка» уже собрана: змейка ползает, яблоки появляются, рекорд сохраняется. Игра работает, но в неё играешь только ты. А что, если открыть ссылку другу и увидеть, как его змейка шевелится на том же поле? Или соревноваться, кто быстрее наберёт очков? Это уже сетевая игра. Покажем, как добавить мультиплеер в браузерную игру с помощью Supabase Realtime, не углубляясь в сложный бэкенд.
Содержание
Что такое Supabase Realtime
Supabase — это облачный бэкенд, который мы используем в курсе для аккаунтов, таблицы рекордов и аналитики. Одна из его частей называется Realtime. Если коротко, это шина сообщений в реальном времени: она позволяет браузерам обмениваться событиями мгновенно, без необходимости писать собственный сервер.
Технически Realtime работает поверх WebSocket — постоянного соединения между браузером и облаком. Вместо того чтобы каждый раз спрашивать сервер «есть что-то новое?», браузер держит открытый канал, и сервер сам присылает сообщения, когда они появляются. Это похоже на телефонный звонок вместо серии писем: не нужно ждать ответа, потому что линия всегда открыта.
Подробнее о возможностях можно почитать в официальной документации Supabase: supabase.com/docs/guides/realtime.
Игровая комната = канал
В Realtime есть понятие канала — это именованная комната, в которой сидят участники. Когда два игрока заходят в одну и ту же игру, они подключаются к одному каналу, например room:abc123. Все сообщения, отправленные в канал, получают остальные подписчики.
Для «Змейки» канал — это игровая сессия. Один канал = одна партия. Если друг открывает твою ссылку и попадает в тот же канал, его браузер начинает слушать события от твоего браузера и наоборот.
Канал помогает отделить разные партии друг от друга. Ты не хочешь, чтобы змейка случайного человека из интернета появилась у тебя на поле. Поэтому имя канала обычно генерируется из идентификатора игры, который передаётся в ссылке.
Как игроки обмениваются событиями
Вместо того чтобы каждый кадр пересылать всё игровое поле целиком, разумнее отправлять только события — краткие сообщения о том, что изменилось. Это экономит трафик и ускоряет реакцию.
В «Змейке» важные события могут выглядеть так:
- direction — игрок нажал стрелку и поменял направление змейки;
- moved — змейка сделала шаг;
- ate — змейка съела яблоко;
- died — игрок проиграл;
- spawned — появилось новое яблоко.
Каждое событие — это небольшой JSON-объект: кто отправил, что случилось, координаты и время. Например, событие о смене направления может содержать только идентификатор игрока и новое направление: вверх, вниз, влево или вправо.
Принимающая сторона получает это событие и обновляет состояние игры. Если в канал пришло сообщение «игрок 2 повернул вправо», твой браузер меняет направление чужой змейки. Отправлять всю змейку каждый раз не нужно. Достаточно сообщать об изменениях, а всё остальное каждый браузер считает сам.
Co-op и versus на примере «Змейки»
С появлением второго игрока возникает вопрос: а что они делают вместе? Есть два простых подхода.
Co-op, или совместная игра. Две змейки на одном поле, общая цель — собрать как можно больше яблок. Яблоки одни на всех, очки суммируются. Можно добавить правило: столкновение с хвостом друга не убивает, а только замедляет. Так игра получается дружеской и прощает ошибки.
Versus, или состязание. Те же две змейки, но цель — обогнать соперника. Кто первым наберёт 50 очков или кто выжил последним. Здесь уже важно, чтобы яблоки появлялись в одинаковых местах у обоих игроков, иначе один увидит яблоко, которого нет у другого.
Разница между режимами — не в технологиях, а в правилах. Технически канал и события одинаковые. Но versus требует более строгой синхронизации состояния, потому что игроки заинтересованы в том, чтобы игра была честной.
Кто решает, что «правильно»
В простой реализации каждый браузер получает события и сам пересчитывает игру. Это работает, пока все честные. Но если один игрок изменит скорость змейки у себя в браузере, его версия игры расходится с версией друга. В мультиплеере это называется проблемой авторитетного источника истины.
В идеале правильное состояние должен определять сервер. Supabase позволяет делать это через базу данных Postgres и Edge Functions: важные события сначала уходят на сервер, он проверяет их и рассылает уже проверенный результат. Например, сервер может решать, успел ли игрок съесть яблоко раньше соперника.
Для первого эксперимента можно обойтись без серверной логики. Но стоит понимать: чем больше игроков и чем важнее результат, тем нужнее авторитетный сервер. Иначе рано или поздно возникнут расхождения в состоянии у разных участников.
Главный враг — задержка
Даже при самом быстром интернете сообщения не летают мгновенно. Время, которое требуется сигналу, чтобы дойти до сервера и вернуться, называется пингом или latency. В России до европейского дата-центра это обычно десятки миллисекунд. Кажется, мало, но для быстрой игры это заметно.
Если ты нажал «вправо», а сообщение о повороте дошло до друга с задержкой, он увидит, что твоя змейка на мгновенье продолжила движение в старом направлении. Это выглядит как рывок или запаздывание.
С этим борются разными способами:
- Интерполяция. Вместо того чтобы резко телепортировать чужую змейку в новую точку, браузер плавно доводит её до полученных координат. Игрок видит не точную позицию, но движение выглядит естественно.
- Предсказание. Браузер друга двигает твою змейку по последнему известному направлению, пока не придёт следующее событие. Если предсказание совпало с реальностью, задержка незаметна.
- Регулярные тики. Вместо обработки каждого события отдельно игра работает короткими «тиками», например 10 раз в секунду. Все события внутри тика применяются одновременно. Это упрощает синхронизацию, но добавляет небольшую задержку в управлении.
Для «Змейки» с клеточным полем обычно достаточно тиковой модели. Змейка двигается не плавно, а скачками по клеткам, поэтому небольшая задержка воспринимается как естественный темп игры.
Как попробовать без кода
Прежде чем просить ИИ-ассистента написать мультиплеер, полезно проверить концепцию вручную. Вот простой план:
- Открой проект с «Змейкой» и подключи Supabase-клиент.
- Создай канал с уникальным именем, например
room:test-123. - Подпишись на события типа
player_movedи выводи их в консоль браузера. - Отправь из консоли тестовое событие:
{ type: 'broadcast', event: 'player_moved', payload: { player: 'me', x: 5, y: 7 } }. - Открой игру во второй вкладке с тем же каналом и убедись, что событие пришло.
- Добавь отправку направления при нажатии стрелок.
- Нарисуй вторую змейку на поле, используя координаты из входящих событий.
Этот минимум уже даст понимание, работает ли канал и насколько быстро приходят сообщения. После этого можно просить ИИ добавить авторитетный сервер, счёт, режимы co-op/versus и защиту от читерства.
Чек-лист «Мультиплеер работает»
- Два браузера получают друг от друга события.
- Каждый игрок видит чужую змейку на поле.
- Смена направления доходит до соперника.
- Яблоки и очки синхронизированы в режиме versus.
- При обрыве соединения игра не падает, а пытается переподключиться.
- В консоли нет ошибок при отправке и приёме событий.
- Ты понимаешь, кто в твоей игре решает спорные моменты: браузер или сервер.
Заключение
Supabase Realtime позволяет превратить одиночную браузерную игру в сетевую, не разворачивая собственный сервер. В основе лежат три идеи: каналы как игровые комнаты, события как короткие сообщения об изменениях и понимание того, что интернет всегда добавляет задержку.
Для «Змейки» можно начать с простого: два игрока в одном канале обмениваются событиями о поворотах и поедании яблок. Co-op делает игру командной, versus — соревновательной. Чтобы результат был честным, важно рано или поздно добавить авторитетный сервер, который решает спорные ситуации.
Мультиплеер — это не волшебная кнопка, а последовательное усложнение. Сначала пусть две змейки просто появляются на одном поле. Потом — счёт, режимы, защита от лагов. Каждый шаг превращает твою игру из одиночного упражнения в настоящий multiplayer-опыт.
Читай дальше
Все статьиНе просто статьи — тебя доведут до результата
В практикуме за 1999 ₽ рядом живая команда практикующих разработчиков и маркетологов: ведём по шагам до твоего работающего приложения. Не «ролики и сам разбирайся» — помогаем на каждом затыке.
Перейти к практикуму