mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 10:25:19 +01:00
Add background music and fix pause menu: - Add GameMusic class for background music playback - Add music toggle button to UI - Fix resume button to properly resume game instead of restarting - Add volume control icons - Add proper music lifecycle management
This commit is contained in:
parent
fabb2742da
commit
a56f08afb9
7 changed files with 172 additions and 7 deletions
|
@ -17,6 +17,7 @@ import com.mintris.game.GameView
|
||||||
import com.mintris.game.NextPieceView
|
import com.mintris.game.NextPieceView
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import com.mintris.model.GameBoard
|
import com.mintris.model.GameBoard
|
||||||
|
import com.mintris.audio.GameMusic
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
@ -25,9 +26,11 @@ class MainActivity : AppCompatActivity() {
|
||||||
private lateinit var gameView: GameView
|
private lateinit var gameView: GameView
|
||||||
private lateinit var gameHaptics: GameHaptics
|
private lateinit var gameHaptics: GameHaptics
|
||||||
private lateinit var gameBoard: GameBoard
|
private lateinit var gameBoard: GameBoard
|
||||||
|
private lateinit var gameMusic: GameMusic
|
||||||
|
|
||||||
// Game state
|
// Game state
|
||||||
private var isSoundEnabled = true
|
private var isSoundEnabled = true
|
||||||
|
private var isMusicEnabled = true
|
||||||
private var selectedLevel = 1
|
private var selectedLevel = 1
|
||||||
private val maxLevel = 20
|
private val maxLevel = 20
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
gameBoard = GameBoard()
|
gameBoard = GameBoard()
|
||||||
gameHaptics = GameHaptics(this)
|
gameHaptics = GameHaptics(this)
|
||||||
gameView = binding.gameView
|
gameView = binding.gameView
|
||||||
|
gameMusic = GameMusic(this)
|
||||||
|
|
||||||
// Set up game view
|
// Set up game view
|
||||||
gameView.setGameBoard(gameBoard)
|
gameView.setGameBoard(gameBoard)
|
||||||
|
@ -51,6 +55,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
binding.nextPieceView.invalidate()
|
binding.nextPieceView.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up music toggle
|
||||||
|
binding.musicToggle.setOnClickListener {
|
||||||
|
isMusicEnabled = !isMusicEnabled
|
||||||
|
gameMusic.setEnabled(isMusicEnabled)
|
||||||
|
updateMusicToggleUI()
|
||||||
|
}
|
||||||
|
|
||||||
// Start game immediately
|
// Start game immediately
|
||||||
startGame()
|
startGame()
|
||||||
|
|
||||||
|
@ -94,7 +105,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
binding.resumeButton.setOnClickListener {
|
binding.resumeButton.setOnClickListener {
|
||||||
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
|
||||||
hidePauseMenu()
|
hidePauseMenu()
|
||||||
gameView.start()
|
resumeGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.settingsButton.setOnClickListener {
|
binding.settingsButton.setOnClickListener {
|
||||||
|
@ -217,11 +228,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
vibrator.vibrate(VibrationEffect.createPredefined(effectId))
|
vibrator.vibrate(VibrationEffect.createPredefined(effectId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMusicToggleUI() {
|
||||||
|
binding.musicToggle.setImageResource(
|
||||||
|
if (isMusicEnabled) R.drawable.ic_volume_up
|
||||||
|
else R.drawable.ic_volume_off
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun startGame() {
|
private fun startGame() {
|
||||||
gameView.visibility = View.VISIBLE
|
|
||||||
gameBoard.startGame()
|
|
||||||
gameView.start()
|
gameView.start()
|
||||||
hidePauseMenu()
|
gameMusic.setEnabled(isMusicEnabled) // Explicitly set enabled state
|
||||||
|
if (isMusicEnabled) {
|
||||||
|
gameMusic.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restartGame() {
|
private fun restartGame() {
|
||||||
|
@ -231,10 +250,22 @@ class MainActivity : AppCompatActivity() {
|
||||||
showPauseMenu()
|
showPauseMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pauseGame() {
|
||||||
|
gameView.pause()
|
||||||
|
gameMusic.pause()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resumeGame() {
|
||||||
|
gameView.resume()
|
||||||
|
if (isMusicEnabled) {
|
||||||
|
gameMusic.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
if (!gameView.isGameOver()) {
|
if (!gameView.isGameOver()) {
|
||||||
gameView.pause()
|
pauseGame()
|
||||||
showPauseMenu()
|
showPauseMenu()
|
||||||
binding.pauseStartButton.visibility = View.GONE
|
binding.pauseStartButton.visibility = View.GONE
|
||||||
binding.resumeButton.visibility = View.VISIBLE
|
binding.resumeButton.visibility = View.VISIBLE
|
||||||
|
@ -256,12 +287,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
binding.resumeButton.visibility = View.VISIBLE
|
binding.resumeButton.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
hidePauseMenu()
|
hidePauseMenu()
|
||||||
gameView.start()
|
resumeGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
gameView.resume()
|
if (!gameView.isGameOver()) {
|
||||||
|
resumeGame()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
gameMusic.release()
|
||||||
}
|
}
|
||||||
}
|
}
|
93
app/src/main/java/com/mintris/audio/GameMusic.kt
Normal file
93
app/src/main/java/com/mintris/audio/GameMusic.kt
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package com.mintris.audio
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.media.AudioAttributes
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import com.mintris.R
|
||||||
|
|
||||||
|
class GameMusic(private val context: Context) {
|
||||||
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
private var isEnabled = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
setupMediaPlayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupMediaPlayer() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Setting up MediaPlayer")
|
||||||
|
mediaPlayer = MediaPlayer.create(context, R.raw.game_music).apply {
|
||||||
|
isLooping = true
|
||||||
|
setVolume(0.5f, 0.5f)
|
||||||
|
|
||||||
|
// Set audio attributes for better performance
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
setAudioAttributes(
|
||||||
|
AudioAttributes.Builder()
|
||||||
|
.setUsage(AudioAttributes.USAGE_GAME)
|
||||||
|
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d("GameMusic", "MediaPlayer setup complete")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error setting up MediaPlayer", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Starting music playback, isEnabled: $isEnabled")
|
||||||
|
if (isEnabled && mediaPlayer?.isPlaying != true) {
|
||||||
|
mediaPlayer?.start()
|
||||||
|
Log.d("GameMusic", "Music playback started")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error starting music", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pause() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Pausing music playback")
|
||||||
|
mediaPlayer?.pause()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error pausing music", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Stopping music playback")
|
||||||
|
mediaPlayer?.stop()
|
||||||
|
mediaPlayer?.prepare()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error stopping music", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setEnabled(enabled: Boolean) {
|
||||||
|
Log.d("GameMusic", "Setting music enabled: $enabled")
|
||||||
|
isEnabled = enabled
|
||||||
|
if (enabled) {
|
||||||
|
start()
|
||||||
|
} else {
|
||||||
|
pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEnabled(): Boolean = isEnabled
|
||||||
|
|
||||||
|
fun release() {
|
||||||
|
try {
|
||||||
|
Log.d("GameMusic", "Releasing MediaPlayer")
|
||||||
|
mediaPlayer?.release()
|
||||||
|
mediaPlayer = null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GameMusic", "Error releasing MediaPlayer", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_volume_off.xml
Normal file
10
app/src/main/res/drawable/ic_volume_off.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_volume_up.xml
Normal file
10
app/src/main/res/drawable/ic_volume_up.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
|
||||||
|
</vector>
|
|
@ -225,6 +225,19 @@
|
||||||
android:text="@string/sound_on"
|
android:text="@string/sound_on"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="18sp" />
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/musicToggle"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/toggle_music"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_volume_up"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/pauseStartButton"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
BIN
app/src/main/res/raw/game_music.mp3
Normal file
BIN
app/src/main/res/raw/game_music.mp3
Normal file
Binary file not shown.
|
@ -15,4 +15,5 @@
|
||||||
<string name="select_level">Select Level</string>
|
<string name="select_level">Select Level</string>
|
||||||
<string name="sound_on">Sound: On</string>
|
<string name="sound_on">Sound: On</string>
|
||||||
<string name="sound_off">Sound: Off</string>
|
<string name="sound_off">Sound: Off</string>
|
||||||
|
<string name="toggle_music">Toggle music</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Add a link
Reference in a new issue