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"> + + + + + + + +