From 05d65eab14a78c47b87f2179420ff5e23c8053c8 Mon Sep 17 00:00:00 2001 From: george Date: Wed, 17 Jun 2026 17:44:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=AD=D1=82=D0=B0=D0=BF=204:=20=D0=B7=D0=B2?= =?UTF-8?q?=D1=83=D0=BA=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=B5=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=B5=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Короткий звуковой эффект при съедании еды через SoundPool. - res/raw/eat.wav — короткий синтезированный «блип» (PCM 16-bit моно) - SoundPool с AudioAttributes USAGE_GAME, загрузка сэмпла один раз - воспроизведение в step() при поедании еды - освобождение SoundPool в DisposableEffect при уходе с экрана Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 7 +++++- .../main/java/com/example/snake/SnakeGame.kt | 23 ++++++++++++++++++ app/src/main/res/raw/eat.wav | Bin 0 -> 9746 bytes 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/raw/eat.wav diff --git a/README.md b/README.md index dfbe84a..20fdae6 100644 --- a/README.md +++ b/README.md @@ -79,4 +79,9 @@ app/src/main/ диск не блокирует UI. Смотри `LaunchedEffect` для загрузки рекорда и `scope.launch { ScoreStore.saveBest(...) }` при новом рекорде. -Идеи для следующих этапов: экранные кнопки-стрелки, анимации, звук, паузу. +- **`snake-stage-4`** — звук при поедании еды через **SoundPool**: короткий + WAV в `res/raw/eat.wav` грузится один раз, играется при каждом съедании + (низкая задержка). Смотри настройку `SoundPool` и `soundPool.play(...)` + в `step()`; освобождение ресурса — в `DisposableEffect`. + +Идеи для следующих этапов: анимации поедания, пауза, выбор размера поля. diff --git a/app/src/main/java/com/example/snake/SnakeGame.kt b/app/src/main/java/com/example/snake/SnakeGame.kt index 26e6c6e..7c14093 100644 --- a/app/src/main/java/com/example/snake/SnakeGame.kt +++ b/app/src/main/java/com/example/snake/SnakeGame.kt @@ -1,5 +1,7 @@ package com.example.snake +import android.media.AudioAttributes +import android.media.SoundPool import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectDragGestures @@ -9,6 +11,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -86,6 +89,24 @@ fun SnakeGame() { best = ScoreStore.bestFlow(context).first() } + // Этап 4: звук поедания еды через SoundPool (короткий эффект, низкая задержка). + // Пул и загруженный сэмпл создаём один раз и освобождаем при уходе с экрана. + val soundPool = remember { + SoundPool.Builder() + .setMaxStreams(4) + .setAudioAttributes( + AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_GAME) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build() + ) + .build() + } + val eatSoundId = remember { soundPool.load(context, R.raw.eat, 1) } + DisposableEffect(Unit) { + onDispose { soundPool.release() } + } + fun reset() { snake = startSnake dir = Cell(0, -1) @@ -112,6 +133,8 @@ fun SnakeGame() { snake = if (grew) listOf(nh) + snake else listOf(nh) + snake.dropLast(1) if (grew) { score++ + // звук поедания (left=1f, right=1f, prio=1, без зацикливания, обычная скорость) + soundPool.play(eatSoundId, 1f, 1f, 1, 0, 1f) if (score > best) { best = score // новый рекорд — сохраняем на диск (асинхронно, UI не блокируется) diff --git a/app/src/main/res/raw/eat.wav b/app/src/main/res/raw/eat.wav new file mode 100644 index 0000000000000000000000000000000000000000..a17034d86723e8f5ae8690b30e1582e8fc10d558 GIT binary patch literal 9746 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