CoOp:Anything
Search any game and see how much of it you can play with friends: every co-op mod, its stage, quality and community rating.
Свет и тени, настоящая баллистика, кооператив и рейтинговые бои. Играйте прямо в браузере — бесплатно.
Translation pending
GamesTypeScript · CSSGitHub @h5xde-devOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Кооперативный top-down шутер в духе BulletEcho: пули летят по-настоящему, свет и тени решают всё, а рассвет наступает один раз. Сайт: https://evntary.ru.
Одиночная игра работает целиком в браузере. Все сетевые режимы (комнаты по коду, кооператив, арены с друзьями, командные режимы, рейтинговые бои) ведёт наш авторитетный игровой сервер: браузер — только клиент. Вход через Яндекс ID нужен для рейтинга и для опыта на аккаунте; в комнаты можно и гостем.
| Обзор | Как в Bullet Echo: видно только то, что в конусе взгляда и в паре метров вокруг, стены перекрывают обзор. Всё остальное погружено во тьму, враги вне обзора не рисуются (и на миникарте тоже), а их выстрелы оставляют красные маркеры. |
| Солдаты | Модели из пака ассетов с процедурной анимацией: шаги по скорости, руки держат оружие через IK, отдача, реакция на попадание, падение при смерти. |
| Свет | Фонарь игрока — настоящий SpotLight с shadow map: стены отбрасывают реальные тени. В темноте врагов почти не видно, выстрелы и взрывы освещают комнату. |
| Пули | Реальное время полёта и падение урона по дистанции, пули останавливаются стенами. Пушка летит мимо — можно уклониться. |
| Физика | Свойки-бочки взрываются цепной реакцией, ящики и столы толкаются, обломки отлетают. |
| Режимы | Кооператив: 6–8 процедурных комнат за бронированными дверями, стартовая комната без врагов. На аренах «Склад», «Двор», «Бункер», «Лес», «Офис», «Порт», «Завод», «Катакомбы», «Окопы», «Лабиринт» (боты добирают до 2–8 бойцов, таблица на Tab): Deathmatch — каждый сам за себя, 15 фрагов или 5 минут; Гонка вооружений — каждые 2 убийства дают следующее оружие (пистолет → ПП → дробовик → винтовка → снайперка), кто прошёл лестницу — победил; Соревнование — раунды до последнего выжившего, старт с пистолетом и $800, закупка на B в первые 15 с раунда, деньги за убийства и итог раунда, выжившие сохраняют снаряжение. |
| Новые режимы | Заражение — через 10 с один из бойцов заражён (на каждые 4 — ещё один): только нож, +50% здоровья, быстрее, без фонаря; убитый человек через 3 с встаёт заражённым, люди не возрождаются; продержались 3 минуты — победа людей. Эвакуация — кооп на арене: 5 грузов у дальних точек под охраной, нести к точке эвакуации (груз замедляет, раненый роняет), подкрепления охраны каждые 45 с, за 6 минут нужно вынести хотя бы половину (всё — победа сразу), павшие возвращаются у точки через 15 с. Сопровождение VIP — раунды по 90 с: атака ведёт VIP (пистолет, броня, +60% здоровья) к точке, защита мешает; без возрождения внутри раунда, стороны меняются каждый раунд, до 4 побед. Сужающаяся зона — одна жизнь, на старте нож и пистолет, остальное оружие разбросано по карте; круг пять раз сжимается (30 с держится, 18 с сжимается), снаружи темно и 9 урона в секунду; последний выживший побеждает. |
| Командные режимы | Командный бой — синие против красных до 30 фрагов, без огня по своим, обзор союзника общий. Захват флага — унести чужой флаг к себе, пока свой на базе; упавший флаг возвращают касанием; три захвата — победа. Закладка бомбы — раунды: синие закладывают бомбу на A или B (зажать E, 3 с), красные обезвреживают (E, 5 с); бомба взрывается через 35 с; закупка и деньги как в «Соревновании», пять раундов — победа. Волны — кооп против волн охраны, которые растут и идут на шум и свет; погибшие возвращаются после волны. |
| Фонарь | Включён — обзор 24 м, но ИИ замечает издалека, а луч виден врагам сквозь темноту. Выключен — обзор 13 м, зато скрытно. Боты гасят фонарь, когда подкрадываются. |
| Гранаты | G — бросок к курсору по дуге, отскок от стен, взрыв через 2 с, стены защищают. Красный круг показывает зону поражения. Боты закидывают гранатами тех, кто прячется. |
| Уровни | Темы комнат — склад, офис, двор, бункер, ночной лес (густые кусты, стены — линии деревьев), поле с зигзагами окопов и мешками с песком: свой пол, свет, разметка и набор укрытий (машины, паллеты, бочки, электрощиты, покрышки, бетонные блоки). Колонны в больших комнатах. Неподвижные укрытия никогда не перекрывают проход. |
| Тактика | Лампы простреливаются: пуля игрока гасит свет, место становится тёмным и для ботов. Дымовая граната (Q, затем G) ставит облако на 14 с — сквозь него не видят ни игроки, ни боты, видны только трассеры. Светошумовая ослепляет всех, кто видит вспышку: дольше, если смотреть на неё. Коктейль Молотова разбивается там, где упал (или о стену), и пол горит 7 с: кто в огне — горит и после, бочки с топливом в пламени взрываются, огонь освещает место для ботов, а стены его не пропускают. В кустах (дворы, арена «Двор») не видно того, кто стоит, идёт шагом или сидит, — пока не выстрелит или не побежит. Окопы (комнаты-«поля» в коопе, арена «Окопы») замедляют на 15%; пригнувшегося в окопе не видно, а пули стрелка снаружи окопа издалека (больше 5 м) бьют того, кто в окопе, на 35% силы; охрана ждёт в окопах пригнувшись. FPV-дрон (X; у инженера один на жизнь, в магазине $900): солдат стоит, дрон летит над укрытиями 12 с. Управление как у настоящего квадрокоптера: мышь разворачивает нос (с ограниченной скоростью поворота), W/S — тангаж вперёд/назад, A/D — крен вбок относительно носа; дрон набирает скорость до ~60 км/ч, по инерции скользит и тормозит, наклоняется в сторону движения, а в стену на полной скорости разбивается; ЛКМ или X — подрыв (4,5 м, 120 урона), села батарея — тоже взрыв. Дрон жужжит (его слышат боты), камера и обзор — с дрона; его можно сбить (30 hp, боты стреляют по дрону рядом), а ранение пилота рвёт связь; сбитый, разбитый о стену или потерявший связь дрон падает и взрывается там, где упал. |
| Бонусы | Аптечка, броня (поглощает 60% урона), усиленный урон, скорость, скорострельность, ПНВ (10 с видно далеко без фонаря, но вспышка слепит сильнее). Враги иногда роняют бонусы; на аренах предметы возвращаются через 18 с. Оружие подбирается, просто пройдя по нему, и исчезает с карты; погибшие роняют своё оружие (30 с). Переключение — 1–5. |
| Оружие | Пистолет, ПП, дробовик, винтовка, снайперка — у каждого свои темп, разброс, отдача и урон. |
| Враги | ИИ с патрулированием, реакцией на шум, поиском по последней известной позиции, стрельбой очередями и перемещением в укрытии. В темноте реагируют хуже. |
| Кооператив | Два и больше операторов на один объект. Матч ведёт игровой сервер: снимки состояния 20 Гц, предикт своего персонажа с откатом, интерполяция остальных. |
| Объекты (E) | Рубильник гасит или включает лампы в 13 м (простреленные остаются тёмными); ящик патронов — полный магазин и гранаты, откат 20 с; медпункт лечит, пока держите E (15 hp/с, запас 150 hp, восполняется); двери на аренах открываются и закрываются (держат пули и обзор, боты открывают сами). |
| Сброс снаряжения | Раз в минуту (в коопе — 90 с, в «Волнах» — 75 с) на парашюте падает ящик с красным дымом, место видно на миникарте. Зажать E на 2 с — топовый ствол и два бонуса; урон сбивает вскрытие. |
| Серии убийств | 3 подряд — радар на 8 с, 5 подряд (и каждые следующие 5) — миномётный удар: T ставит три мины по курсору, через 2 с свиста они падают. Смерть обнуляет серию. |
| Проволока, ракеты, мины | Колючая проволока замедляет вдвое и ранит, пули её пролетают; режется ножом или зажатой E. Осветительная ракета (граната, Q) 12 с освещает 9 м — там не спрятаться ни в кусте, ни в окопе, ни под маскировкой. Мины инженера (N, две на жизнь, $300 в магазине): взрываются под врагом, врагам видны только вблизи, расстреливаются. |
| Бонусы | Кроме аптечки, брони, урона, скорости, темпа и ПНВ: боеприпасы, регенерация (вне перестрелки), сверхщит, маскировка, радар. На каждой арене есть новые бонусы, в коопе — до двух на комнату; убитые на аренах иногда роняют бонус. |
| «Лабиринт» | Арена-лабиринт из окопов: тыловая и передняя линии зигзагом, ходы сообщения, тупики, два блиндажа (дверь, медпункт, патроны, рубильник), пулемётные гнёзда и ничейная земля с воронками и проволокой. Окопы теперь выглядят вырытыми: дощатые стенки, столбы, мешки с песком по брустверу. |
Боты в сетевой комнате. Переключатель «Боты в сетевой комнате» в меню, под числом бойцов на арене. Если боты включены, они появляются, только когда в комнате двое игроков или больше: создатель комнаты, который ждёт друзей, не попадёт в бой с ботами в одиночку. Когда остаётся один игрок, боты уходят. Если переключатель выключен, в комнате играют только люди. Выбор запоминается. В одиночной игре боты есть всегда, в рейтинговом бою их нет никогда.
В меню есть «Справка» (и в паузе): классы, режимы, оружие с характеристиками, бонусы, объекты и все клавиши. Под кнопками классов — карточка выбранного класса.
/play?room=КОД сразу заводит друга в комнату; её копирует кнопка под кодом и клик по коду в игре.Со входом через Яндекс: три задания дня и три задания недели (у каждого игрока свои, обновляются в полночь и в понедельник по Москве), достижения за всё время игры и косметика за них — камуфляжи (узор на форме бойца) и значки у имени, их видят все. Всё считает сервер по итогам онлайн-матчей; выполненное задание сразу даёт опыт. На экране итогов — награды матча (MVP, ангел-хранитель, тактик, тихий клинок, сборщик), выполненные задания и достижения.
| Клавиша | Действие |
|---|---|
WASD | движение по экрану: W вверх, S вниз, A/D влево-вправо; в паузе можно «по прицелу» (W к курсору, S от него) |
Shift | шаг: медленнее, тихо (шум 4 м) |
C | присед: ещё медленнее, бесшумно, точнее |
| мышь | прицел |
ЛКМ | огонь |
R | перезарядка |
F | фонарь вкл/выкл |
1–9 | оружие из подобранного (8 — нож, 9 — огнемёт) |
G | бросить выбранную гранату |
Q | сменить гранату: осколочная → дымовая → светошумовая → молотов |
E (зажать) | заложить / обезвредить бомбу |
Z / колёсико | метка для союзников |
V | инженер: поставить щит |
X | запустить FPV-дрон; в полёте ЛКМ или X — подрыв |
E | использовать: рубильник, ящик, дверь, медпункт, сброс, проволока |
N | инженер: поставить мину |
T | миномётный удар (серия из 5 убийств) |
B | магазин (соревнование, начало раунда) |
Tab | таблица счёта (арены) |
npm install --legacy-peer-deps # на этом Mac npm спотыкается о peer-дерево
npm run dev # http://localhost:5173 — соло работает и без сервисов
npm run dev:services # для сетевой игры и входа (см. «Архитектура»)
Если
npm installпадает сCannot read properties of null (reading 'edgesOut')— это баг npm 10 при разрешении peer-зависимостей. Флаг--legacy-peer-depsего обходит.
Модели, текстуры и звуки лежат в apps/web/public/assets/ (~2.7 МБ) и собираются из
библиотеки ассетов frontline скриптом:
FRONTLINE_ASSETS=~/frontline/assets npm run assets
Скрипт упрощает сетки, пережимает текстуры в WebP и сжимает геометрию meshopt.
Результат коммитится, поэтому деплой от frontline не зависит. Проверить, как
легли модели: /test/models.html, анимацию — /test/anim.html (на dev-сервере).
браузер ──https──▶ nginx ─┬─ статика: apps/web/dist (текущий релиз)
├─ /api, /auth, /callback, /rating ─▶ api :8090 (SQLite)
├─ /meta (WebSocket) ─────────────▶ meta :8091
└─ /game (WebSocket) ─────────────▶ game :8092
браузер ◀──UDP (WebRTC, 40000–40199)──────────────────────────▶ game
meta ◀── heartbeat ── game ── итоги матча ──▶ api
| Сервис | Что делает |
|---|---|
web (apps/web) | Сайт и игра: посадочная /, игра /play, рейтинг /rating. Соло считается в браузере, сетевые режимы — клиент сервера. |
api (apps/api) | Вход через Яндекс ID, сессии, профиль и настройки аккаунта, опыт, рейтинг Эло, история боёв, страница рейтинга для поисковиков. Единственный, кто работает с базой. |
meta (apps/meta) | Входная дверь онлайна: кто игрок (аккаунт или гость), создание комнаты, вход по коду, очередь рейтинговых боёв, реестр игровых серверов. Отвечает подписанным тикетом на место в комнате. |
game (apps/game) | Ведёт матчи всех режимов той же симуляцией, что и браузер (packages/shared): разминка и старт матча, боты, места при обрыве, проверка ввода, итоги и опыт → api. |
shared (packages/shared) | Симуляция, протоколы, правила прогресса. Чистый TypeScript без DOM. |
node-kit (packages/node-kit) | Общее для сервисов: настройки, HTTP, тикеты (HMAC), остановка. |
Как идёт сетевая игра. Браузер открывает /meta, говорит, кто он, и просит комнату
(create), вход по коду (join) или рейтинговый бой (queue). Meta выбирает игровой
сервер, создаёт на нём комнату и выдаёт тикет: кто, в какую комнату, с каким классом и
цветом, хост или нет, на 2 минуты. С тикетом браузер открывает /game, получает карту и
дальше играет как клиент. Гость опознаётся случайным id вкладки, аккаунт — cookie входа.
Транспорт с игровым сервером.
Клиент интерполирует чужих бойцов со сдвигом ~110 мс, а своего предсказывает (с учётом оружия и класса) и сверяет со снапшотами. Сервер компенсирует лаг по пингу клиента (не больше 150 мс) и чистит ввод: длина стика не больше 1, никаких NaN, только известные покупки.
Обрыв связи. Место игрока держится 30 с: браузер сам просит у meta новый тикет и возвращается тем же бойцом. Если сервер закрыл комнату (пуста минуту, обновление), браузер показывает причину.
Рейтинговый бой. Очередь в meta: бой начинается сразу, когда набирается 6 игроков, или через 20 с после того, как в очереди появились двое. Deathmatch на случайной арене без ботов. Выбывший может вернуться за 30 с, иначе занимает последнее место; если в бою остался один игрок, через 20 с бой засчитывается. Рейтинг — многопользовательский Эло: каждый сравнивается с каждым по месту, K = 32 делится на число соперников, старт 1000.
npm install --legacy-peer-deps # на этом Mac npm спотыкается о peer-дерево
npm run dev:services # api :8090, meta :8091, game :8092; вход /auth/dev?name=… без Яндекса
npm run dev # Vite на :5173 проксирует /api, /auth, /meta, /game на сервисы
Секреты Яндекса для локального входа можно положить в apps/api/.env (в git не попадает):
YANDEX_CLIENT_ID=…
YANDEX_CLIENT_SECRET=…
YANDEX_REDIRECT=http://127.0.0.1:5173/callback
Сервер 157.228.137.18, Ubuntu 24.04, nginx и certbot, Node 20.19+ (на сервере 20.20). Хост общий с другими сайтами: скрипты трогают только свой server-блок nginx.
Разовая настройка (deploy/setup.sh, идемпотентна, переводит и со старой схемы):
YANDEX_CLIENT_ID=… YANDEX_CLIENT_SECRET=… bash /var/www/northecho/deploy/setup.sh
northecho;/etc/northecho/env (права 640): секреты Яндекса, SERVICE_SECRET
для тикетов и внутренних вызовов, ORIGINS, путь к базе;sqlite3 .backup) рядом с ней перед миграцией схемы;northecho-api, northecho-meta, northecho-game (вместе — northecho.target)
и northecho-deploy.timer, останавливает старый northecho.service;deploy/nginx.conf.Автодеплой. Раз в минуту northecho-deploy смотрит ветку (main; другая — в
/etc/northecho/deploy.env). Если там новый коммит:
releases/<sha> — живой релиз не трогается;npm ci и сборка (типы, сайт, три сервиса) там же;current одним rename и перезапускает только изменившиеся сервисы;
игровой сервер перед остановкой даёт идущим матчам доиграть (до 120 с);/healthz у api, meta и game. Не ответили — возвращает прошлый релиз, а коммит
записывает в releases/.failed и больше не пробует (до нового коммита или FORCE=1);nginx -t прошёл) и сам скрипт.Хранятся три последних релиза. Логи:
journalctl -u northecho-deploy -f # деплой
journalctl -u 'northecho-*' -f # сервисы
Ручной деплой ветки: BRANCH=имя FORCE=1 /usr/local/sbin/northecho-deploy.
UDP-порты 40000–40199 должны быть открыты во входящих, если у хостинга есть свой файрвол.
apps/
web/ сайт и игра: render (Three.js), ui, game.ts (клиент и соло), net (meta, game-сервер)
api/ вход, аккаунт, опыт, рейтинг, история; SQLite
meta/ комнаты, коды, очередь, реестр игровых серверов, тикеты
game/ комнаты и матчи на сервере (Room), транспорт WebSocket + WebRTC
packages/
shared/ детерминированная симуляция, протоколы, проверка ввода, правила прогресса
node-kit/ настройки, HTTP, тикеты, остановка — общее для сервисов
deploy/ nginx, systemd, setup.sh, deploy.sh
tests/ сервисы целиком без браузера
tools/ проверка битых символов, запуск сервисов для разработки
Физика и правила боя живут в плоскости XZ — как 2D, но в 3D-сцене. Это даёт детерминированную симуляцию и дешёвые расчёты; одна и та же симуляция работает в браузере и на сервере.
npm run typecheck # все пакеты и сервисы
npm run check:text # битые символы (U+FFFD) в исходниках — входит в сборку
npm run test:services # api + meta + game без браузера: комната по коду, лобби и старт,
# переподключение, чистка ввода, рейтинговый бой, опыт, остановка
npm run test:online # два браузера: комната, вход по коду без чёрного экрана, движение,
# предикт против сервера, старт хостом, переподключение
npm run test:server # рейтинговый бой в браузерах: очередь, бой по UDP, рейтинг
npm run test:arenas # арены и режимы на ботах, дрон, бонусы, прогресс (соло)
test:services поднимает сервисы сам (сначала npm run build). Браузерные тесты ходят на
запущенные npm run dev:services и npm run dev (адреса — переменные ONLINE_URL,
SERVER_TEST_URL, DM_URL).
Профиль кадров: node apps/web/tools/perf.mjs [арена] [режим] [секунды] (PERF_CPU=4
замедляет процессор вчетверо). Всё, что появляется в бою, прогревается в Renderer.warmup.
Vite · TypeScript · Three.js · Node.js (ws, node-datachannel, better-sqlite3) · npm workspaces · systemd · nginx.