CNN TürkSiber saldırganların yeni hedefi: Marketler | Bir tuşla tonlarca gıda çöpe gidebilir!The Jerusalem Post'They have too much to lose': Trump says he does not think China, Russia are helping Iran 'at all'PunchHow to check your name, home address on Nigeria’s new postcode systemESPNTransfer rumors, news: Barcelona, Real Madrid scout Erling Haaland at AnfieldRTP DesportoSporting defronta Lens na ChampionsInquirerMarcos: Pax Silica won’t displace indigenous communities, burial sitesInquirer EntertainmentWowie de Guzman figures in Batangas car accident, assures he’s OKCollider‘The Boys’ Star’s 100% RT Hidden Gem Officially Gets a Second Chance on NetflixSouth China Morning PostBritish Council to resume IELTS exams after 4 days of cancellations across ChinaWirtualna PolskaMieli monitoring, świadków i podejrzaną. I co? I nicThe RegisterUK Cabinet Office takes £7.8M hit to kill off recruitment systemRapplerFACT CHECK: Quezon City disputes claims of DILG fire truck, ambulance turnover
The Daily Newsstand · Free, Always
Tuesday, October 13, 2026

Кооп-бадминтон на двух телефонах с сонар-управлением, и зачем мне понадобилась картонка

Translate

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

Видео, где я играю сам с собой на двух телефонах. Картонка между телефонами там не просто так, про неё ниже.

Код по-прежнему пишет Claude, я придумываю, решаю и тестирую на своих iPhone и Mi 9. Разработка кооп-игры уместилась в одно длинное воскресенье и немного вечера понедельника.

Что получилось

Каждый телефон слушает ладонь своего игрока сам, своим динамиком и микрофоном. По сети идёт только высота ладони, одно число на шаг игры. Камера не нужна, ставить тоже ничего не надо, на айфоне это просто страница в Safari.

Игра называется SonaLob, это перекидка воланом между двумя ракетками, цель подкинуть волан как можно выше, но не задевая потолок. Сила броска напрямую зависит от резкости взмаха ладонью. В синглплэе одна ладонь водит обе ракетки, вдвоём у каждого своя. Подключиться можно в одной Wi-Fi или по коду из четырёх цифр, тогда хоть из другого города.

Игру друг против друга делать я не стал, счёт общий. Телефоны слышат ладонь по-разному: у старенького Mi 9 ракетка дрожит заметно сильнее, чем у айфона, а без чехла ещё хуже. В дуэли проигрывал бы тот, у кого телефон слабее, а не тот, кто хуже играет. Когда же играют вместе, этого никто не замечает. Да и сама идея мне больше нравится такая: двое людей с двух телефонов делают одно общее дело.

Сеть: как не ждать напарника

Свою ладонь телефон знает сразу, а ладонь напарника приходит по сети с опозданием. Если её ждать, ракетка начнёт отставать от руки, и это очень чувствуется. В сетевых файтингах эту задачу давно решают через rollback, его и взяли.

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

  2. Свой шаг телефон делает сразу.

  3. Чего он про напарника ещё не знает, угадывает: считает, что ладонь там же, где была в последний раз.

  4. Когда приходит настоящая ладонь за шаг N, телефон достаёт сохранённую копию партии на этом шаге и быстро пересчитывает всё до текущего. Копии держит за последние 3 секунды.

rollback на одном телефоне · три случая шага

rollback на одном телефоне · три случая шага

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

Шаги отсчитываются по часам сервера, старт назначается на общий момент. Ладони ходят напрямую между телефонами через WebRTC, а если напрямую не соединилось, через сервер. В каждом сообщении лежат все ладони, которые напарник ещё не подтвердил, поэтому потерянный пакет ничего не ломает.

Цифры с моей партии (айфон и Mi 9 в одной Wi-Fi): напрямую 10–30 мс туда-обратно, через сервер 50–80. Откатываться обычно приходилось на 2–4 шага. В конце обе партии сошлись до шага. Рекорд пары сервер принимает так же, как одиночный: переигрывает партию по двум записям ладоней и сверяет счёт.

Два сонара на одном столе

Со звуком в итоге было сложнее, чем с сетью. Два телефона рядом слышат друг друга.

Первую проблему мы поймали заранее, ещё до режима вдвоём. Если оба телефона пищат одними и теми же тонами, каждый принимает чужой писк за ладонь, которая висит над ним и никуда не уходит. С убранной рукой игра считала, что рука видна, 70% времени, а без соседа 30%. Поэтому вдвоём тоны поделены: один телефон пищит чётными, другой нечётными, и каждый слушает только свои. По журналам чужой писк теперь на 25–40 дБ тише своего. Заплатили за это громкостью (сигнал тише на 7 дБ) и дальностью: телефон видит на 0,9 м вместо 1,8. Ладонь висит в 10–20 см над экраном, так что разницы никто не заметит.

Вторая проблема тонами не лечится. Свой писк отражается от любой руки над телефоном, в том числе от чужой. На видео я играю двумя руками над двумя соседними телефонами, руки при этом в 30 см друг от друга. Айфон ещё как-то справлялся, а Mi 9 меня почти не слушался, его ракетки 80% времени лежали внизу. Похоже, он видел мою вторую руку.

Помог большой лист картона, поставленный стоймя между телефонами. До и после:

без картонки

с картонкой

чужой зонд тише своего, айфон

на 32 дБ

на 39 дБ

дрожь расстояния до ладони, айфон

12,5 мм

8,4 мм

дрожь расстояния до ладони, Mi 9

11 мм

7,6 мм

Mi 9 видит ладонь

87% времени

100%

ракетки Mi 9 лежат на дне

79% времени

10%

Если играют двое, картон не нужен, хватит сесть в метре друг от друга.

Ещё одна история про железо. Перед вечерними тестами я снял с Mi 9 чехол, и калибровка стала проходить раз из десяти. Сначала думал, что что-то сломал в коде, но журналы показали другое: без чехла телефон слышит свой писк на 4 дБ тише, а расстояние до ладони скачет примерно вдвое сильнее (12–14 мм вместо 6–8). Почему так, точно не знаю. Наверное, чехол немного направляет звук от нижнего динамика и гасит дребезг корпуса. Надел чехол обратно, и всё заработало как раньше.

Что ещё вылезло

Первая же партия вдвоём игралась, счёт шёл, но человечки на ракетках дёргались на месте, как персонажи, застрявшие в текстурах. До волана они не добегали, отбивала голая доска. Виноват оказался тот же rollback. После каждого пересчёта партия становится новой копией, а код рисования принимал её за новую игру и ставил человечков на стартовые места. В тесте на двух страницах это случилось 120 раз за 3 секунды. Сама игра при этом считалась правильно, ломалась только картинка.

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

С паузой похоже. Кто её нажал, тот называет номер шага, и оба телефона останавливаются на нём. Тот, что успел убежать вперёд, откатывается. Если напарник свернул игру или у него пропала сеть, у второго включается пауза.

Ссылки

Если будете пробовать вдвоём, садитесь подальше друг от друга или ставьте что-нибудь между телефонами. А если что-то пойдёт не так, долгое нажатие на номер версии на экране игр дает возможность сохранить логи, присылайте.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.