mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-17 23:55:21 +01:00
Implement full gamepad menu support and title screen start
This commit is contained in:
parent
779fa8eab1
commit
f4f40c4c34
2 changed files with 155 additions and 3 deletions
|
@ -41,7 +41,8 @@ import android.app.AlertDialog
|
|||
|
||||
class MainActivity : AppCompatActivity(),
|
||||
GamepadController.GamepadConnectionListener,
|
||||
GamepadController.GamepadMenuListener {
|
||||
GamepadController.GamepadMenuListener,
|
||||
GamepadController.GamepadNavigationListener {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
|
@ -93,6 +94,10 @@ class MainActivity : AppCompatActivity(),
|
|||
// Track connected gamepads to detect changes
|
||||
private val connectedGamepads = mutableSetOf<String>()
|
||||
|
||||
// Track currently selected menu item in pause menu for gamepad navigation
|
||||
private var currentMenuSelection = 0
|
||||
private val pauseMenuItems = mutableListOf<View>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Register activity result launcher for high score entry
|
||||
highScoreEntryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
|
@ -124,6 +129,7 @@ class MainActivity : AppCompatActivity(),
|
|||
gamepadController = GamepadController(gameView)
|
||||
gamepadController.setGamepadConnectionListener(this)
|
||||
gamepadController.setGamepadMenuListener(this)
|
||||
gamepadController.setGamepadNavigationListener(this)
|
||||
|
||||
// Set up touch event forwarding
|
||||
binding.touchInterceptor?.setOnTouchListener { _, event ->
|
||||
|
@ -395,6 +401,9 @@ class MainActivity : AppCompatActivity(),
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
window.setDecorFitsSystemWindows(false)
|
||||
}
|
||||
|
||||
// Initialize pause menu items for gamepad navigation
|
||||
initPauseMenuNavigation()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -591,6 +600,15 @@ class MainActivity : AppCompatActivity(),
|
|||
gameView.getCurrentBlockSkin(),
|
||||
progressionManager.getPlayerLevel()
|
||||
)
|
||||
|
||||
// Initialize pause menu navigation
|
||||
initPauseMenuNavigation()
|
||||
|
||||
// Reset and highlight first selectable menu item
|
||||
if (pauseMenuItems.isNotEmpty()) {
|
||||
currentMenuSelection = if (binding.resumeButton.visibility == View.VISIBLE) 0 else 1
|
||||
highlightMenuItem(currentMenuSelection)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1013,6 +1031,13 @@ class MainActivity : AppCompatActivity(),
|
|||
|
||||
// First check if it's a gamepad input
|
||||
if (GamepadController.isGamepad(event.device)) {
|
||||
// Handle title screen start with gamepad
|
||||
if (titleScreen.visibility == View.VISIBLE &&
|
||||
(keyCode == KeyEvent.KEYCODE_BUTTON_A || keyCode == KeyEvent.KEYCODE_BUTTON_START)) {
|
||||
titleScreen.performClick()
|
||||
return true
|
||||
}
|
||||
|
||||
// If gamepad input was handled by the controller, consume the event
|
||||
if (gamepadController.handleKeyEvent(keyCode, event)) {
|
||||
return true
|
||||
|
@ -1086,7 +1111,93 @@ class MainActivity : AppCompatActivity(),
|
|||
// If pause menu is showing, handle as a resume
|
||||
hidePauseMenu()
|
||||
resumeGame()
|
||||
} else if (titleScreen.visibility == View.VISIBLE) {
|
||||
// If title screen is showing, start the game
|
||||
titleScreen.performClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements GamepadNavigationListener to handle menu navigation
|
||||
*/
|
||||
override fun onMenuUp() {
|
||||
runOnUiThread {
|
||||
if (binding.pauseContainer.visibility == View.VISIBLE) {
|
||||
moveMenuSelectionUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMenuDown() {
|
||||
runOnUiThread {
|
||||
if (binding.pauseContainer.visibility == View.VISIBLE) {
|
||||
moveMenuSelectionDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMenuSelect() {
|
||||
runOnUiThread {
|
||||
if (binding.pauseContainer.visibility == View.VISIBLE) {
|
||||
activateSelectedMenuItem()
|
||||
} else if (titleScreen.visibility == View.VISIBLE) {
|
||||
titleScreen.performClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize pause menu items for gamepad navigation
|
||||
*/
|
||||
private fun initPauseMenuNavigation() {
|
||||
pauseMenuItems.clear()
|
||||
pauseMenuItems.add(binding.resumeButton)
|
||||
pauseMenuItems.add(binding.pauseStartButton)
|
||||
pauseMenuItems.add(binding.pauseRestartButton)
|
||||
pauseMenuItems.add(binding.highScoresButton)
|
||||
pauseMenuItems.add(binding.statsButton)
|
||||
pauseMenuItems.add(binding.pauseLevelUpButton)
|
||||
pauseMenuItems.add(binding.pauseLevelDownButton)
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight the currently selected menu item
|
||||
*/
|
||||
private fun highlightMenuItem(index: Int) {
|
||||
// Reset all items to normal state
|
||||
pauseMenuItems.forEachIndexed { i, item ->
|
||||
item.alpha = if (i == index) 1.0f else 0.7f
|
||||
item.scaleX = if (i == index) 1.2f else 1.0f
|
||||
item.scaleY = if (i == index) 1.2f else 1.0f
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move menu selection up
|
||||
*/
|
||||
private fun moveMenuSelectionUp() {
|
||||
if (pauseMenuItems.isEmpty()) return
|
||||
currentMenuSelection = (currentMenuSelection - 1 + pauseMenuItems.size) % pauseMenuItems.size
|
||||
highlightMenuItem(currentMenuSelection)
|
||||
gameHaptics.vibrateForPieceMove()
|
||||
}
|
||||
|
||||
/**
|
||||
* Move menu selection down
|
||||
*/
|
||||
private fun moveMenuSelectionDown() {
|
||||
if (pauseMenuItems.isEmpty()) return
|
||||
currentMenuSelection = (currentMenuSelection + 1) % pauseMenuItems.size
|
||||
highlightMenuItem(currentMenuSelection)
|
||||
gameHaptics.vibrateForPieceMove()
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the currently selected menu item
|
||||
*/
|
||||
private fun activateSelectedMenuItem() {
|
||||
if (pauseMenuItems.isEmpty() || currentMenuSelection < 0 || currentMenuSelection >= pauseMenuItems.size) return
|
||||
pauseMenuItems[currentMenuSelection].performClick()
|
||||
}
|
||||
}
|
|
@ -149,9 +149,16 @@ class GamepadController(
|
|||
fun onPauseRequested()
|
||||
}
|
||||
|
||||
interface GamepadNavigationListener {
|
||||
fun onMenuUp()
|
||||
fun onMenuDown()
|
||||
fun onMenuSelect()
|
||||
}
|
||||
|
||||
// Listeners
|
||||
private var connectionListener: GamepadConnectionListener? = null
|
||||
private var menuListener: GamepadMenuListener? = null
|
||||
private var navigationListener: GamepadNavigationListener? = null
|
||||
|
||||
// Currently active gamepad for rumble
|
||||
private var activeGamepad: InputDevice? = null
|
||||
|
@ -170,6 +177,13 @@ class GamepadController(
|
|||
menuListener = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a listener for gamepad navigation events
|
||||
*/
|
||||
fun setGamepadNavigationListener(listener: GamepadNavigationListener) {
|
||||
navigationListener = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check for newly connected gamepads.
|
||||
* Call this periodically from the activity to detect connection changes.
|
||||
|
@ -253,7 +267,34 @@ class GamepadController(
|
|||
*/
|
||||
fun handleKeyEvent(keyCode: Int, event: KeyEvent): Boolean {
|
||||
// Skip if game is not active
|
||||
if (!gameView.isActive()) return false
|
||||
if (!gameView.isActive()) {
|
||||
// Handle menu navigation even when game is not active
|
||||
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_DPAD_UP -> {
|
||||
navigationListener?.onMenuUp()
|
||||
return true
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_DOWN -> {
|
||||
navigationListener?.onMenuDown()
|
||||
return true
|
||||
}
|
||||
KeyEvent.KEYCODE_BUTTON_A,
|
||||
KeyEvent.KEYCODE_DPAD_CENTER -> {
|
||||
navigationListener?.onMenuSelect()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle menu/start button for pause menu
|
||||
if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BUTTON_START) {
|
||||
menuListener?.onPauseRequested()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
val device = event.device
|
||||
if (!isGamepad(device)) return false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue