diff --git a/app/src/main/java/com/mintris/HighScoreEntryActivity.kt b/app/src/main/java/com/mintris/HighScoreEntryActivity.kt index 5290cf6..8829d52 100644 --- a/app/src/main/java/com/mintris/HighScoreEntryActivity.kt +++ b/app/src/main/java/com/mintris/HighScoreEntryActivity.kt @@ -66,7 +66,8 @@ class HighScoreEntryActivity : AppCompatActivity() { } private fun loadThemePreference(): String { - return progressionManager.getSelectedTheme() + val prefs = getSharedPreferences("mintris_settings", MODE_PRIVATE) + return prefs.getString("selected_theme", PlayerProgressionManager.THEME_CLASSIC) ?: PlayerProgressionManager.THEME_CLASSIC } private fun applyTheme(themeId: String) { diff --git a/app/src/main/java/com/mintris/HighScoresActivity.kt b/app/src/main/java/com/mintris/HighScoresActivity.kt index d91dfad..ae525bf 100644 --- a/app/src/main/java/com/mintris/HighScoresActivity.kt +++ b/app/src/main/java/com/mintris/HighScoresActivity.kt @@ -58,7 +58,8 @@ class HighScoresActivity : AppCompatActivity() { } private fun loadThemePreference(): String { - return progressionManager.getSelectedTheme() + val prefs = getSharedPreferences("mintris_settings", MODE_PRIVATE) + return prefs.getString("selected_theme", PlayerProgressionManager.THEME_CLASSIC) ?: PlayerProgressionManager.THEME_CLASSIC } private fun applyTheme(themeId: String) { diff --git a/app/src/main/java/com/mintris/MainActivity.kt b/app/src/main/java/com/mintris/MainActivity.kt index 3e94bac..5390803 100644 --- a/app/src/main/java/com/mintris/MainActivity.kt +++ b/app/src/main/java/com/mintris/MainActivity.kt @@ -91,14 +91,6 @@ class MainActivity : AppCompatActivity() { themeSelector = binding.themeSelector blockSkinSelector = binding.blockSkinSelector - // Set up progression screen - progressionScreen = binding.progressionScreen - progressionScreen.visibility = View.GONE - progressionScreen.onContinue = { - progressionScreen.visibility = View.GONE - binding.gameOverContainer.visibility = View.VISIBLE - } - // Load and apply theme preference currentTheme = progressionManager.getSelectedTheme() applyTheme(currentTheme) @@ -106,17 +98,18 @@ class MainActivity : AppCompatActivity() { // Load and apply block skin preference gameView.setBlockSkin(progressionManager.getSelectedBlockSkin()) - // Update block skin selector with current selection - blockSkinSelector.updateBlockSkins( - progressionManager.getUnlockedBlocks(), - gameView.getCurrentBlockSkin(), - progressionManager.getPlayerLevel() - ) - // Set up game view gameView.setGameBoard(gameBoard) gameView.setHaptics(gameHaptics) + // Set up progression screen + progressionScreen = binding.progressionScreen + progressionScreen.visibility = View.GONE + progressionScreen.onContinue = { + progressionScreen.visibility = View.GONE + binding.gameOverContainer.visibility = View.VISIBLE + } + // Set up theme selector themeSelector.onThemeSelected = { themeId: String -> // Apply the new theme @@ -358,7 +351,10 @@ class MainActivity : AppCompatActivity() { var showingHighScore = false // Show progression screen first with XP animation - showProgressionScreen(xpGained, newRewards) + binding.gameOverContainer.visibility = View.GONE + progressionScreen.visibility = View.VISIBLE + progressionScreen.applyTheme(currentTheme) + progressionScreen.showProgress(progressionManager, xpGained, newRewards, currentTheme) // Override the continue button behavior if high score needs to be shown val originalOnContinue = progressionScreen.onContinue @@ -590,55 +586,63 @@ class MainActivity : AppCompatActivity() { * Apply a theme to the game */ private fun applyTheme(themeId: String) { + // Only apply if the theme is unlocked + if (!progressionManager.isThemeUnlocked(themeId)) return + + // Save the selected theme currentTheme = themeId - val themeColor = when (themeId) { - PlayerProgressionManager.THEME_CLASSIC -> Color.WHITE - PlayerProgressionManager.THEME_NEON -> Color.parseColor("#FF00FF") - PlayerProgressionManager.THEME_MONOCHROME -> Color.LTGRAY - PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#FF5A5F") - PlayerProgressionManager.THEME_MINIMALIST -> Color.BLACK - PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#66FCF1") - else -> Color.WHITE - } - - // Get background color for the theme - val backgroundColor = when (themeId) { - PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK - PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221") - PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A") - PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#3F2832") - PlayerProgressionManager.THEME_MINIMALIST -> Color.WHITE - PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#0B0C10") - else -> Color.BLACK - } - - // Apply background color to root view - binding.root.setBackgroundColor(backgroundColor) - - // Apply theme color to title screen - titleScreen.setThemeColor(themeColor) - titleScreen.setBackgroundColor(backgroundColor) - - // Apply theme color to game over screen - binding.gameOverContainer.setBackgroundColor(backgroundColor) - binding.gameOverText.setTextColor(themeColor) - binding.scoreText.setTextColor(themeColor) - binding.currentLevelText.setTextColor(themeColor) - binding.linesText.setTextColor(themeColor) - binding.comboText.setTextColor(themeColor) - binding.playAgainButton.setTextColor(themeColor) - binding.playAgainButton.setBackgroundResource(android.R.color.transparent) - binding.playAgainButton.setTextSize(24f) - - // Apply theme to progression screen (it will handle its own colors) - progressionScreen.applyTheme(themeId) - - // Apply theme color to game view - gameView.setThemeColor(themeColor) - gameView.setBackgroundColor(backgroundColor) - - // Save theme preference progressionManager.setSelectedTheme(themeId) + + // Apply theme to title screen if it's visible + if (titleScreen.visibility == View.VISIBLE) { + titleScreen.applyTheme(themeId) + } + + // Apply theme colors based on theme ID + when (themeId) { + PlayerProgressionManager.THEME_CLASSIC -> { + // Default black theme + binding.root.setBackgroundColor(Color.BLACK) + } + PlayerProgressionManager.THEME_NEON -> { + // Neon theme with dark purple background + binding.root.setBackgroundColor(Color.parseColor("#0D0221")) + } + PlayerProgressionManager.THEME_MONOCHROME -> { + // Monochrome dark gray + binding.root.setBackgroundColor(Color.parseColor("#1A1A1A")) + } + PlayerProgressionManager.THEME_RETRO -> { + // Retro arcade theme + binding.root.setBackgroundColor(Color.parseColor("#3F2832")) + } + PlayerProgressionManager.THEME_MINIMALIST -> { + // Minimalist white theme + binding.root.setBackgroundColor(Color.WHITE) + + // Update text colors for visibility + binding.scoreText.setTextColor(Color.BLACK) + binding.currentLevelText.setTextColor(Color.BLACK) + binding.linesText.setTextColor(Color.BLACK) + binding.comboText.setTextColor(Color.BLACK) + } + PlayerProgressionManager.THEME_GALAXY -> { + // Galaxy dark blue theme + binding.root.setBackgroundColor(Color.parseColor("#0B0C10")) + } + } + + // Apply theme to progression screen if it's visible and initialized + if (::progressionScreen.isInitialized && progressionScreen.visibility == View.VISIBLE) { + progressionScreen.applyTheme(themeId) + } + + // Apply theme color to the stats button + val textColor = getThemeColor(currentTheme) + binding.statsButton.setTextColor(textColor) + + // Update the game view to apply theme + gameView.invalidate() } /** @@ -734,16 +738,4 @@ class MainActivity : AppCompatActivity() { } return super.onKeyDown(keyCode, event) } - - private fun showProgressionScreen(xpGained: Long, newRewards: List) { - // Apply theme before showing the screen - progressionScreen.applyTheme(currentTheme) - - // Show the progression screen - binding.gameOverContainer.visibility = View.GONE - progressionScreen.visibility = View.VISIBLE - - // Display progression data - progressionScreen.showProgress(progressionManager, xpGained, newRewards, currentTheme) - } } \ No newline at end of file diff --git a/app/src/main/java/com/mintris/StatsActivity.kt b/app/src/main/java/com/mintris/StatsActivity.kt index c7d2e0e..e7f6f3e 100644 --- a/app/src/main/java/com/mintris/StatsActivity.kt +++ b/app/src/main/java/com/mintris/StatsActivity.kt @@ -44,7 +44,8 @@ class StatsActivity : AppCompatActivity() { } private fun loadThemePreference(): String { - return progressionManager.getSelectedTheme() + val prefs = getSharedPreferences("mintris_settings", MODE_PRIVATE) + return prefs.getString("selected_theme", PlayerProgressionManager.THEME_CLASSIC) ?: PlayerProgressionManager.THEME_CLASSIC } private fun applyTheme(themeId: String) { diff --git a/app/src/main/java/com/mintris/game/GameView.kt b/app/src/main/java/com/mintris/game/GameView.kt index 1095af8..fe388b5 100644 --- a/app/src/main/java/com/mintris/game/GameView.kt +++ b/app/src/main/java/com/mintris/game/GameView.kt @@ -2,14 +2,12 @@ package com.mintris.game import android.animation.ValueAnimator import android.content.Context -import android.graphics.BlurMaskFilter import android.graphics.Canvas import android.graphics.Color -import android.graphics.LinearGradient import android.graphics.Paint import android.graphics.Rect import android.graphics.RectF -import android.graphics.Shader +import android.graphics.BlurMaskFilter import android.os.Build import android.os.Handler import android.os.Looper @@ -153,7 +151,6 @@ class GameView @JvmOverloads constructor( // Block skin private var currentBlockSkin: String = "block_skin_1" private val blockSkinPaints = mutableMapOf() - private var currentThemeColor = Color.WHITE private enum class Direction { HORIZONTAL, VERTICAL @@ -176,10 +173,6 @@ class GameView @JvmOverloads constructor( // Start with paused state pause() - // Load saved block skin - val prefs = context.getSharedPreferences("mintris_progression", Context.MODE_PRIVATE) - currentBlockSkin = prefs.getString("selected_block_skin", "block_skin_1") ?: "block_skin_1" - // Connect our callbacks to the GameBoard gameBoard.onPieceMove = { onPieceMove?.invoke() } gameBoard.onPieceLock = { @@ -239,7 +232,6 @@ class GameView @JvmOverloads constructor( blockSkinPaints["block_skin_1"] = Paint().apply { color = Color.WHITE isAntiAlias = true - style = Paint.Style.FILL } // Neon skin @@ -252,8 +244,9 @@ class GameView @JvmOverloads constructor( // Retro skin blockSkinPaints["block_skin_3"] = Paint().apply { color = Color.parseColor("#FF5A5F") - isAntiAlias = false // Pixelated look - style = Paint.Style.FILL + isAntiAlias = true + style = Paint.Style.STROKE + strokeWidth = 2f } // Minimalist skin @@ -276,9 +269,6 @@ class GameView @JvmOverloads constructor( */ fun setBlockSkin(skinId: String) { currentBlockSkin = skinId - // Save the selection to SharedPreferences - val prefs = context.getSharedPreferences("mintris_progression", Context.MODE_PRIVATE) - prefs.edit().putString("selected_block_skin", skinId).commit() invalidate() } @@ -604,139 +594,61 @@ class GameView @JvmOverloads constructor( // Create a clone of the paint to avoid modifying the original val blockPaint = Paint(paint) - // Draw block based on current skin - when (currentBlockSkin) { - "block_skin_1" -> { // Classic - // Draw outer glow - blockGlowPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else Color.WHITE - canvas.drawRect(left - 2f, top - 2f, right + 2f, bottom + 2f, blockGlowPaint) - - // Draw block - blockPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else Color.WHITE - blockPaint.alpha = if (isGhost) 30 else 255 - canvas.drawRect(left, top, right, bottom, blockPaint) - - // Draw inner glow - glowPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else Color.WHITE - canvas.drawRect(left + 1f, top + 1f, right - 1f, bottom - 1f, glowPaint) + // Special handling for neon skin + if (currentBlockSkin == "block_skin_2") { + // Stronger outer glow for neon skin + blockGlowPaint.color = if (isGhost) Color.argb(30, 255, 0, 255) else Color.parseColor("#FF00FF") + blockGlowPaint.maskFilter = BlurMaskFilter(16f, BlurMaskFilter.Blur.OUTER) + canvas.drawRect(left - 4f, top - 4f, right + 4f, bottom + 4f, blockGlowPaint) + + // For neon, use semi-translucent fill with strong glowing edges + blockPaint.style = Paint.Style.FILL_AND_STROKE + blockPaint.strokeWidth = 2f + blockPaint.maskFilter = BlurMaskFilter(8f, BlurMaskFilter.Blur.NORMAL) + + if (isGhost) { + blockPaint.color = Color.argb(30, 255, 0, 255) + blockPaint.alpha = 30 + } else { + blockPaint.color = Color.parseColor("#66004D") // Darker magenta fill + blockPaint.alpha = 170 // More opaque to be more visible } - "block_skin_2" -> { // Neon - // Stronger outer glow for neon skin - blockGlowPaint.color = if (isGhost) Color.argb(30, 255, 0, 255) else Color.parseColor("#FF00FF") - blockGlowPaint.maskFilter = BlurMaskFilter(16f, BlurMaskFilter.Blur.OUTER) - canvas.drawRect(left - 4f, top - 4f, right + 4f, bottom + 4f, blockGlowPaint) - - // For neon, use semi-translucent fill with strong glowing edges - blockPaint.style = Paint.Style.FILL_AND_STROKE - blockPaint.strokeWidth = 2f - blockPaint.maskFilter = BlurMaskFilter(8f, BlurMaskFilter.Blur.NORMAL) - - if (isGhost) { - blockPaint.color = Color.argb(30, 255, 0, 255) - blockPaint.alpha = 30 - } else { - blockPaint.color = Color.parseColor("#66004D") // Darker magenta fill - blockPaint.alpha = 170 // More opaque to be more visible - } - - // Draw block with neon effect - canvas.drawRect(left, top, right, bottom, blockPaint) - - // Draw a brighter border for better visibility - val borderPaint = Paint().apply { - color = Color.parseColor("#FF00FF") - style = Paint.Style.STROKE - strokeWidth = 3f - alpha = 255 - isAntiAlias = true - maskFilter = BlurMaskFilter(6f, BlurMaskFilter.Blur.NORMAL) - } - canvas.drawRect(left, top, right, bottom, borderPaint) - - // Inner glow for neon blocks - glowPaint.color = if (isGhost) Color.argb(10, 255, 0, 255) else Color.parseColor("#FF00FF") - glowPaint.alpha = if (isGhost) 10 else 100 - glowPaint.style = Paint.Style.STROKE - glowPaint.strokeWidth = 2f - glowPaint.maskFilter = BlurMaskFilter(4f, BlurMaskFilter.Blur.NORMAL) - canvas.drawRect(left + 4f, top + 4f, right - 4f, bottom - 4f, glowPaint) - } - "block_skin_3" -> { // Retro - // Draw pixelated block with retro effect - blockPaint.color = if (isGhost) Color.argb(30, 255, 90, 95) else Color.parseColor("#FF5A5F") - blockPaint.alpha = if (isGhost) 30 else 255 - - // Draw main block - canvas.drawRect(left, top, right, bottom, blockPaint) - - // Draw pixelated highlights - val highlightPaint = Paint().apply { - color = Color.parseColor("#FF8A8F") - isAntiAlias = false - style = Paint.Style.FILL - } - // Top and left highlights - canvas.drawRect(left, top, right - 2f, top + 2f, highlightPaint) - canvas.drawRect(left, top, left + 2f, bottom - 2f, highlightPaint) - - // Draw pixelated shadows - val shadowPaint = Paint().apply { - color = Color.parseColor("#CC4A4F") - isAntiAlias = false - style = Paint.Style.FILL - } - // Bottom and right shadows - canvas.drawRect(left + 2f, bottom - 2f, right, bottom, shadowPaint) - canvas.drawRect(right - 2f, top + 2f, right, bottom - 2f, shadowPaint) - } - "block_skin_4" -> { // Minimalist - // Draw clean, simple block with subtle border - blockPaint.color = if (isGhost) Color.argb(30, 0, 0, 0) else Color.BLACK - blockPaint.alpha = if (isGhost) 30 else 255 - blockPaint.style = Paint.Style.FILL - canvas.drawRect(left, top, right, bottom, blockPaint) - - // Draw subtle border - val borderPaint = Paint().apply { - color = Color.parseColor("#333333") - style = Paint.Style.STROKE - strokeWidth = 1f - isAntiAlias = true - } - canvas.drawRect(left, top, right, bottom, borderPaint) - } - "block_skin_5" -> { // Galaxy - // Draw cosmic glow effect - blockGlowPaint.color = if (isGhost) Color.argb(30, 102, 252, 241) else Color.parseColor("#66FCF1") - blockGlowPaint.maskFilter = BlurMaskFilter(20f, BlurMaskFilter.Blur.OUTER) - canvas.drawRect(left - 8f, top - 8f, right + 8f, bottom + 8f, blockGlowPaint) - - // Draw main block with gradient - val gradient = LinearGradient( - left, top, right, bottom, - Color.parseColor("#66FCF1"), - Color.parseColor("#45B7AF"), - Shader.TileMode.CLAMP - ) - blockPaint.shader = gradient - blockPaint.color = if (isGhost) Color.argb(30, 102, 252, 241) else Color.parseColor("#66FCF1") - blockPaint.alpha = if (isGhost) 30 else 255 - blockPaint.style = Paint.Style.FILL - canvas.drawRect(left, top, right, bottom, blockPaint) - - // Draw star-like sparkles - if (!isGhost) { - val sparklePaint = Paint().apply { - color = Color.WHITE - style = Paint.Style.FILL - isAntiAlias = true - maskFilter = BlurMaskFilter(4f, BlurMaskFilter.Blur.NORMAL) - } - // Add small white dots for sparkle effect - canvas.drawCircle(left + 4f, top + 4f, 1f, sparklePaint) - canvas.drawCircle(right - 4f, bottom - 4f, 1f, sparklePaint) - } + + // Draw block with neon effect + canvas.drawRect(left, top, right, bottom, blockPaint) + + // Draw a brighter border for better visibility + val borderPaint = Paint().apply { + color = Color.parseColor("#FF00FF") + style = Paint.Style.STROKE + strokeWidth = 3f + alpha = 255 + isAntiAlias = true + maskFilter = BlurMaskFilter(6f, BlurMaskFilter.Blur.NORMAL) } + canvas.drawRect(left, top, right, bottom, borderPaint) + + // Inner glow for neon blocks - brighter than before + glowPaint.color = if (isGhost) Color.argb(10, 255, 0, 255) else Color.parseColor("#FF00FF") + glowPaint.alpha = if (isGhost) 10 else 100 // More visible inner glow + glowPaint.style = Paint.Style.STROKE + glowPaint.strokeWidth = 2f + glowPaint.maskFilter = BlurMaskFilter(4f, BlurMaskFilter.Blur.NORMAL) + canvas.drawRect(left + 4f, top + 4f, right - 4f, bottom - 4f, glowPaint) + } else { + // Standard rendering for other skins + // Draw outer glow + blockGlowPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else Color.WHITE + canvas.drawRect(left - 2f, top - 2f, right + 2f, bottom + 2f, blockGlowPaint) + + // Draw block with current skin + blockPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else blockPaint.color + blockPaint.alpha = if (isGhost) 30 else 255 + canvas.drawRect(left, top, right, bottom, blockPaint) + + // Draw inner glow + glowPaint.color = if (isGhost) Color.argb(30, 255, 255, 255) else Color.WHITE + canvas.drawRect(left + 1f, top + 1f, right - 1f, bottom - 1f, glowPaint) } // Draw pulse effect if animation is active and this is a pulsing line @@ -1051,26 +963,4 @@ class GameView @JvmOverloads constructor( } pulseAnimator?.start() } - - /** - * Set the theme color for the game view - */ - fun setThemeColor(color: Int) { - currentThemeColor = color - blockPaint.color = color - ghostBlockPaint.color = color - glowPaint.color = color - blockGlowPaint.color = color - borderGlowPaint.color = color - pulsePaint.color = color - invalidate() - } - - /** - * Set the background color for the game view - */ - override fun setBackgroundColor(color: Int) { - super.setBackgroundColor(color) - invalidate() - } } diff --git a/app/src/main/java/com/mintris/game/TitleScreen.kt b/app/src/main/java/com/mintris/game/TitleScreen.kt index 34627f7..4c7a80f 100644 --- a/app/src/main/java/com/mintris/game/TitleScreen.kt +++ b/app/src/main/java/com/mintris/game/TitleScreen.kt @@ -46,9 +46,8 @@ class TitleScreen @JvmOverloads constructor( // Callback for when the user touches the screen var onStartGame: (() -> Unit)? = null - // Theme color and background color + // Theme color private var themeColor = Color.WHITE - private var backgroundColor = Color.BLACK // Define tetromino shapes (I, O, T, S, Z, J, L) private val tetrominoShapes = arrayOf( @@ -111,7 +110,7 @@ class TitleScreen @JvmOverloads constructor( init { // Title text settings titlePaint.apply { - color = themeColor + color = Color.WHITE textSize = 120f textAlign = Paint.Align.CENTER typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD) @@ -120,7 +119,7 @@ class TitleScreen @JvmOverloads constructor( // "Touch to start" text settings promptPaint.apply { - color = themeColor + color = Color.WHITE textSize = 50f textAlign = Paint.Align.CENTER typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL) @@ -130,7 +129,7 @@ class TitleScreen @JvmOverloads constructor( // High scores text settings highScorePaint.apply { - color = themeColor + color = Color.WHITE textSize = 70f textAlign = Paint.Align.LEFT // Changed to LEFT alignment typeface = Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL) // Changed to monospace @@ -138,16 +137,16 @@ class TitleScreen @JvmOverloads constructor( alpha = 200 } - // General paint settings for tetrominos + // General paint settings for tetrominos (white) paint.apply { - color = themeColor + color = Color.WHITE style = Paint.Style.FILL isAntiAlias = true } // Glow paint settings for tetrominos glowPaint.apply { - color = themeColor + color = Color.WHITE style = Paint.Style.FILL isAntiAlias = true alpha = 60 @@ -185,8 +184,8 @@ class TitleScreen @JvmOverloads constructor( try { super.onDraw(canvas) - // Draw background using the current background color - canvas.drawColor(backgroundColor) + // Draw background + canvas.drawColor(Color.BLACK) // Add any pending tetrominos tetrominos.addAll(tetrominosToAdd) @@ -341,7 +340,7 @@ class TitleScreen @JvmOverloads constructor( glowPaint.color = themeColor // Update background color - backgroundColor = when (themeId) { + setBackgroundColor(when (themeId) { PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221") PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A") @@ -349,29 +348,8 @@ class TitleScreen @JvmOverloads constructor( PlayerProgressionManager.THEME_MINIMALIST -> Color.WHITE PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#0B0C10") else -> Color.BLACK - } + }) invalidate() } - - /** - * Set the theme color for the title screen - */ - fun setThemeColor(color: Int) { - themeColor = color - titlePaint.color = color - promptPaint.color = color - highScorePaint.color = color - paint.color = color - glowPaint.color = color - invalidate() - } - - /** - * Set the background color for the title screen - */ - override fun setBackgroundColor(color: Int) { - backgroundColor = color - invalidate() - } } \ No newline at end of file diff --git a/app/src/main/java/com/mintris/model/PlayerProgressionManager.kt b/app/src/main/java/com/mintris/model/PlayerProgressionManager.kt index 0ddc2a7..bf62a6a 100644 --- a/app/src/main/java/com/mintris/model/PlayerProgressionManager.kt +++ b/app/src/main/java/com/mintris/model/PlayerProgressionManager.kt @@ -5,7 +5,6 @@ import android.content.SharedPreferences import com.mintris.R import kotlin.math.pow import kotlin.math.roundToInt -import kotlin.math.min /** * Manages player progression, experience points, and unlockable rewards @@ -95,22 +94,21 @@ class PlayerProgressionManager(context: Context) { */ fun calculateGameXP(score: Int, lines: Int, level: Int, gameTime: Long, tetrisCount: Int, perfectClearCount: Int): Long { - // Base XP from score with level multiplier (capped at level 10) - val cappedLevel = min(level, 10) - val scoreXP = (score * (1 + LEVEL_MULTIPLIER * cappedLevel)).toLong() + // Base XP from score with level multiplier + val scoreXP = (score * (1 + LEVEL_MULTIPLIER * level)).toLong() - // XP from lines cleared (reduced for higher levels) - val linesXP = lines * XP_PER_LINE * (1 - (level - 1) * 0.05).coerceAtLeast(0.5) + // XP from lines cleared + val linesXP = lines * XP_PER_LINE - // XP from special moves (reduced for higher levels) - val tetrisBonus = tetrisCount * TETRIS_XP_BONUS * (1 - (level - 1) * 0.05).coerceAtLeast(0.5) - val perfectClearBonus = perfectClearCount * PERFECT_CLEAR_XP_BONUS * (1 - (level - 1) * 0.05).coerceAtLeast(0.5) + // XP from special moves + val tetrisBonus = tetrisCount * TETRIS_XP_BONUS + val perfectClearBonus = perfectClearCount * PERFECT_CLEAR_XP_BONUS - // Time bonus (reduced for longer games) - val timeBonus = (gameTime / 60000) * TIME_XP_PER_MINUTE * (1 - (gameTime / 3600000) * 0.1).coerceAtLeast(0.5) + // Time bonus (to reward longer gameplay) + val timeBonus = (gameTime / 60000) * TIME_XP_PER_MINUTE // XP per minute played // Calculate total XP - return (scoreXP + linesXP + tetrisBonus + perfectClearBonus + timeBonus).toLong() + return scoreXP + linesXP + tetrisBonus + perfectClearBonus + timeBonus } /** @@ -283,19 +281,21 @@ class PlayerProgressionManager(context: Context) { private const val KEY_UNLOCKED_THEMES = "unlocked_themes" private const val KEY_UNLOCKED_BLOCKS = "unlocked_blocks" private const val KEY_UNLOCKED_BADGES = "unlocked_badges" - private const val KEY_SELECTED_THEME = "selected_theme" private const val KEY_SELECTED_BLOCK_SKIN = "selected_block_skin" + private const val KEY_SELECTED_THEME = "selected_theme" - // XP constants - private const val BASE_XP = 3000L - private const val XP_CURVE_FACTOR = 2.0 - private const val LEVEL_MULTIPLIER = 0.03 - private const val XP_PER_LINE = 40L - private const val TETRIS_XP_BONUS = 150L - private const val PERFECT_CLEAR_XP_BONUS = 300L - private const val TIME_XP_PER_MINUTE = 20L + // XP curve parameters + private const val BASE_XP = 4000.0 // Base XP for level 1 (reduced from 5000) + private const val XP_CURVE_FACTOR = 1.9 // Exponential factor for XP curve (reduced from 2.2) - // Theme constants + // XP calculation constants + private const val LEVEL_MULTIPLIER = 0.15 // 15% bonus per level (increased from 10%) + private const val XP_PER_LINE = 15L // Increased from 10 + private const val TETRIS_XP_BONUS = 75L // Increased from 50 + private const val PERFECT_CLEAR_XP_BONUS = 250L // Increased from 200 + private const val TIME_XP_PER_MINUTE = 8L // Increased from 5 + + // Theme IDs with required levels const val THEME_CLASSIC = "theme_classic" const val THEME_NEON = "theme_neon" const val THEME_MONOCHROME = "theme_monochrome" @@ -326,7 +326,7 @@ class PlayerProgressionManager(context: Context) { */ fun setSelectedBlockSkin(skinId: String) { if (unlockedBlocks.contains(skinId)) { - prefs.edit().putString(KEY_SELECTED_BLOCK_SKIN, skinId).commit() + prefs.edit().putString(KEY_SELECTED_BLOCK_SKIN, skinId).apply() } } diff --git a/app/src/main/java/com/mintris/ui/ProgressionScreen.kt b/app/src/main/java/com/mintris/ui/ProgressionScreen.kt index 8c5d4d4..bc67809 100644 --- a/app/src/main/java/com/mintris/ui/ProgressionScreen.kt +++ b/app/src/main/java/com/mintris/ui/ProgressionScreen.kt @@ -31,9 +31,6 @@ class ProgressionScreen @JvmOverloads constructor( private val rewardsContainer: LinearLayout private val continueButton: TextView - // Current theme - private var currentTheme: String = PlayerProgressionManager.THEME_CLASSIC - // Callback for when the player dismisses the screen var onContinue: (() -> Unit)? = null @@ -65,9 +62,6 @@ class ProgressionScreen @JvmOverloads constructor( newRewards: List, themeId: String = PlayerProgressionManager.THEME_CLASSIC ) { - // Update current theme - currentTheme = themeId - // Hide rewards container initially if there are no new rewards rewardsContainer.visibility = if (newRewards.isEmpty()) View.GONE else View.INVISIBLE @@ -80,39 +74,20 @@ class ProgressionScreen @JvmOverloads constructor( playerLevelText.text = "Player Level: $playerLevel" xpGainText.text = "+$xpGained XP" - // Update level up text visibility - val progressionTitle = findViewById(R.id.progression_title) - progressionTitle.visibility = if (newRewards.any { it.contains("Level") }) View.VISIBLE else View.GONE + // Begin animation sequence + xpProgressBar.setXPValues(playerLevel, currentXP, xpForNextLevel) - // Start with initial animations - AnimatorSet().apply { - // Fade in the XP gain text - val xpTextAnimator = ObjectAnimator.ofFloat(xpGainText, "alpha", 0f, 1f).apply { - duration = 800 - interpolator = AccelerateDecelerateInterpolator() - } - - // Set up the XP progress bar animation sequence - val xpBarAnimator = ObjectAnimator.ofFloat(xpProgressBar, "alpha", 0f, 1f).apply { - duration = 800 - interpolator = AccelerateDecelerateInterpolator() - } - - // Play animations in sequence - play(xpTextAnimator) - play(xpBarAnimator).after(xpTextAnimator) - start() + // Animate XP gain text entrance + val xpTextAnimator = ObjectAnimator.ofFloat(xpGainText, "alpha", 0f, 1f).apply { + duration = 500 } - // Set initial progress bar state - xpProgressBar.setXPValues(playerLevel, currentXP - xpGained, xpForNextLevel) - - // Animate the XP gain after a short delay + // Schedule animation for the XP bar after text appears postDelayed({ xpProgressBar.animateXPGain(xpGained, playerLevel, currentXP, xpForNextLevel) - }, 1000) // Increased delay to 1 second for better visual flow + }, 600) - // If there are new rewards, show them with animation after XP bar animation + // If there are new rewards, show them with animation if (newRewards.isNotEmpty()) { // Create reward cards rewardsContainer.removeAllViews() @@ -138,12 +113,18 @@ class ProgressionScreen @JvmOverloads constructor( card.animate() .alpha(1f) .translationY(0f) - .setDuration(600) // Increased duration for smoother animation - .setStartDelay((i * 200).toLong()) // Increased delay between cards + .setDuration(400) + .setStartDelay((i * 150).toLong()) .setInterpolator(OvershootInterpolator()) .start() } - }, 2500) // Increased delay to wait for XP bar animation to finish + }, 2000) // Wait for XP bar animation to finish + } + + // Start with initial animations + AnimatorSet().apply { + play(xpTextAnimator) + start() } } @@ -156,17 +137,8 @@ class ProgressionScreen @JvmOverloads constructor( cardElevation = 4f useCompatPadding = true - // Set background color based on current theme - val backgroundColor = when (currentTheme) { - PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK - PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221") - PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A") - PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#3F2832") - PlayerProgressionManager.THEME_MINIMALIST -> Color.WHITE - PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#0B0C10") - else -> Color.BLACK - } - setCardBackgroundColor(backgroundColor) + // Default background color - will be adjusted based on theme + setCardBackgroundColor(Color.BLACK) layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, @@ -195,8 +167,6 @@ class ProgressionScreen @JvmOverloads constructor( * Apply the current theme to the progression screen */ fun applyTheme(themeId: String) { - currentTheme = themeId - // Get reference to the title text val progressionTitle = findViewById(R.id.progression_title) val rewardsTitle = findViewById(R.id.rewards_title) @@ -278,10 +248,10 @@ class ProgressionScreen @JvmOverloads constructor( } } - // Update XP progress bar theme color + // Set theme color on XP progress bar xpProgressBar.setThemeColor(xpThemeColor) - // Update reward card colors + // Update card colors for any existing reward cards updateRewardCardColors(themeId) } @@ -289,7 +259,8 @@ class ProgressionScreen @JvmOverloads constructor( * Update colors of existing reward cards to match the theme */ private fun updateRewardCardColors(themeId: String) { - val backgroundColor = when (themeId) { + // Color for card backgrounds based on theme + val cardBackgroundColor = when (themeId) { PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221") PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A") @@ -299,9 +270,28 @@ class ProgressionScreen @JvmOverloads constructor( else -> Color.BLACK } + // Text color for rewards based on theme + val rewardTextColor = when (themeId) { + PlayerProgressionManager.THEME_CLASSIC -> Color.WHITE + PlayerProgressionManager.THEME_NEON -> Color.parseColor("#FF00FF") + PlayerProgressionManager.THEME_MONOCHROME -> Color.LTGRAY + PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#FF5A5F") + PlayerProgressionManager.THEME_MINIMALIST -> Color.BLACK + PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#66FCF1") + else -> Color.WHITE + } + + // Update each card in the rewards container for (i in 0 until rewardsContainer.childCount) { val card = rewardsContainer.getChildAt(i) as? CardView - card?.setCardBackgroundColor(backgroundColor) + card?.let { + it.setCardBackgroundColor(cardBackgroundColor) + + // Update text color in the card + if (it.childCount > 0 && it.getChildAt(0) is TextView) { + (it.getChildAt(0) as TextView).setTextColor(rewardTextColor) + } + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/mintris/ui/XPProgressBar.kt b/app/src/main/java/com/mintris/ui/XPProgressBar.kt index 930da2f..c50ab6d 100644 --- a/app/src/main/java/com/mintris/ui/XPProgressBar.kt +++ b/app/src/main/java/com/mintris/ui/XPProgressBar.kt @@ -99,8 +99,6 @@ class XPProgressBar @JvmOverloads constructor( */ fun setThemeColor(color: Int) { themeColor = color - progressPaint.color = color - textPaint.color = color levelBadgePaint.color = color invalidate() } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2224e92..ddea78a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -62,40 +62,36 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/white" - android:textSize="32sp" - android:textStyle="bold" - android:fontFamily="sans-serif" - tools:text="score: 0" /> + android:textSize="24sp" + android:fontFamily="sans-serif-light" + tools:text="Score: 0" /> + android:textSize="24sp" + android:fontFamily="sans-serif-light" + tools:text="Level: 1" /> + android:textSize="24sp" + android:fontFamily="sans-serif-light" + tools:text="Lines: 0" /> + android:textSize="24sp" + android:fontFamily="sans-serif-light" + tools:text="Combo: 0" /> @@ -135,18 +131,16 @@ android:layout_height="wrap_content" android:text="@string/game_over" android:textColor="@color/white" - android:textSize="36sp" - android:textStyle="bold" - android:fontFamily="sans-serif" /> + android:textSize="24sp" + android:textStyle="bold" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" /> + android:textSize="18sp" />