Иногда при поедании обычной еды появляется золотая бонус-еда на ограниченное время и даёт больше очков. - bonusFood/bonusStepsLeft; шанс выката 1 из 4 при обычном поедании - бонус живёт BONUS_LIFETIME_STEPS шагов (таймер в шагах -> учитывает паузу) - съеденный бонус даёт BONUS_POINTS очков, звук выше тоном, вспышка - отрисовка золотой клетки + дуга-таймер (drawArc) в drawBoard() - randomFreeCell учитывает и еду, и бонус, чтобы не наложить их Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🐍 Змейка на 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 (рекомендуется)
- Открыть папку проекта в Android Studio (File → Open).
- Дождаться Gradle Sync.
- Подключить телефон по USB (с включённой отладкой по USB) или запустить эмулятор.
- Нажать ▶ Run.
Вариант 2: командная строка
# нужен 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.
Там по шагам видно идеи 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(popProgress0→1), запуск анимации вstep()и отрисовку кольца вdrawBoard(). -
snake-stage-6— пауза: тап по полю во время игры ставит/снимает паузу (свайпы по-прежнему рулят направлением). Смотри флагpaused, условие в игровом цикле и оверлей «ПАУЗА». -
snake-stage-7— бонус-еда с таймером: иногда (1 из 4 при поедании обычной еды) появляется золотая еда на ~36 шагов и даёт +3 очка; вокруг неё рисуется дуга-таймер, по истечении она исчезает. Время считается в шагах игры, поэтому пауза учитывается автоматически. СмотриbonusFood/bonusStepsLeft, логику вstep()и отрисовку (drawArc) вdrawBoard().
Идеи для следующих этапов: препятствия и уровни, режим «сквозь стены», два игрока.