Изометрическая ферма на чистом JavaScript (ES-модули). Рисует PixiJS (WebGL), а логика, движок и скелетная анимация — свои.
Модули не работают через file://, поэтому нужен любой локальный веб-сервер:
tools\run-local.cmd— двойной клик (нужен Node.js или Python), откроется http://localhost:8080- или
npm run dev
Полезные параметры адреса:
?debug— FPS, время кадра, фризы, уровень качества и масштаб рендера?quality=low|mid|high— принудительно выбрать качество (проверка поведения на слабом телефоне)
Все игроки начинают с одной карты — assets/map.json. Редактировать её:
- Запустить
tools\editor.cmd(нужен Node.js) — откроется http://localhost:8080/editor. - Левая кнопка мыши — рисовать выбранным инструментом (трава, тропинка, вода, грядка, деревья,
камни, лес, дом, колодец, старт призрачка, ластик, перенос). Правая кнопка — двигать карту,
колесо — масштаб,
[]— размер кисти, Ctrl+Z — отмена, Ctrl+S — сохранить. - «Сохранить» записывает
assets/map.jsonпрямо в папку проекта. Потом — коммит и пуш (push.cmd).
Редактор открывается только с этого компьютера (localhost) и в сборку dist для игроков не попадает.
Жёлтая рамка — стартовый участок: дом, колодец, старт и хотя бы одна грядка должны быть в нём.
После изменения карты у игроков сохраняется прогресс (монеты, уровень, участки, рюкзак),
а деревья, камни, тропинки и постройки становятся как на новой карте.
npm install
npm run build # → dist/: один минифицированный бандл, CSS, index.html, картинки
npm run preview # открыть собранную версию на http://localhost:8080
В бандл вшиты список картинок, иконок и стартовая карта: игра не делает за ними отдельных запросов.
Папка dist/ в репозиторий не попадает: при каждом пуше в main GitHub Actions сам собирает игру и публикует её на GitHub Pages (.github/workflows/pages.yml). Адрес: https://matarener.github.io/FarmGames/
- Адрес игры — GitHub Pages (выше) или любой другой HTTPS-хостинг с содержимым
dist/. - В @BotFather:
/newapp(или/mybots → Bot Settings → Menu Button) и укажите адресindex.html. - Внутри Telegram игра сама разворачивается на весь экран, отключает закрытие свайпом вниз, учитывает вырезы экрана и сохраняет прогресс в CloudStorage аккаунта (плюс localStorage).
index.html, style.css точка входа и интерфейс (mobile-first, отдельные правила для планшета и ПК)
src/main.js сборка всего вместе, экран загрузки, прогрев, запуск игрового цикла
src/engine/ свой движок
Game.js цикл кадров, пауза в фоне, реже кадры в простое
Renderer.js размер холста, плотность пикселей, видимая область мира
Camera.js панорама, зум к точке, инерция, границы
Input.js тап / перетаскивание / щипок / колесо / наведение / WASD
Perf.js мощность устройства, качество графики, 30 FPS на слабых, замер фризов
Iso.js изометрия 2:1 (тайл 64×32)
Pathfinding.js A* на типизированных массивах
Sprite.js спрайты из кода, затемнение, загрузка картинок, ГПСЧ
Audio.js звуки и музыка, синтезируются на лету (без файлов)
src/skeleton/ своя скелетная анимация
Skeleton.js кости (аффинные матрицы), слоты, скины, порядок отрисовки
Animation.js ключевые кадры, кривые, события, плавное смешивание анимаций
src/game/
data.js все таблицы и баланс: культуры, растения, предметы, дом, цены
World.js карта: клетки, объекты, участки 10×10, туман, сохранение разницы
Farm.js правила фермы: тапы, действия, рост, урожай, рынок, рюкзак
PixiScene.js отрисовка всего мира через WebGL (PixiJS), атласы текстур
artSprites.js загрузка картинок художника (assets/art) и иконок
shore.js берег пруда (рисуется кодом поверх текстуры воды)
Player.js, ghost.js персонаж-призрачок: путь, очередь до 6 действий, кости и анимации
Mover.js режим «Переставить»: дом, колодец, грядки, тропинки, свои растения и постройки
placed.js свои постройки из рюкзака (поливалки, потом декор и здания): поставить, убрать, перенести
storeAll.js «Убрать всё»: свои вещи с карты разом в рюкзак (чистые функции, группы — STORE_ALL)
sprinklers.js поливалки: какие клетки поливают (сам полив — beds.js growBed)
beds.js грядки: рост и полив, покупка (цена, предел по уровню), грядка в рюкзаке
buildData.js здания с крафтом: здания (чертёж, материалы, время стройки), новые товары, рецепты
buildRules.js правила зданий (чистые функции): чертёж, стройка, очередь крафта, ускорение
houseRules.js улучшение дома по времени (чистые функции): начать, кончилось, ускорить
buildings.js здания и дом в игре: леса и здание на карте, окно здания, «+N» за готовое, полоски
flora.js, wild.js деревья и кусты: плоды, рост; дикая трава, кусты и саженцы
inventory.js рюкзак: чистые функции над состоянием
planting.js посадка культур и саженцев: чем платить, порядок и фильтры в окне выбора
questData.js таблицы заданий: сюжет и ветки, задания дня/недели/месяца, события по датам
questRules.js правила заданий (чистые функции): счёт, награды, смена дня, перенос старых сохранений
quests.js задания в игре: тосты, звуки, опыт по событиям правил
giftData.js подарки: разделы окна, дорожка ежедневных подарков на 30 дней
giftRules.js правила подарков (чистые функции): какой день, забрать, смена дня
gifts.js подарки в игре: звук, радость призрака, сохранение
wheelData.js колесо фортуны: сектора с призами и шансами, цены вращений
wheelRules.js правила колеса (чистые функции): сколько вращений осталось, какой сектор выпал
wheel.js колесо в игре (вращение и щелчки рисует окно в UI.js)
orderData.js доска заказов: сколько заказов, размер, награда, ожидание, заказчики
orderRules.js правила заказов (чистые функции): что просят, сдать, отказаться, позвать сразу
orders.js заказы в игре: звук, опыт, счётчики заданий «Продай…» и «Заработай…»
hints.js стрелка-подсказка к заданию на карточке
bars.js полоски времени роста
Save.js localStorage + Telegram CloudStorage (с нарезкой на части)
src/ui/UI.js HUD, всплывающие меню, окна дома, рынка (с доской заказов), рюкзака, заданий, подарков, колеса, настроек
src/editor/MapEditor.js редактор карты (только локально)
src/telegram/ обёртка над Telegram WebApp API
assets/ картинки художника и стартовая карта — см. assets/README.md
tools/ локальный сервер, сборка, нарезка картинок, бот баланса,
проверка правил (node tools/test-quests.mjs, test-gifts.mjs,
test-wheel.mjs, test-orders.mjs, test-planting.mjs, test-paths.mjs, test-sprinklers.mjs,
test-store-all.mjs, test-builds.mjs, test-beds.mjs)
docs/GDD.md геймдизайн-документ
Правила игры (Farm, flora, wild, inventory, quests, World) отделены от звука и отрисовки, время
и случайность передаются параметрами, контент — в таблицах data.js: так их потом можно перенести
на сервер.
Сюжет и пять веток (Огород, Рыбалка, Лес и сад, Стройка, Торговля) идут параллельно, в каждой
открыто одно задание. С 3 уровня добавляются задания дня, недели и месяца (сброс по московскому
времени) и события по датам. Новое задание, ветка или событие — это строка в questData.js.
Окно заданий открывается кнопкой «Задания» в нижнем меню (дом — в «Ещё»). Оно устроено как рюкзак:
разделы (Основные, День, Неделя, Месяц, Событие) — колонкой слева, и они видны и у открытого задания,
так что из любого задания, в том числе открытого с карточки на экране, можно перейти к любому списку.
На экране до трёх заданий: закреплённые игроком и текущее задание сюжета.
С ?debug в адресе в «Настройках» есть кнопки «+1 день», «+7 дней» и «Событие» для проверки.
Не объект на карте, а кнопка под монетами: она светится, пока есть подарок, который можно забрать,
и пропадает, когда забирать нечего. Окно «Подарки» всегда открывается из «Ещё». В окне разделы
«Ежедневные», «От друзей», «Приглашения», «События»; пока работают только «Ежедневные».
Ежедневные — дорожка из 30 дней входа: раз в день (новый день в 00:00 по Москве, как у заданий)
забирается подарок следующего дня, каждый 7-й день — кристаллы, 30-й — сундук с кристаллами,
пропущенные дни не сгорают, после 30-го дорожка начинается заново. Награды — giftData.js.
С ?debug в «Настройках» кнопка «Подарки заново» сбрасывает дорожку, «+1 день» — следующий день.
Кнопка под подарком светится, пока есть бесплатное вращение на сегодня; окно всегда открывается
из «Ещё» → «Колесо». Бесплатно — раз в день, за монеты — 5 раз в день (цена растёт), за кристаллы —
без ограничений. Сектор решают правила (wheelRules.js, случайность параметром), окно докручивает
колесо до него. Призы, шансы и цены — wheelData.js. С ?debug — кнопка «Колесо заново».
Грядки не копают: их покупают на рынке (раздел «Постройки», грядка там первая) и получают за задания
«Огорода». Купленная грядка ложится в рюкзак, «Поставить» ставит её на траву, как дорожку: каждое нажатие —
готовая грядка, без энергии. Кнопка «Грядки» справа (над «К фермеру», цифра — сколько грядок в рюкзаке)
включает расстановку, а если в рюкзаке пусто — открывает рынок сразу на грядке.
Каждая следующая грядка дороже, а сколько их можно купить, зависит от уровня (2 + 2 за уровень, не больше 40):
считаются все свои грядки, на ферме и в рюкзаке. Предел мешает только покупке: грядки-награды даются и сверх
него, а в старых сохранениях остаются все вскопанные. Цены и предел — BEDS в data.js, правила —
beds.js (bedLimit, bedPrice, buyBed). Задания про грядки и достижение «Огородник» считают, сколько грядок
есть (их даёт мир: ctx.stats у заданий, ctx.bedsAll у достижений), а не события.
Поливалки продаются на рынке в разделе «Постройки», ставятся из рюкзака кнопкой «Поставить» (или
«Ещё» → «Переставить» → нажать на пустую траву): первое нажатие на клетку — предпросмотр, голубым
видно, какие клетки она польёт, второе нажатие или «Поставить» — ставит. Грядка в зоне поливалки
поливается сама, как только просит воды, и за время отсутствия тоже. Виды, клетки полива и цены —
SPRINKLERS в data.js. Все свои постройки хранятся в st.placed (placed.js): новая постройка —
это строка в OBJECTS с item и предмет в ITEMS с place: 'obj'; свои правила (оплата, стройка,
запрет убрать) подключаются через registerPlaced.
«Ещё» → «Переставить» → «Убрать всё» (кнопка видна, пока ничего не выбрано). Окно показывает группы
своих вещей с числом и переключателями: дорожки, пустые грядки, пруды (с камышом, рогозом и камнями),
починенный колодец, свои взрослые деревья и кусты (висящие плоды — в рюкзак), постройки и растущие ростки
(выключены: вернутся саженцами и начнут расти заново). Дом, грядки с посадками, сломанный колодец, дикое,
закрытые участки и то, с чем сейчас работает призрачок, остаются. Если после уборки не останется ни пруда,
ни колодца, окно предупреждает, что воду будет негде набрать. После уборки режим «Переставить» остаётся:
пустая трава — поставить обратно.
Пустую грядку и починенный колодец можно убрать и по одной («В рюкзак» в «Переставить»): предметы
«Грядка» и «Колодец» (раздел «Постройки»). Грядки ставятся обратно, как дорожки (каждое нажатие на траву —
готовая грядка), колодец — как постройка. Правила — beds.js (storeBed/placeBed) и well.js; пока
колодец в рюкзаке, при загрузке он сам не возвращается.
Группы — STORE_ALL в data.js, правило — storeAll.js (каждая вещь убирается тем же правилом,
что и по одной). Новая своя постройка через placed.js попадает в «Постройки» сама; отдельная группа
(например, «Декор») — строка в STORE_ALL и одна строка в groupOf.
Рынок → «Заказы», со 2 уровня. На доске 3 заказа от соседей: 1–3 товара (культуры по уровню, рыба
после задания «Рыбалка», плоды своих деревьев и кустов) за монеты в 1,5 раза дороже рынка и опыт.
Сданный заказ засчитывается как продажа на рынке. После сдачи новый покупатель приходит через 5 минут,
после отказа — через 15, ожидание можно пропустить за кристаллы. Цифра на кнопке «Рынок» — сколько заказов
уже можно сдать. Все числа — orderData.js. С ?debug — кнопка «Заказы заново».
Кухня (с 3 уровня), столярная мастерская (4), кузница (5) и камнерезная мастерская (6) — по одной на ферму,
2×2 клетки, как дом. Чертёж покупается на рынке в «Постройках», ставится из рюкзака кнопкой «Построить»:
материалы списываются, и на месте стоит это же здание в лесах, пока идёт стройка (полоска над ним,
«Достроить сейчас» за кристаллы). Готовое здание открывает своё окно: рецепты сеткой и очередь на 3 места — товары делаются по
одному, готовое забирается нажатием на здание (над ним пузырь с галочкой). Ждущий товар можно отменить
(продукты вернутся), тот, что делается, — доделать за кристаллы. Здание можно убрать в рюкзак и поставить
снова: очередь не теряется. Здания, товары и рецепты — buildData.js, правила — buildRules.js
(состояние st.builds), задания — ветка «Мастерские» в questData.js.
Улучшение дома идёт по времени (time в HOUSE, data.js: до 2 уровня — 3 мин, до 3 — 20 мин, до 4 — 1 ч,
до 5 — 3 ч). Ресурсы списываются сразу, дом стоит в лесах (картинка house_up_<уровень>, полоска над ним),
а энергия, лейка и участки остаются прежними, пока стройка не кончится. В окне дома — сколько осталось и
«Достроить сейчас» за кристаллы. Правила — houseRules.js (состояние st.houseUp).
- Вся графика — картинки художника в атласах видеокарты; игра открывается только когда всё загружено и прогрето (~2 с кадров за экраном загрузки), чтобы в игре не было подгрузок.
- Земля каждого участка — одна сетка ромбов; объекты не перерисовываются, пока не изменились.
- Разрешение рендера ограничено по классу устройства (×1 / ×1.5 / ×2). Если кадр не укладывается в бюджет, FPS ограничивается до 30.
- В простое игра рисует реже, а в фоне останавливается полностью.
Как называются картинки, где лежат листы художника и как их нарезать — в assets/README.md.