# 🐍 Змейка на Jetpack Compose Учебный пример простого Android-приложения для студентов: классическая игра «Змейка» на одном экране. Цель примера — показать, как устроено реальное Android-приложение на современном стеке (Kotlin + Jetpack Compose) без лишней сложности. ## Что внутри - Игровое поле-сетка 20×30 - Управление **свайпами** (вверх/вниз/влево/вправо) - Змейка растёт, когда съедает еду; ведётся счёт и рекорд за сессию - Столкновение со стеной или с собой = Game Over, **тап** — рестарт - Вся отрисовка — через Compose `Canvas`, игровой цикл — на корутине ## Стек | Что | Версия | |-----|--------| | Язык | Kotlin 2.0.20 | | UI | Jetpack Compose (BOM 2024.10.01, Material 3) | | Android Gradle Plugin | 8.13.2 | | Gradle | 8.13 | | compileSdk / minSdk | 36 / 24 | ## Как запустить ### Вариант 1: Android Studio (рекомендуется) 1. Открыть папку проекта в Android Studio (**File → Open**). 2. Дождаться Gradle Sync. 3. Подключить телефон по USB (с включённой *отладкой по USB*) или запустить эмулятор. 4. Нажать ▶ **Run**. ### Вариант 2: командная строка ```bash # нужен JDK 17+ и установленный Android SDK ./gradlew installDebug # соберёт и поставит приложение на подключённое устройство ``` > Файл `local.properties` с путём к SDK создаётся автоматически Android Studio > и **не** хранится в репозитории — у каждого свой путь. ## Структура проекта ``` app/src/main/ ├── java/com/example/snake/ │ ├── MainActivity.kt # точка входа: ComponentActivity + setContent { SnakeGame() } │ └── SnakeGame.kt # вся игра: состояние, игровой цикл, отрисовка, управление ├── res/values/themes.xml # тема приложения └── AndroidManifest.xml ``` 👉 **Главный файл для изучения — [`SnakeGame.kt`](app/src/main/java/com/example/snake/SnakeGame.kt).** Там по шагам видно идеи Compose: - состояние через `remember { mutableStateOf(...) }` — UI сам перерисовывается при его изменении; - игровой цикл через `LaunchedEffect { while(true) { delay(); step() } }`; - ввод через `Modifier.pointerInput { detectTapGestures / detectDragGestures }`; - рисование через `Canvas { drawRoundRect / drawLine }`. ## Управление | Действие | Жест | |----------|------| | Начать игру | свайп или тап | | Повернуть | свайп ↑ ↓ ← → | | Рестарт после проигрыша | тап по экрану | ## Этапы (ветки) Проект задуман как серия этапов — каждый в своей ветке, чтобы можно было сравнивать версии: - **`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-4`** — звук при поедании еды через **SoundPool**: короткий WAV в `res/raw/eat.wav` грузится один раз, играется при каждом съедании (низкая задержка). Смотри настройку `SoundPool` и `soundPool.play(...)` в `step()`; освобождение ресурса — в `DisposableEffect`. - **`snake-stage-5`** — анимация поедания: в момент укуса на месте еды расходится затухающее кольцо. Смотри `Animatable` (`popProgress` 0→1), запуск анимации в `step()` и отрисовку кольца в `drawBoard()`. - **`snake-stage-6`** — пауза: тап по полю во время игры ставит/снимает паузу (свайпы по-прежнему рулят направлением). Смотри флаг `paused`, условие в игровом цикле и оверлей «ПАУЗА». Идеи для следующих этапов: выбор размера поля, экран настроек, светлая тема.