diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 924b03a..8815afb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,6 @@ (R.id.inPauseThemeSelector) + inPauseThemeSelector?.onThemeSelected = { themeId: String -> + // Apply the new theme + applyTheme(themeId) + + // Provide haptic feedback + gameHaptics.vibrateForPieceLock() + + // Refresh the pause menu + showPauseMenu() + } + // Set up block skin selector blockSkinSelector.onBlockSkinSelected = { skinId: String -> // Apply the new block skin @@ -145,6 +158,19 @@ class MainActivity : AppCompatActivity() { gameHaptics.vibrateForPieceLock() } + // Set up landscape mode block skin selector if available + val inPauseBlockSkinSelector = findViewById(R.id.inPauseBlockSkinSelector) + inPauseBlockSkinSelector?.onBlockSkinSelected = { skinId: String -> + // Apply the new block skin + gameView.setBlockSkin(skinId) + + // Save the selection + progressionManager.setSelectedBlockSkin(skinId) + + // Provide haptic feedback + gameHaptics.vibrateForPieceLock() + } + // Set up title screen titleScreen.onStartGame = { titleScreen.visibility = View.GONE @@ -437,8 +463,8 @@ class MainActivity : AppCompatActivity() { binding.resumeButton.visibility = View.GONE // Update level badge - binding.pauseLevelBadge.setLevel(progressionManager.getPlayerLevel()) - binding.pauseLevelBadge.setThemeColor(getThemeColor(currentTheme)) + binding.pauseLevelBadge?.setLevel(progressionManager.getPlayerLevel()) + binding.pauseLevelBadge?.setThemeColor(getThemeColor(currentTheme)) // Get theme color val textColor = getThemeColor(currentTheme) @@ -461,26 +487,41 @@ class MainActivity : AppCompatActivity() { binding.resumeButton.setTextColor(textColor) binding.highScoresButton.setTextColor(textColor) binding.statsButton.setTextColor(textColor) - binding.pauseLevelText.setTextColor(textColor) + binding.pauseLevelText?.setTextColor(textColor) binding.pauseLevelUpButton.setTextColor(textColor) binding.pauseLevelDownButton.setTextColor(textColor) binding.settingsButton.setTextColor(textColor) binding.musicToggle.setColorFilter(textColor) // Apply theme colors to text elements - binding.settingsTitle.setTextColor(textColor) + binding.settingsTitle?.setTextColor(textColor) binding.selectLevelText.setTextColor(textColor) binding.musicText.setTextColor(textColor) - // Update theme selector + // Update theme selector - handle both standard and landscape versions updateThemeSelector() - // Update block skin selector + // Handle landscape mode theme selectors (using null-safe calls) + val inPauseThemeSelector = findViewById(R.id.inPauseThemeSelector) + inPauseThemeSelector?.updateThemes( + unlockedThemes = progressionManager.getUnlockedThemes(), + currentTheme = currentTheme + ) + + // Update block skin selector - handle both standard and landscape versions blockSkinSelector.updateBlockSkins( progressionManager.getUnlockedBlocks(), gameView.getCurrentBlockSkin(), progressionManager.getPlayerLevel() ) + + // Handle landscape mode block skin selectors (using null-safe calls) + val inPauseBlockSkinSelector = findViewById(R.id.inPauseBlockSkinSelector) + inPauseBlockSkinSelector?.updateBlockSkins( + progressionManager.getUnlockedBlocks(), + gameView.getCurrentBlockSkin(), + progressionManager.getPlayerLevel() + ) } /** diff --git a/app/src/main/java/com/mintris/game/GameView.kt b/app/src/main/java/com/mintris/game/GameView.kt index 24e8f0c..f5043f1 100644 --- a/app/src/main/java/com/mintris/game/GameView.kt +++ b/app/src/main/java/com/mintris/game/GameView.kt @@ -1019,6 +1019,16 @@ class GameView @JvmOverloads constructor( return true } + // Define the game board boundaries + val boardRight = boardLeft + (gameBoard.width * blockSize) + val boardBottom = boardTop + (gameBoard.height * blockSize) + + // Determine if touch is on left side, right side, or within board area + val isLeftSide = event.x < boardLeft + val isRightSide = event.x > boardRight + val isWithinBoard = event.x >= boardLeft && event.x <= boardRight && + event.y >= boardTop && event.y <= boardBottom + when (event.action) { MotionEvent.ACTION_DOWN -> { startX = event.x @@ -1051,36 +1061,81 @@ class GameView @JvmOverloads constructor( } } - // Handle movement based on locked direction - when (lockedDirection) { - Direction.HORIZONTAL -> { - if (abs(deltaX) > blockSize * minMovementThreshold) { - if (deltaX > 0) { - gameBoard.moveRight() - } else { - gameBoard.moveLeft() - } - lastTouchX = event.x - if (currentTime - lastMoveTime >= moveCooldown) { - gameHaptics?.vibrateForPieceMove() - lastMoveTime = currentTime - } + // Special handling for landscape mode - side controls + if (isLeftSide) { + // Left side controls - move left + if (deltaY < -blockSize * minMovementThreshold) { + // Swipe up on left side - rotate + if (currentTime - lastRotationTime >= rotationCooldown) { + gameBoard.rotate() + lastRotationTime = currentTime + gameHaptics?.vibrateForPieceMove() invalidate() } + } else if (deltaY > blockSize * minMovementThreshold) { + // Swipe down on left side - move left + gameBoard.moveLeft() + lastTouchY = event.y + if (currentTime - lastMoveTime >= moveCooldown) { + gameHaptics?.vibrateForPieceMove() + lastMoveTime = currentTime + } + invalidate() } - Direction.VERTICAL -> { - if (deltaY > blockSize * minMovementThreshold) { - gameBoard.softDrop() - lastTouchY = event.y - if (currentTime - lastMoveTime >= moveCooldown) { - gameHaptics?.vibrateForPieceMove() - lastMoveTime = currentTime - } + } else if (isRightSide) { + // Right side controls - move right + if (deltaY < -blockSize * minMovementThreshold) { + // Swipe up on right side - hold piece + if (currentTime - lastHoldTime >= holdCooldown) { + gameBoard.holdPiece() + lastHoldTime = currentTime + gameHaptics?.vibrateForPieceMove() invalidate() } + } else if (deltaY > blockSize * minMovementThreshold) { + // Swipe down on right side - move right + gameBoard.moveRight() + lastTouchY = event.y + if (currentTime - lastMoveTime >= moveCooldown) { + gameHaptics?.vibrateForPieceMove() + lastMoveTime = currentTime + } + invalidate() } - null -> { - // No direction lock yet, don't process movement + } + // Standard touch controls for main board area or portrait mode + else { + // Handle movement based on locked direction + when (lockedDirection) { + Direction.HORIZONTAL -> { + if (abs(deltaX) > blockSize * minMovementThreshold) { + if (deltaX > 0) { + gameBoard.moveRight() + } else { + gameBoard.moveLeft() + } + lastTouchX = event.x + if (currentTime - lastMoveTime >= moveCooldown) { + gameHaptics?.vibrateForPieceMove() + lastMoveTime = currentTime + } + invalidate() + } + } + Direction.VERTICAL -> { + if (deltaY > blockSize * minMovementThreshold) { + gameBoard.softDrop() + lastTouchY = event.y + if (currentTime - lastMoveTime >= moveCooldown) { + gameHaptics?.vibrateForPieceMove() + lastMoveTime = currentTime + } + invalidate() + } + } + null -> { + // No direction lock yet, don't process movement + } } } } @@ -1090,6 +1145,32 @@ class GameView @JvmOverloads constructor( val deltaY = event.y - startY val moveTime = currentTime - lastTapTime + // Special handling for taps on game board or sides + if (moveTime < minTapTime * 1.5 && + abs(deltaY) < maxTapMovement * 1.5 && + abs(deltaX) < maxTapMovement * 1.5) { + + if (isLeftSide) { + // Tap on left side - move left + gameBoard.moveLeft() + gameHaptics?.vibrateForPieceMove() + invalidate() + } else if (isRightSide) { + // Tap on right side - move right + gameBoard.moveRight() + gameHaptics?.vibrateForPieceMove() + invalidate() + } else if (isWithinBoard && currentTime - lastRotationTime >= rotationCooldown) { + // Tap on board - rotate + gameBoard.rotate() + lastRotationTime = currentTime + gameHaptics?.vibrateForPieceMove() + invalidate() + } + return true + } + + // Long swipe handling for hard drops and holds // Check for hold gesture (swipe up) if (deltaY < -blockSize * minHoldDistance && abs(deltaX) / abs(deltaY) < 0.5f) { @@ -1125,17 +1206,6 @@ class GameView @JvmOverloads constructor( gameBoard.softDrop() invalidate() } - // Check for rotation (quick tap with minimal movement) - else if (moveTime < minTapTime * 1.5 && // Increased from 1.0 to 1.5 for more lenient timing - abs(deltaY) < maxTapMovement * 1.5 && // Increased from 1.0 to 1.5 for more lenient movement - abs(deltaX) < maxTapMovement * 1.5) { // Increased from 1.0 to 1.5 for more lenient movement - if (currentTime - lastRotationTime >= rotationCooldown) { - Log.d(TAG, "Rotation detected - moveTime: $moveTime, deltaX: $deltaX, deltaY: $deltaY") - gameBoard.rotate() - lastRotationTime = currentTime - invalidate() - } - } // Reset direction lock lockedDirection = null diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml new file mode 100644 index 0000000..20ad154 --- /dev/null +++ b/app/src/main/res/layout-land/activity_main.xml @@ -0,0 +1,606 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +