From 08c9f8a1cef9491aa519544ecbc464238c54925c Mon Sep 17 00:00:00 2001 From: cmclark00 Date: Mon, 31 Mar 2025 08:01:47 -0400 Subject: [PATCH] Add full gamepad support to all screens including pause menu, progression screen, high scores, and game over --- .../com/mintris/HighScoreEntryActivity.kt | 57 +++++++++++++++---- .../java/com/mintris/HighScoresActivity.kt | 27 +++++++++ app/src/main/java/com/mintris/MainActivity.kt | 20 +++++++ .../com/mintris/game/GamepadController.kt | 7 ++- .../java/com/mintris/ui/ProgressionScreen.kt | 7 +++ 5 files changed, 107 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/mintris/HighScoreEntryActivity.kt b/app/src/main/java/com/mintris/HighScoreEntryActivity.kt index 5290cf6..339c3b6 100644 --- a/app/src/main/java/com/mintris/HighScoreEntryActivity.kt +++ b/app/src/main/java/com/mintris/HighScoreEntryActivity.kt @@ -12,6 +12,8 @@ import com.mintris.model.HighScore import com.mintris.model.HighScoreManager import com.mintris.model.PlayerProgressionManager import android.graphics.Color +import android.view.KeyEvent +import android.view.InputDevice class HighScoreEntryActivity : AppCompatActivity() { private lateinit var binding: HighScoreEntryBinding @@ -39,20 +41,55 @@ class HighScoreEntryActivity : AppCompatActivity() { binding.scoreText.text = "Score: $score" binding.saveButton.setOnClickListener { - // Only allow saving once - if (!hasSaved) { - val name = binding.nameInput.text.toString().trim() - if (name.isNotEmpty()) { - hasSaved = true - val highScore = HighScore(name, score, 1) - highScoreManager.addHighScore(highScore) - - // Set result and finish - setResult(Activity.RESULT_OK) + saveScore() + } + } + + private fun saveScore() { + // Only allow saving once + if (!hasSaved) { + val name = binding.nameInput.text.toString().trim() + if (name.isNotEmpty()) { + hasSaved = true + val highScore = HighScore(name, score, 1) + highScoreManager.addHighScore(highScore) + + // Set result and finish + setResult(Activity.RESULT_OK) + finish() + } + } + } + + // Override onKeyDown to handle gamepad buttons + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + // Check if it's a gamepad input + if (event != null && isGamepadDevice(event.device)) { + when (keyCode) { + KeyEvent.KEYCODE_BUTTON_A, + KeyEvent.KEYCODE_DPAD_CENTER -> { + // A button saves the score + saveScore() + return true + } + KeyEvent.KEYCODE_BUTTON_B -> { + // B button cancels + setResult(Activity.RESULT_CANCELED) finish() + return true } } } + + return super.onKeyDown(keyCode, event) + } + + // Helper function to check if the device is a gamepad + private fun isGamepadDevice(device: InputDevice?): Boolean { + if (device == null) return false + val sources = device.sources + return (sources and InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD || + (sources and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK } // Prevent accidental back button press from causing issues diff --git a/app/src/main/java/com/mintris/HighScoresActivity.kt b/app/src/main/java/com/mintris/HighScoresActivity.kt index d91dfad..0fdc75d 100644 --- a/app/src/main/java/com/mintris/HighScoresActivity.kt +++ b/app/src/main/java/com/mintris/HighScoresActivity.kt @@ -12,6 +12,8 @@ import com.mintris.model.HighScoreManager import com.mintris.model.PlayerProgressionManager import android.graphics.Color import android.util.Log +import android.view.KeyEvent +import android.view.InputDevice class HighScoresActivity : AppCompatActivity() { private lateinit var binding: HighScoresBinding @@ -113,4 +115,29 @@ class HighScoresActivity : AppCompatActivity() { Log.e("HighScoresActivity", "Error in onResume", e) } } + + // Handle gamepad buttons + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + // Check if it's a gamepad input + if (event != null && isGamepadDevice(event.device)) { + when (keyCode) { + KeyEvent.KEYCODE_BUTTON_B, + KeyEvent.KEYCODE_BACK -> { + // B button or Back button returns to previous screen + finish() + return true + } + } + } + + return super.onKeyDown(keyCode, event) + } + + // Helper function to check if the device is a gamepad + private fun isGamepadDevice(device: InputDevice?): Boolean { + if (device == null) return false + val sources = device.sources + return (sources and InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD || + (sources and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK + } } \ No newline at end of file diff --git a/app/src/main/java/com/mintris/MainActivity.kt b/app/src/main/java/com/mintris/MainActivity.kt index 916e837..23c7603 100644 --- a/app/src/main/java/com/mintris/MainActivity.kt +++ b/app/src/main/java/com/mintris/MainActivity.kt @@ -1143,6 +1143,12 @@ class MainActivity : AppCompatActivity(), activateSelectedMenuItem() } else if (titleScreen.visibility == View.VISIBLE) { titleScreen.performClick() + } else if (progressionScreen.visibility == View.VISIBLE) { + // Handle continue in progression screen + progressionScreen.performContinue() + } else if (binding.gameOverContainer.visibility == View.VISIBLE) { + // Handle play again in game over screen + binding.playAgainButton.performClick() } } } @@ -1159,6 +1165,20 @@ class MainActivity : AppCompatActivity(), pauseMenuItems.add(binding.statsButton) pauseMenuItems.add(binding.pauseLevelUpButton) pauseMenuItems.add(binding.pauseLevelDownButton) + pauseMenuItems.add(binding.settingsButton) + pauseMenuItems.add(binding.musicToggle) + + // Add theme selector if present + val themeSelector = binding.themeSelector + if (themeSelector.visibility == View.VISIBLE) { + pauseMenuItems.add(themeSelector) + } + + // Add block skin selector if present + val blockSkinSelector = binding.blockSkinSelector + if (blockSkinSelector.visibility == View.VISIBLE) { + pauseMenuItems.add(blockSkinSelector) + } } /** diff --git a/app/src/main/java/com/mintris/game/GamepadController.kt b/app/src/main/java/com/mintris/game/GamepadController.kt index 2d12bee..811dea9 100644 --- a/app/src/main/java/com/mintris/game/GamepadController.kt +++ b/app/src/main/java/com/mintris/game/GamepadController.kt @@ -266,7 +266,7 @@ class GamepadController( * @return true if the event was handled, false otherwise */ fun handleKeyEvent(keyCode: Int, event: KeyEvent): Boolean { - // Skip if game is not active + // Skip if game is not active but handle menu navigation if (!gameView.isActive()) { // Handle menu navigation even when game is not active if (event.action == KeyEvent.ACTION_DOWN) { @@ -284,6 +284,11 @@ class GamepadController( navigationListener?.onMenuSelect() return true } + KeyEvent.KEYCODE_BUTTON_B -> { + // B button can be used to go back/cancel + menuListener?.onPauseRequested() + return true + } } } diff --git a/app/src/main/java/com/mintris/ui/ProgressionScreen.kt b/app/src/main/java/com/mintris/ui/ProgressionScreen.kt index 8c5d4d4..117a440 100644 --- a/app/src/main/java/com/mintris/ui/ProgressionScreen.kt +++ b/app/src/main/java/com/mintris/ui/ProgressionScreen.kt @@ -304,4 +304,11 @@ class ProgressionScreen @JvmOverloads constructor( card?.setCardBackgroundColor(backgroundColor) } } + + /** + * Public method to handle continue action via gamepad + */ + fun performContinue() { + continueButton.performClick() + } } \ No newline at end of file