Add full gamepad support to all screens including pause menu, progression screen, high scores, and game over

This commit is contained in:
cmclark00 2025-03-31 08:01:47 -04:00
parent f4f40c4c34
commit 08c9f8a1ce
5 changed files with 107 additions and 11 deletions

View file

@ -12,6 +12,8 @@ import com.mintris.model.HighScore
import com.mintris.model.HighScoreManager import com.mintris.model.HighScoreManager
import com.mintris.model.PlayerProgressionManager import com.mintris.model.PlayerProgressionManager
import android.graphics.Color import android.graphics.Color
import android.view.KeyEvent
import android.view.InputDevice
class HighScoreEntryActivity : AppCompatActivity() { class HighScoreEntryActivity : AppCompatActivity() {
private lateinit var binding: HighScoreEntryBinding private lateinit var binding: HighScoreEntryBinding
@ -39,20 +41,55 @@ class HighScoreEntryActivity : AppCompatActivity() {
binding.scoreText.text = "Score: $score" binding.scoreText.text = "Score: $score"
binding.saveButton.setOnClickListener { binding.saveButton.setOnClickListener {
// Only allow saving once saveScore()
if (!hasSaved) { }
val name = binding.nameInput.text.toString().trim() }
if (name.isNotEmpty()) {
hasSaved = true private fun saveScore() {
val highScore = HighScore(name, score, 1) // Only allow saving once
highScoreManager.addHighScore(highScore) if (!hasSaved) {
val name = binding.nameInput.text.toString().trim()
// Set result and finish if (name.isNotEmpty()) {
setResult(Activity.RESULT_OK) 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() 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 // Prevent accidental back button press from causing issues

View file

@ -12,6 +12,8 @@ import com.mintris.model.HighScoreManager
import com.mintris.model.PlayerProgressionManager import com.mintris.model.PlayerProgressionManager
import android.graphics.Color import android.graphics.Color
import android.util.Log import android.util.Log
import android.view.KeyEvent
import android.view.InputDevice
class HighScoresActivity : AppCompatActivity() { class HighScoresActivity : AppCompatActivity() {
private lateinit var binding: HighScoresBinding private lateinit var binding: HighScoresBinding
@ -113,4 +115,29 @@ class HighScoresActivity : AppCompatActivity() {
Log.e("HighScoresActivity", "Error in onResume", e) 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
}
} }

View file

@ -1143,6 +1143,12 @@ class MainActivity : AppCompatActivity(),
activateSelectedMenuItem() activateSelectedMenuItem()
} else if (titleScreen.visibility == View.VISIBLE) { } else if (titleScreen.visibility == View.VISIBLE) {
titleScreen.performClick() 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.statsButton)
pauseMenuItems.add(binding.pauseLevelUpButton) pauseMenuItems.add(binding.pauseLevelUpButton)
pauseMenuItems.add(binding.pauseLevelDownButton) 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)
}
} }
/** /**

View file

@ -266,7 +266,7 @@ class GamepadController(
* @return true if the event was handled, false otherwise * @return true if the event was handled, false otherwise
*/ */
fun handleKeyEvent(keyCode: Int, event: KeyEvent): Boolean { 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()) { if (!gameView.isActive()) {
// Handle menu navigation even when game is not active // Handle menu navigation even when game is not active
if (event.action == KeyEvent.ACTION_DOWN) { if (event.action == KeyEvent.ACTION_DOWN) {
@ -284,6 +284,11 @@ class GamepadController(
navigationListener?.onMenuSelect() navigationListener?.onMenuSelect()
return true return true
} }
KeyEvent.KEYCODE_BUTTON_B -> {
// B button can be used to go back/cancel
menuListener?.onPauseRequested()
return true
}
} }
} }

View file

@ -304,4 +304,11 @@ class ProgressionScreen @JvmOverloads constructor(
card?.setCardBackgroundColor(backgroundColor) card?.setCardBackgroundColor(backgroundColor)
} }
} }
/**
* Public method to handle continue action via gamepad
*/
fun performContinue() {
continueButton.performClick()
}
} }