diff --git a/app/src/main/java/com/mintris/game/GameView.kt b/app/src/main/java/com/mintris/game/GameView.kt
index 1095af8..f1608f4 100644
--- a/app/src/main/java/com/mintris/game/GameView.kt
+++ b/app/src/main/java/com/mintris/game/GameView.kt
@@ -140,15 +140,21 @@ class GameView @JvmOverloads constructor(
private var touchFreezeUntil = 0L // Time until which touch events should be ignored
private val pieceLockFreezeTime = 300L // Time to freeze touch events after piece locks
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 maxTapMovement = 30f // Increased from 20f to 30f for more lenient tap detection
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 val doubleTapTimeout = 400L // Increased from 300ms to 400ms for more lenient double tap detection
+ private var lastTapX = 0f // X coordinate of last tap
+ private var lastTapY = 0f // Y coordinate of last tap
+ private var lastHoldTime = 0L // Track when the last hold occurred
+ private val holdCooldown = 250L // Minimum time between holds
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 = 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 minMovementThreshold = 0.5f // Reduced from 0.75f for more sensitive movement
+ private val directionLockThreshold = 1.5f // Reduced from 2.5f to make direction locking less aggressive
+ private val isStrictDirectionLock = true // Re-enabled strict direction locking to prevent diagonal inputs
private val minHardDropDistance = 1.5f // Minimum distance (in blocks) for hard drop gesture
+ private val minHoldDistance = 2.0f // Minimum distance (in blocks) for hold gesture
// Block skin
private var currentBlockSkin: String = "block_skin_1"
@@ -803,46 +809,33 @@ class GameView @JvmOverloads constructor(
when (event.action) {
MotionEvent.ACTION_DOWN -> {
- // Record start of touch
startX = event.x
startY = event.y
lastTouchX = event.x
lastTouchY = event.y
- lockedDirection = null // Reset direction lock
+ lastTapTime = currentTime // Set the tap time when touch starts
- // Check for double tap (rotate)
- val currentTime = System.currentTimeMillis()
- if (currentTime - lastTapTime < 200) { // Reduced from 250ms for faster response
- // Double tap detected, rotate the piece
- if (currentTime - lastRotationTime >= rotationCooldown) {
- gameBoard.rotate()
- lastRotationTime = currentTime
- invalidate()
- }
- }
- lastTapTime = currentTime
+ // Reset direction lock
+ lockedDirection = null
}
MotionEvent.ACTION_MOVE -> {
val deltaX = event.x - lastTouchX
val deltaY = event.y - lastTouchY
- val currentTime = System.currentTimeMillis()
- // Determine movement direction if not locked
+ // Check if we should lock direction
if (lockedDirection == null) {
val absDeltaX = abs(deltaX)
val absDeltaY = abs(deltaY)
- // Check if movement exceeds threshold
- if (absDeltaX > blockSize * minMovementThreshold || absDeltaY > blockSize * minMovementThreshold) {
- // Determine dominant direction with stricter criteria
- if (absDeltaX > absDeltaY * directionLockThreshold) {
- lockedDirection = Direction.HORIZONTAL
- } else if (absDeltaY > absDeltaX * directionLockThreshold) {
- lockedDirection = Direction.VERTICAL
+ if (absDeltaX > blockSize * directionLockThreshold ||
+ absDeltaY > blockSize * directionLockThreshold) {
+ // Lock to the dominant direction
+ lockedDirection = if (absDeltaX > absDeltaY) {
+ Direction.HORIZONTAL
+ } else {
+ 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
}
}
@@ -881,38 +874,43 @@ class GameView @JvmOverloads constructor(
}
MotionEvent.ACTION_UP -> {
- // Calculate movement speed for potential fling detection
- val moveTime = System.currentTimeMillis() - lastTapTime
- val deltaY = event.y - startY
val deltaX = event.x - startX
- val currentTime = System.currentTimeMillis()
+ val deltaY = event.y - startY
+ val moveTime = currentTime - lastTapTime
- // Check if this might have been a hard drop gesture
- val isVerticalSwipe = moveTime > 0 &&
- deltaY > blockSize * minHardDropDistance &&
- (deltaY / moveTime) * 1000 > minSwipeVelocity &&
- abs(deltaX) < abs(deltaY) * 0.3f
-
- // Check cooldown separately for better logging
- val isCooldownActive = currentTime - lastHardDropTime <= hardDropCooldown
-
- if (isVerticalSwipe) {
- if (isCooldownActive) {
- // Log when we're blocking a hard drop due to cooldown
- Log.d("GameView", "Hard drop blocked by cooldown - time since last: ${currentTime - lastHardDropTime}ms, cooldown: ${hardDropCooldown}ms")
+ // Check for hold gesture (swipe up)
+ if (deltaY < -blockSize * minHoldDistance &&
+ abs(deltaX) / abs(deltaY) < 0.5f) {
+ if (currentTime - lastHoldTime < holdCooldown) {
+ Log.d(TAG, "Hold blocked by cooldown - time since last: ${currentTime - lastHoldTime}ms, cooldown: ${holdCooldown}ms")
} else {
- // Process the hard drop
- Log.d("GameView", "Hard drop detected - deltaY: $deltaY, velocity: ${(deltaY / moveTime) * 1000}, ratio: ${abs(deltaX) / abs(deltaY)}")
- gameBoard.hardDrop()
- lastHardDropTime = currentTime // Update the last hard drop time
+ // Process the hold
+ Log.d(TAG, "Hold detected - deltaY: $deltaY, ratio: ${abs(deltaX) / abs(deltaY)}")
+ gameBoard.holdPiece()
+ lastHoldTime = currentTime
+ gameHaptics?.vibrateForPieceMove()
invalidate()
}
- } else if (moveTime < minTapTime &&
+ }
+ // Check for hard drop
+ else if (deltaY > blockSize * minHardDropDistance &&
+ abs(deltaX) / abs(deltaY) < 0.5f) {
+ if (currentTime - lastHardDropTime < hardDropCooldown) {
+ Log.d(TAG, "Hard drop blocked by cooldown - time since last: ${currentTime - lastHardDropTime}ms, cooldown: ${hardDropCooldown}ms")
+ } else {
+ // Process the hard drop
+ Log.d(TAG, "Hard drop detected - deltaY: $deltaY, velocity: ${(deltaY / moveTime) * 1000}, ratio: ${abs(deltaX) / abs(deltaY)}")
+ gameBoard.hardDrop()
+ lastHardDropTime = currentTime
+ invalidate()
+ }
+ }
+ // Check for rotation (quick tap with minimal movement)
+ else if (moveTime < minTapTime &&
abs(deltaY) < maxTapMovement &&
abs(deltaX) < maxTapMovement) {
- // Quick tap with minimal movement (rotation)
if (currentTime - lastRotationTime >= rotationCooldown) {
- Log.d("GameView", "Rotation detected")
+ Log.d(TAG, "Rotation detected - moveTime: $moveTime, deltaX: $deltaX, deltaY: $deltaY")
gameBoard.rotate()
lastRotationTime = currentTime
invalidate()
@@ -954,6 +952,11 @@ class GameView @JvmOverloads constructor(
return gameBoard.getNextPiece()
}
+ /**
+ * Get the game board instance
+ */
+ fun getGameBoard(): GameBoard = gameBoard
+
/**
* Clean up resources when view is detached
*/
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 2224e92..9b2b84a 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -99,12 +99,28 @@
-
+ android:layout_gravity="end"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+