mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 15:15:21 +01:00
Disable diagonal inputs and prevent accidental hard drops. Block back swipe gesture to prevent accidental app exits.
This commit is contained in:
parent
809ae33e5e
commit
8661fd8a80
3 changed files with 105 additions and 7 deletions
|
@ -32,6 +32,8 @@ import java.util.*
|
|||
import android.graphics.Color
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import android.graphics.Rect
|
||||
import android.view.KeyEvent
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
|
@ -73,6 +75,9 @@ class MainActivity : AppCompatActivity() {
|
|||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
// Disable Android back gesture to prevent accidental app exits
|
||||
disableAndroidBackGesture()
|
||||
|
||||
// Initialize game components
|
||||
gameBoard = GameBoard()
|
||||
gameHaptics = GameHaptics(this)
|
||||
|
@ -646,4 +651,83 @@ class MainActivity : AppCompatActivity() {
|
|||
else -> Color.WHITE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the Android system back gesture to prevent accidental exits
|
||||
*/
|
||||
private fun disableAndroidBackGesture() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// Set the entire window to be excluded from the system gesture areas
|
||||
window.decorView.post {
|
||||
// Create a list of rectangles representing the edges of the screen to exclude from system gestures
|
||||
val gestureInsets = window.decorView.rootWindowInsets?.systemGestureInsets
|
||||
if (gestureInsets != null) {
|
||||
val leftEdge = Rect(0, 0, 50, window.decorView.height)
|
||||
val rightEdge = Rect(window.decorView.width - 50, 0, window.decorView.width, window.decorView.height)
|
||||
val bottomEdge = Rect(0, window.decorView.height - 50, window.decorView.width, window.decorView.height)
|
||||
|
||||
window.decorView.systemGestureExclusionRects = listOf(leftEdge, rightEdge, bottomEdge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add an on back pressed callback to handle back button/gesture
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
onBackPressedDispatcher.addCallback(this, object : androidx.activity.OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
// If we're playing the game, handle it as a pause action instead of exiting
|
||||
if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
|
||||
gameView.pause()
|
||||
gameMusic.pause()
|
||||
showPauseMenu()
|
||||
binding.pauseStartButton.visibility = View.GONE
|
||||
binding.resumeButton.visibility = View.VISIBLE
|
||||
} else if (binding.pauseContainer.visibility == View.VISIBLE) {
|
||||
// If pause menu is showing, handle as a resume
|
||||
resumeGame()
|
||||
} else if (binding.gameOverContainer.visibility == View.VISIBLE) {
|
||||
// If game over is showing, go back to title
|
||||
hideGameOver()
|
||||
showTitleScreen()
|
||||
} else if (titleScreen.visibility == View.VISIBLE) {
|
||||
// If title screen is showing, allow normal back behavior (exit app)
|
||||
isEnabled = false
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// For Android 11 (R) to Android 12 (S), use the WindowInsetsController to disable gestures
|
||||
window.insetsController?.systemBarsBehavior =
|
||||
android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely block the hardware back button during gameplay
|
||||
*/
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
// If back button is pressed
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
// Handle back button press as a pause action during gameplay
|
||||
if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
|
||||
gameView.pause()
|
||||
gameMusic.pause()
|
||||
showPauseMenu()
|
||||
binding.pauseStartButton.visibility = View.GONE
|
||||
binding.resumeButton.visibility = View.VISIBLE
|
||||
return true // Consume the event
|
||||
} else if (binding.pauseContainer.visibility == View.VISIBLE) {
|
||||
// If pause menu is showing, handle as a resume
|
||||
resumeGame()
|
||||
return true // Consume the event
|
||||
} else if (binding.gameOverContainer.visibility == View.VISIBLE) {
|
||||
// If game over is showing, go back to title
|
||||
hideGameOver()
|
||||
showTitleScreen()
|
||||
return true // Consume the event
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
}
|
|
@ -39,7 +39,8 @@ class GameView @JvmOverloads constructor(
|
|||
|
||||
// Game state
|
||||
private var isRunning = false
|
||||
private var isPaused = false
|
||||
var isPaused = false // Changed from private to public to allow access from MainActivity
|
||||
private var score = 0
|
||||
|
||||
// Callbacks
|
||||
var onNextPieceChanged: (() -> Unit)? = null
|
||||
|
@ -128,14 +129,16 @@ class GameView @JvmOverloads constructor(
|
|||
private var lastTapTime = 0L
|
||||
private var lastRotationTime = 0L
|
||||
private var lastMoveTime = 0L
|
||||
private var minSwipeVelocity = 800 // Minimum velocity for swipe to be considered a hard drop
|
||||
private var minSwipeVelocity = 1200 // Increased from 800 to require more deliberate swipes
|
||||
private val maxTapMovement = 20f // Maximum movement allowed for a tap (in pixels)
|
||||
private val minTapTime = 100L // Minimum time for a tap (in milliseconds)
|
||||
private val rotationCooldown = 150L // Minimum time between rotations (in milliseconds)
|
||||
private val moveCooldown = 50L // Minimum time between move haptics (in milliseconds)
|
||||
private var lockedDirection: Direction? = null // Track the locked movement direction
|
||||
private val minMovementThreshold = 0.75f // Minimum movement threshold relative to block size
|
||||
private val directionLockThreshold = 1.5f // Threshold for direction lock relative to block size
|
||||
private val directionLockThreshold = 2.5f // Increased from 1.5f to make direction locking more aggressive
|
||||
private val isStrictDirectionLock = true // Enable strict direction locking to prevent diagonal inputs
|
||||
private val minHardDropDistance = 1.5f // Minimum distance (in blocks) for hard drop gesture
|
||||
|
||||
private enum class Direction {
|
||||
HORIZONTAL, VERTICAL
|
||||
|
@ -612,12 +615,14 @@ class GameView @JvmOverloads constructor(
|
|||
|
||||
// Check if movement exceeds threshold
|
||||
if (absDeltaX > blockSize * minMovementThreshold || absDeltaY > blockSize * minMovementThreshold) {
|
||||
// Determine dominant direction
|
||||
// Determine dominant direction with stricter criteria
|
||||
if (absDeltaX > absDeltaY * directionLockThreshold) {
|
||||
lockedDirection = Direction.HORIZONTAL
|
||||
} else if (absDeltaY > absDeltaX * directionLockThreshold) {
|
||||
lockedDirection = Direction.VERTICAL
|
||||
}
|
||||
// If strict direction lock is enabled and we couldn't determine a clear direction, don't set one
|
||||
// This prevents diagonal movements from being recognized
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,8 +666,12 @@ class GameView @JvmOverloads constructor(
|
|||
val deltaY = event.y - startY
|
||||
val deltaX = event.x - startX
|
||||
|
||||
// If the movement was fast and downward, treat as hard drop
|
||||
if (moveTime > 0 && deltaY > blockSize * 0.5f && (deltaY / moveTime) * 1000 > minSwipeVelocity) {
|
||||
// Only allow hard drops with a deliberate downward swipe
|
||||
// Requires: predominantly vertical movement, minimum distance, and minimum velocity
|
||||
if (moveTime > 0 &&
|
||||
deltaY > blockSize * minHardDropDistance && // Require longer swipe for hard drop
|
||||
(deltaY / moveTime) * 1000 > minSwipeVelocity &&
|
||||
abs(deltaX) < abs(deltaY) * 0.3f) { // Require more purely vertical movement (reduced from 0.5f to 0.3f)
|
||||
gameBoard.hardDrop()
|
||||
invalidate()
|
||||
} else if (moveTime < minTapTime &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue