Документация процесса разработки (docs/DEVLOG.md)

- этапы: ТЗ, реализация, среда проверки, автотесты, визуал, баги, публикация
- таблица инструментов с версиями и командами установки
- найденные автотестом баги и выводы
- гигиена секретов (отзыв токена, чистка remote)
- как развивать игру дальше
This commit is contained in:
2026-08-27 06:13:00 +00:00
parent a90123be3b
commit 34c93b1229
2 changed files with 179 additions and 0 deletions
+4
View File
@@ -24,6 +24,10 @@
- Звуки на WebAudio, вибрация на телефоне
- Вся графика нарисована на Canvas — внешних ресурсов нет
## Документация
[📋 Процесс разработки](docs/DEVLOG.md) — этапы (ТЗ → прототип → автотесты → публикация), инструменты, найденные баги, гигиена секретов и как развивать игру дальше.
## Запуск
Просто открой [index.html](index.html) в браузере (десктоп или телефон). Для локальной разработки:
+175
View File
@@ -0,0 +1,175 @@
# Процесс разработки
Как игру «Рыбалка» спроектировали, собрали, проверили и опубликовали. Документ описывает этапы, инструменты и повторяемые команды — чтобы любой (включая вас через полгода) мог воспроизвести и продолжить процесс.
```
ТЗ → макет-прототип → среда проверки → автотесты → визуал → баги → публ. → поддержка
1 2 3 4 5 6 7 8
```
---
## Этап 1. Требования и дизайн (ТЗ)
**Исходное ТЗ:** браузерная игра про рыбалку, играбельная на телефоне.
Ключевые решения:
| Решение | Зачем |
|---|---|
| Один самодостаточный `index.html` (HTML+CSS+JS) | Нет сборки, зависимостей и бэкенда. Файл можно открыть где угодно: телефон, десктоп, статический хостинг |
| Вся графика на Canvas, без внешних ассетов | Игра работает офлайн, грузится мгновенно |
| Портретная ориентация, управление одним пальцем | Все действия — тап/удержание по экрану, больших тач-мишеней (кнопки ≥ 44 px) |
| HTML-оверлеи для меню/магазина/карточек, Canvas — только мир игры | Кнопки и текст резкие и доступные, игровой мир — 60 fps |
| WebAudio для звуков (без файлов), `navigator.vibrate` для тактильного отклика | Снова ноль внешних ресурсов; на телефоне — вибрация на клёв/рывки/обрыв |
| Прогресс в `localStorage` | Мобильная игра без аккаунтов и сервера |
Механика (единый цикл):
```
бросок (удержание = мощность) → ожидание → клёв («!») → подсечка (тап в окно)
→ вываживание (тяни/отпускай) → {улов / обрыв / срыв} → монеты → магазин
```
## Этап 2. Реализация
Структура `index.html` (все секции помечены комментариями в файле):
1. **Данные** — `SPECIES` (8 рыб: сила, редкость, цена, мин. дистанция), `RODS`, `LURES`. *Баланс игры крутится здесь.*
2. **Сохранение** — `save` + `localStorage` (монеты, снасти, коллекция, статистика).
3. **Холст** — масштабирование под `devicePixelRatio`, пересчёт layout'а при `resize`.
4. **Звук** — генеративный WebAudio: 12 эффектов из осцилляторов и шума.
5. **Состояния** — машина из 9 состояний: `MENU → IDLE → CHARGE → CAST → WAIT → APPROACH → BITE → REEL → SNAP/CARD → (IDLE)`.
6. **Физика вываживания** — `updateReel()`: напряжение шнура, дистанция, фазы «тянет/отдыхает». *Сложность крутится здесь.*
7. **Отрисовка** — небо, вода, рыбы-силуэты, лодка, поплавок, частицы, риплы, метры.
8. **Ввод** — Pointer Events (`pointerdown/up`), работают и палец, и мышь (важно для автотестов!).
9. **UI** — магазин, дневник, карточка улова.
## Этап 3. Среда проверки
Игра проверена в контейнере **Alpine Linux 3.24**. Минимальный набор инструментов:
| Инструмент | Версия (в нашем прогоне) | Зачем | Установка |
|---|---|---|---|
| Node.js | v24.18.1 | Статический анализ JS, запуск автотестов | `apk add nodejs npm` |
| Chromium | 151.0.7922 | Headless-браузер для настоящего прогона игры | `apk add chromium` |
| puppeteer-core | 25.9.0 | Управление Chromium через CDP (клики, скриншоты, чтение состояний) | `npm i puppeteer-core` (в `tests/`) |
| Noto Color Emoji | — | Чтобы в headless-скриншотах эмодзи рендерились как на телефоне | `apk add font-noto-emoji` |
| git | 2.54.0 | Публикация | `apk add git` |
| curl | — | Проверка API Gitea, smoke-запросы | уже есть в Alpine |
> В браузере на телефоне для *игры* не нужен ни один инструмент из таблицы — только сам браузер.
## Этап 4. Статическая проверка
Первый рубеж — компиляция кода настоящим движком (V8):
```bash
# вытащить JS из HTML и проверить синтаксис
node --check game.js
```
Ловит опечатки, несбалансированные скобки, висячие конструкции — до запуска в браузере.
## Этап 5. Автотесты (плейтест через CDP)
`tests/test.js` — сценарный автотест: headless Chromium загружает игру, а «игрок» управляет мышью (в браузере мышь порождает те же Pointer Events, что и палец). Тест читает и подталкивает внутренние состояния игры (`state`, `biteTimer`, `reel.d`) через `page.evaluate`, чтобы покрыть все ветки без ожидания случайностей.
**Что покрыто (21 проверка):**
- меню → старт → зарядка → бросок → ожидание
- клёв (ускорен через `biteTimer`) → подсечка → `REEL`
- **все три исхода вываживания**: улов → карточка, обрыв шнура (`SNAP`), срыв рыбы
- магазин: открытие, покупка удочки и приманки (с проверкой баланса и экипировки)
- дневник: рендер, пойманная рыба в коллекции
- **сохранение после перезагрузки страницы** (coins/снасти/статистика)
- ноль ошибок в консоли и `pageerror`
Запуск:
```bash
cd tests
npm install
node test.js # при необходимости: CHROMIUM=/путь/к/хромью
```
## Этап 6. Визуальная проверка
`tests/shots.js` — та же техника, но с фиксацией скриншотов каждого состояния (`screenshots/shot-*.png`). Скриншоты просматривает разработчик: ловит проблемы, которые не видны по коду и логам (сбившиеся метки, отсутствующие глифы, нечитаемые метры).
## Этап 7. Найденные баги (ради чего всё это)
Автотест + скриншоты поймали то, что ручное «посмотрел глазами» пропустило:
| # | Баг | Как нашли | Лечение |
|---|---|---|---|
| 1 | **Критический:** после поимки рыбы игра вешалась навсегда. `catchFish()` ставил `reel=null`, но кейс `REEL` в `updateGame()` на следующей строке читал `reel.holding` → исключение убивало цикл `requestAnimationFrame` | Автотест: второй бросок не происходил; `pageerror` показал точную строку | `if(state==='REEL'&&reel){...}` |
| 2 | Точка крепления лески висела в углу экрана в меню/карточке | Визуальный осмотр скриншотов | Условие отрисовки по состояниям |
| 3 | Рыбка-маркер не стояла на краю полосы «дистанция» | Визуальный осмотр | Полоса = оставшаяся дистанция, маркер на её конце |
| 4 | Глиф `✕` (U+2715) отсутствовал в некоторых шрифтах | Скриншот магазина | Заменён на `×` (U+00D7) |
**Вывод:** для игр с таймерами и случайностями автотест, который *управляет* временем и состоянием, покрывает за минуту то, что вручную ищут часами.
## Этап 8. Публикация в Gitea
Использовано: Gitea API (создание репозитория) + обычный `git push`.
```bash
# 1. Создать репозиторий (токен: Настройки → Приложения → Токены, права: Repository)
curl -X POST -H "Authorization: token <ТОКЕН>" -H "Content-Type: application/json" \
-d '{"name":"fishing-game","private":false,"auto_init":false}' \
https://git.shstk.ru/api/v1/user/repos
# 2. Наполнить ветку и запушить
git init -b main
git add -A
git commit -m "..."
git remote add origin https://git.shstk.ru/andrey/fishing-game.git
git push -u origin main # git попросит логин/пароль (или токен в URL — см. ниже)
```
Игра доступна анонимно по сырой ссылке:
`https://git.shstk.ru/andrey/fishing-game/raw/branch/main/index.html`
### 🔐 Гигиена секретов (проверено на себе)
1. **Токен — одноразовый.** Для публикации достаточно кратковременного токена с правами на репозиторий; после push его **отзываем** (в нашем случае — отозван, старый токен теперь отдаёт `401`).
2. **Токен не попадает в историю и конфиг.** Если передавать токен в URL (`https://user:TOKEN@host/...`), после push удалите его из конфига:
`git remote set-url origin https://git.shstk.ru/andrey/fishing-game.git`
3. **В репозиторий и в документы — только плейсхолдеры** (`<ТОКЕН>`), реальные секреты нигде не фиксируются.
## Этап 9. Поддержка и развитие
**Крутить баланс:** константы `SPECIES` / `RODS` / `LURES` в начале `index.html`; физика вываживания — в `updateReel()`.
**Цикл изменений:**
```bash
# 1. поправить index.html
# 2. прогнать автотест
cd tests && node test.js # ждём 21/21
# 3. (опционально) свежие скриншоты
node shots.js
# 4. закоммитить и запушить
git add -A && git commit -m "что изменилось" && git push
```
**Идеи развития** (по нарастающей сложности):
- ночной клёв (своя таблица рыб по времени)
- босс-рыба с механикой «разрывать и переподсекать»
- продажи улова / рыбный прайс по редкости
- мировая таблица лидеров (нужен простой бэкенд или Gitea-Actions с webhook'ом)
- офлайн-режим PWA (service worker в тот же файл)
---
## Шпаргалка: минимум инструментов по этапам
| Этап | Инструменты |
|---|---|
| Игра (конечный пользователь) | Любой браузер на телефоне/десктопе |
| Написание/изменение кода | Текстовый редактор (или LLM-сессия) |
| Статическая проверка | Node.js |
| Автотесты | Node.js + npm + Chromium + puppeteer-core |
| Визуальная проверка | Скриншоты из автотеста + Noto Color Emoji в headless |
| Публикация | git + curl + Gitea (токен с минимальными правами, отзываемый) |