Add random mode toggle and fix resource linking issues

This commit is contained in:
cmclark00 2025-03-31 16:37:57 -04:00
parent 0b78bf7833
commit b2a9c40539
6 changed files with 209 additions and 100 deletions

View file

@ -45,6 +45,7 @@ import android.widget.ScrollView
import android.widget.ImageButton
import android.graphics.drawable.GradientDrawable
import android.widget.TextView
import android.widget.Switch
class MainActivity : AppCompatActivity(),
GamepadController.GamepadConnectionListener,
@ -80,6 +81,7 @@ class MainActivity : AppCompatActivity(),
private var gameStartTime: Long = 0
private var piecesPlaced: Int = 0
private var currentTheme = PlayerProgressionManager.THEME_CLASSIC
private var isRandomModeEnabled = false
// Activity result launcher for high score entry
private lateinit var highScoreEntryLauncher: ActivityResultLauncher<Intent>
@ -138,6 +140,10 @@ class MainActivity : AppCompatActivity(),
blockSkinSelector = binding.customizationBlockSkinSelector!!
pauseMenuScrollView = binding.pauseMenuScrollView
// Load random mode setting
isRandomModeEnabled = getSharedPreferences("com.mintris.preferences", Context.MODE_PRIVATE)
.getBoolean("random_mode_enabled", false)
// Initialize gamepad controller
gamepadController = GamepadController(gameView)
gamepadController.setGamepadConnectionListener(this)
@ -241,16 +247,33 @@ class MainActivity : AppCompatActivity(),
// Set up callbacks
gameView.onGameStateChanged = { score, level, lines ->
updateUI(score, level, lines)
}
// Track pieces placed using callback
gameBoard.onPieceLock = {
// Increment pieces placed counter
piecesPlaced++
currentScore = score
currentLevel = level
// Provide haptic feedback
gameHaptics.vibrateForPieceLock()
binding.scoreText.text = "$score"
binding.currentLevelText.text = "$level"
binding.linesText.text = "$lines"
binding.comboText.text = gameBoard.getCombo().toString()
// If random mode is enabled and we've leveled up, select random theme and block skin
if (isRandomModeEnabled && level > 1) {
val unlockedThemes = progressionManager.getUnlockedThemes().toList()
val unlockedBlocks = progressionManager.getUnlockedBlocks().toList()
// Randomly change theme (50% chance)
if (unlockedThemes.isNotEmpty() && Math.random() < 0.5) {
val randomTheme = unlockedThemes.random()
currentTheme = randomTheme
applyTheme(randomTheme)
}
// Randomly change block skin (50% chance)
if (unlockedBlocks.isNotEmpty() && Math.random() < 0.5) {
val randomBlock = unlockedBlocks.random()
gameView.setBlockSkin(randomBlock)
progressionManager.setSelectedBlockSkin(randomBlock)
}
}
}
gameView.onGameOver = { finalScore ->
@ -525,8 +548,8 @@ class MainActivity : AppCompatActivity(),
* Show customization menu
*/
private fun showCustomizationMenu() {
binding.customizationContainer.visibility = View.VISIBLE
binding.pauseContainer.visibility = View.GONE
binding.customizationContainer.visibility = View.VISIBLE
// Get theme colors
val themeColor = getThemeColor(currentTheme)
@ -535,58 +558,48 @@ class MainActivity : AppCompatActivity(),
// Apply background color to customization container
binding.customizationContainer.setBackgroundColor(backgroundColor)
// Update level badge
// Update level badge with player's level and theme color
binding.customizationLevelBadge.setLevel(progressionManager.getPlayerLevel())
binding.customizationLevelBadge.setThemeColor(themeColor)
// Apply theme colors to text and buttons
binding.customizationTitle.setTextColor(themeColor)
binding.customizationBackButton.setTextColor(themeColor)
// Apply theme colors to all text views in the container
// Apply theme color to all text views in the container
applyThemeColorToTextViews(binding.customizationContainer, themeColor)
// Update theme and block skin selectors
binding.customizationThemeSelector.updateThemes(
progressionManager.getUnlockedThemes(),
currentTheme
// Update theme selector with available themes
binding.customizationThemeSelector?.updateThemes(
unlockedThemes = progressionManager.getUnlockedThemes(),
currentTheme = currentTheme
)
// Set up block skin selector callback
binding.customizationBlockSkinSelector.onBlockSkinSelected = { selectedSkin ->
// Update the game view with the selected block skin
gameView.setBlockSkin(selectedSkin)
// Save the selection
progressionManager.setSelectedBlockSkin(selectedSkin)
}
// Update block skin selector with current selection
binding.customizationBlockSkinSelector.updateBlockSkins(
// Update block skin selector with available skins
binding.customizationBlockSkinSelector?.updateBlockSkins(
progressionManager.getUnlockedBlocks(),
gameView.getCurrentBlockSkin(),
progressionManager.getPlayerLevel()
)
// Reset scroll position
binding.customizationMenuScrollView.scrollTo(0, 0)
// Set up block skin selection callback
binding.customizationBlockSkinSelector?.onBlockSkinSelected = { blockSkin ->
gameView.setBlockSkin(blockSkin)
progressionManager.setSelectedBlockSkin(blockSkin)
gameHaptics.vibrateForPieceLock()
}
// Initialize customization menu items
customizationMenuItems.clear()
customizationMenuItems.addAll(listOf(
binding.customizationThemeSelector,
binding.customizationBlockSkinSelector,
binding.customizationBackButton
).filterNotNull().filter { it.visibility == View.VISIBLE })
// Set initial selection and highlight
currentCustomizationMenuSelection = 0
highlightCustomizationMenuItem(currentCustomizationMenuSelection)
// Set initial focus to theme selector
binding.customizationThemeSelector.requestFocus()
// Initialize customization menu navigation
// Initialize customization menu items for gamepad navigation
initCustomizationMenuNavigation()
// Set up random mode switch
binding.randomModeSwitch?.apply {
isChecked = isRandomModeEnabled
isEnabled = progressionManager.getPlayerLevel() >= 5
setOnCheckedChangeListener { _, isChecked ->
isRandomModeEnabled = isChecked
getSharedPreferences("com.mintris.preferences", Context.MODE_PRIVATE)
.edit()
.putBoolean("random_mode_enabled", isChecked)
.apply()
}
}
}
private fun initCustomizationMenuNavigation() {
@ -595,6 +608,7 @@ class MainActivity : AppCompatActivity(),
// Add items in order
customizationMenuItems.addAll(listOf(
binding.customizationThemeSelector,
binding.randomModeSwitch,
binding.customizationBlockSkinSelector,
binding.customizationBackButton
).filterNotNull().filter { it.visibility == View.VISIBLE })
@ -835,6 +849,26 @@ class MainActivity : AppCompatActivity(),
binding.currentLevelText.text = "$level"
binding.linesText.text = "$lines"
binding.comboText.text = gameBoard.getCombo().toString()
// If random mode is enabled and we've leveled up, select random theme and block skin
if (isRandomModeEnabled && level > 1) {
val unlockedThemes = progressionManager.getUnlockedThemes().toList()
val unlockedBlocks = progressionManager.getUnlockedBlocks().toList()
// Randomly change theme (50% chance)
if (unlockedThemes.isNotEmpty() && Math.random() < 0.5) {
val randomTheme = unlockedThemes.random()
currentTheme = randomTheme
applyTheme(randomTheme)
}
// Randomly change block skin (50% chance)
if (unlockedBlocks.isNotEmpty() && Math.random() < 0.5) {
val randomBlock = unlockedBlocks.random()
gameView.setBlockSkin(randomBlock)
progressionManager.setSelectedBlockSkin(randomBlock)
}
}
}
gameView.onGameOver = { finalScore ->
@ -1431,7 +1465,7 @@ class MainActivity : AppCompatActivity(),
item.scaleX = 1.0f
item.scaleY = 1.0f
}
// Reset background/focus state for all items before applying highlight
// Reset
when (item) {
is Button -> item.background = ColorDrawable(Color.TRANSPARENT)
is ImageButton -> item.background = null // Let default background handle non-selected
@ -1470,37 +1504,34 @@ class MainActivity : AppCompatActivity(),
item.background = it
}
} ?: run {
// Absolute fallback: create a border if drawable fails
item.background = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
// Fallback to simple border if drawable not found
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
}
}
is ImageButton -> {
item.background = GradientDrawable().apply {
setColor(Color.TRANSPARENT) // Keep original button look, just add border
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
// Similar handling for ImageButton
ContextCompat.getDrawable(this, R.drawable.menu_item_selected)?.mutate()?.let {
if (it is GradientDrawable) {
it.setStroke(borderWidth, highlightBorderColor)
item.background = it
} else {
it.setTint(highlightBorderColor)
item.background = it
}
} ?: run {
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
}
}
is ThemeSelector -> {
item.background = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.setHasFocus(true) // Tell selector it HAS component focus
}
is BlockSkinSelector -> {
item.background = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.setHasFocus(true) // Tell selector it HAS component focus
}
}
}
}
@ -1726,6 +1757,8 @@ class MainActivity : AppCompatActivity(),
val themeColor = getThemeColor(currentTheme)
val highlightBorderColor = themeColor
val borderWidth = 4 // Define border width for highlight
val cornerRadius = 12f
customizationMenuItems.forEachIndexed { i, item ->
val isSelected = (i == index)
@ -1747,58 +1780,55 @@ class MainActivity : AppCompatActivity(),
item.background = ColorDrawable(Color.TRANSPARENT)
item.setHasFocus(false)
}
is Switch -> {
item.background = ColorDrawable(Color.TRANSPARENT)
}
}
if (isSelected) {
if (item is Button || item is ImageButton) {
item.scaleX = 1.1f
item.scaleY = 1.1f
}
val borderWidth = 4
val cornerRadius = 12f
when (item) {
is Button -> {
ContextCompat.getDrawable(this, R.drawable.menu_item_selected)?.mutate()?.let {
if (it is GradientDrawable) {
it.setStroke(borderWidth, highlightBorderColor)
item.background = it
} else {
it.setTint(highlightBorderColor)
item.background = it
}
} ?: run {
item.background = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
}
is ImageButton -> {
item.background = GradientDrawable().apply {
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
}
is ThemeSelector -> {
item.background = GradientDrawable().apply {
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
item.setHasFocus(true)
}
is BlockSkinSelector -> {
item.background = GradientDrawable().apply {
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
item.setHasFocus(true)
}
is Switch -> {
var gradientDrawable = GradientDrawable().apply {
setColor(Color.TRANSPARENT)
setStroke(borderWidth, highlightBorderColor)
setCornerRadius(cornerRadius)
}
item.background = gradientDrawable
}
}
}
}
@ -1857,6 +1887,11 @@ class MainActivity : AppCompatActivity(),
selectedItem.confirmSelection()
// The onBlockSkinSelected callback will handle updating the game view and saving the selection
}
is Switch -> {
if (selectedItem.isEnabled) {
selectedItem.isChecked = !selectedItem.isChecked
}
}
else -> {
selectedItem.performClick()
}