From 64b47a55362cb3e8ec420186e99608ca39572600 Mon Sep 17 00:00:00 2001 From: george Date: Wed, 17 Jun 2026 18:40:05 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D0=B0=20=D1=8D=D1=82=D0=B0=D0=BF=D0=BE=D0=B2=20=D0=B2=20README?= =?UTF-8?q?=20+=20=D0=B0=D0=BA=D1=82=D1=83=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - раздел «Этапы» переписан таблицей: что меняется / приём / где в коде - «Что внутри» и «Управление» приведены к итоговой версии (тор, пауза) Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 76 +++++++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index f98e19c..ab255ce 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,18 @@ Android-приложение на современном стеке (Kotlin + Jetpack Compose) без лишней сложности. -## Что внутри +## Что внутри (итоговая версия на `main`) -- Игровое поле-сетка 20×30 -- Управление **свайпами** (вверх/вниз/влево/вправо) -- Змейка растёт, когда съедает еду; ведётся счёт и рекорд за сессию -- Столкновение со стеной или с собой = Game Over, **тап** — рестарт +- Игровое поле-сетка 20×30, управление **свайпами** +- Змейка растёт и **ускоряется** с ростом счёта; ведётся счёт, **уровень** и **рекорд** (сохраняется между запусками) +- **Бонус-еда** с таймером даёт больше очков; **препятствия** добавляются с каждым уровнем +- Границы поля **телепортируют** на противоположную сторону (тор); смерть — от самой себя и от препятствий +- **Звук** и **анимация-вспышка** при поедании, **пауза** по тапу - Вся отрисовка — через Compose `Canvas`, игровой цикл — на корутине +> Каждая фича добавлялась отдельным этапом-веткой — см. раздел [Этапы](#этапы-ветки) +> ниже: там видно, что именно меняется на каждом шаге. + ## Стек | Что | Версия | @@ -63,50 +67,32 @@ app/src/main/ |----------|------| | Начать игру | свайп или тап | | Повернуть | свайп ↑ ↓ ← → | +| Пауза / продолжить | тап по полю во время игры | | Рестарт после проигрыша | тап по экрану | ## Этапы (ветки) -Проект задуман как серия этапов — каждый в своей ветке, чтобы можно было -сравнивать версии: +Проект построен как серия этапов: каждый — отдельная **ветка**, добавляющая +**одну** фичу поверх предыдущего. Между соседними ветками — маленький diff, +поэтому легко увидеть, что именно меняется и какой Android/Kotlin-приём за это +отвечает. `main` = последний этап (вся игра целиком). -- **`snake-stage-1`** — базовая рабочая игра. -- **`snake-stage-2`** — ускорение: змейка ускоряется с каждой съеденной едой - (задержка шага 150 → 60 мс), на экране индикатор «Скорость». Смотри - функции `stepDelay()` / `speedLevel()` и игровой цикл в `SnakeGame.kt`. -- **`snake-stage-3`** — рекорд сохраняется между запусками через **Jetpack - DataStore** (`ScoreStore.kt`): чтение — `Flow`, запись — suspend-функция, - диск не блокирует UI. Смотри `LaunchedEffect` для загрузки рекорда и - `scope.launch { ScoreStore.saveBest(...) }` при новом рекорде. +| Этап (ветка) | Что меняется | Ключевой приём | Где в коде | +|---|---|---|---| +| **`snake-stage-1`** | Базовая игра: поле 20×30, рост змейки, счёт, рекорд за сессию, свайпы, Game Over об стену/себя | Compose `Canvas`, игровой цикл на корутине, состояние в `remember` | весь `SnakeGame.kt` | +| **`snake-stage-2`** | Змейка ускоряется с ростом счёта (150→60 мс), индикатор «Скорость» | задержка шага пересчитывается из состояния | `stepDelay()`, `speedLevel()` | +| **`snake-stage-3`** | Рекорд **сохраняется между запусками** | Jetpack **DataStore** (`Flow` на чтение, `suspend` на запись) | `ScoreStore.kt`, загрузка в `LaunchedEffect` | +| **`snake-stage-4`** | **Звук** при поедании еды | **SoundPool** + `res/raw/eat.wav`, очистка в `DisposableEffect` | `soundPool.play(...)` в `step()` | +| **`snake-stage-5`** | **Анимация-вспышка** (кольцо) в момент укуса | **`Animatable`** (0→1) + `drawCircle` | `popProgress`, `drawBoard()` | +| **`snake-stage-6`** | **Пауза** по тапу во время игры | флаг `paused` в условии игрового цикла | `detectTapGestures`, оверлей «ПАУЗА» | +| **`snake-stage-7`** | **Бонус-еда** с таймером (1 из 4), +3 очка, золотая, исчезает по времени | таймер в «шагах» (учитывает паузу) + `drawArc` | `bonusFood`/`bonusStepsLeft`, `step()`/`drawBoard()` | +| **`snake-stage-8`** | **Препятствия и уровни**: каждые 5 очков +порция стен; врезался — Game Over | генерация на `Set`, коллизии, прогрессия | `obstacles`/`level`, `addObstacles()` | +| **`snake-stage-9`** | **Сквозь границы (тор)**: уходишь за край — появляешься с другой стороны | модульная арифметика координат `% COLS/ROWS` | `step()` | -- **`snake-stage-4`** — звук при поедании еды через **SoundPool**: короткий - WAV в `res/raw/eat.wav` грузится один раз, играется при каждом съедании - (низкая задержка). Смотри настройку `SoundPool` и `soundPool.play(...)` - в `step()`; освобождение ресурса — в `DisposableEffect`. +Посмотреть, что именно поменялось на этапе N, удобно diff'ом между ветками, +например для этапа 7: +```bash +git diff snake-stage-6 snake-stage-7 +``` -- **`snake-stage-5`** — анимация поедания: в момент укуса на месте еды - расходится затухающее кольцо. Смотри `Animatable` (`popProgress` 0→1), - запуск анимации в `step()` и отрисовку кольца в `drawBoard()`. - -- **`snake-stage-6`** — пауза: тап по полю во время игры ставит/снимает - паузу (свайпы по-прежнему рулят направлением). Смотри флаг `paused`, - условие в игровом цикле и оверлей «ПАУЗА». - -- **`snake-stage-7`** — бонус-еда с таймером: иногда (1 из 4 при поедании - обычной еды) появляется золотая еда на ~36 шагов и даёт +3 очка; вокруг - неё рисуется дуга-таймер, по истечении она исчезает. Время считается в - шагах игры, поэтому пауза учитывается автоматически. Смотри `bonusFood` / - `bonusStepsLeft`, логику в `step()` и отрисовку (`drawArc`) в `drawBoard()`. - -- **`snake-stage-8`** — препятствия и уровни: каждые 5 очков — новый уровень, - на поле добавляется порция серых стен; врезался в стену — Game Over. Еда и - бонус не спавнятся в препятствиях, новые стены не ставятся вплотную к голове. - В шапке — «Уровень». Смотри `obstacles`/`level`, `addObstacles()`, проверку - коллизий и повышение уровня в `step()`. - -- **`snake-stage-9`** — сквозь границы (тор): змейка проходит сквозь край - поля и появляется с противоположной стороны; смерть остаётся только от - самой себя и от препятствий. Реализовано %-арифметикой по координатам - головы в `step()`. - -Идеи для следующих этапов: два игрока, выбор размера поля, экран настроек. +Идеи для следующих этапов: два игрока на одном экране, выбор размера поля, экран настроек.