diff --git a/android-app/app/src/main/java/com/tetris3d/views/TetrisGameView.kt b/android-app/app/src/main/java/com/tetris3d/views/TetrisGameView.kt index f6376bd..690d5a4 100644 --- a/android-app/app/src/main/java/com/tetris3d/views/TetrisGameView.kt +++ b/android-app/app/src/main/java/com/tetris3d/views/TetrisGameView.kt @@ -55,14 +55,16 @@ class TetrisGameView @JvmOverloads constructor( private val autoRepeatHandler = Handler(Looper.getMainLooper()) private var isAutoRepeating = false private var currentMovement: (() -> Unit)? = null - private val autoRepeatDelay = 40L // Faster repeat for smoother movement - private val initialAutoRepeatDelay = 100L // Initial delay before repeating + private val autoRepeatDelay = 150L // Increased delay between movements for slower response + private val initialAutoRepeatDelay = 200L // Increased initial delay private val interpolator = DecelerateInterpolator(1.5f) // Touch tracking for continuous swipe private var lastTouchX = 0f private var lastTouchY = 0f - private var swipeThreshold = 15f // Distance needed to trigger a move while dragging + private var swipeThreshold = 30f // Increased threshold to prevent accidental moves + private var lastMoveTime = 0L + private val moveCooldown = 200L // Add cooldown between movements // Refresh timer private val refreshHandler = Handler(Looper.getMainLooper()) @@ -329,6 +331,12 @@ class TetrisGameView @JvmOverloads constructor( MotionEvent.ACTION_MOVE -> { val diffX = event.x - lastTouchX val diffY = event.y - lastTouchY + val currentTime = System.currentTimeMillis() + + // Check if cooldown has elapsed since last move + if (currentTime - lastMoveTime < moveCooldown) { + return true + } // Check if drag distance exceeds threshold for continuous movement if (abs(diffX) > swipeThreshold && abs(diffX) > abs(diffY)) { @@ -341,6 +349,7 @@ class TetrisGameView @JvmOverloads constructor( // Update last position after processing the move lastTouchX = event.x lastTouchY = event.y + lastMoveTime = currentTime invalidate() return true } else if (abs(diffY) > swipeThreshold && abs(diffY) > abs(diffX)) { @@ -350,6 +359,7 @@ class TetrisGameView @JvmOverloads constructor( // Update last position after processing the move lastTouchX = event.x lastTouchY = event.y + lastMoveTime = currentTime invalidate() return true } @@ -401,15 +411,17 @@ class TetrisGameView @JvmOverloads constructor( return true } - override fun onSingleTapUp(e: MotionEvent): Boolean { + override fun onSingleTapConfirmed(e: MotionEvent): Boolean { + // Use onSingleTapConfirmed instead of onSingleTapUp for better tap detection + // Determine if tap is on left or right side of screen val screenMiddle = width / 2 if (e.x < screenMiddle) { - // Left side - rotate counterclockwise (in a real 3D game) + // Left side - rotate X axis (horizontal rotation) game?.rotate3DX() } else { - // Right side - rotate clockwise + // Right side - rotate Y axis (vertical rotation) game?.rotate3DY() } @@ -431,12 +443,13 @@ class TetrisGameView @JvmOverloads constructor( // Horizontal swipe if (abs(velocityX) > minSwipeVelocity && abs(diffX) > minSwipeDistance) { if (diffX > 0) { - // Swipe right - use auto-repeat for smoother movement - startAutoRepeat { game?.moveRight() } + // Swipe right - move right once, not auto-repeat + game?.moveRight() } else { - // Swipe left - use auto-repeat for smoother movement - startAutoRepeat { game?.moveLeft() } + // Swipe left - move left once, not auto-repeat + game?.moveLeft() } + invalidate() return true } } else { diff --git a/android-app/app/src/main/res/layout/activity_main.xml b/android-app/app/src/main/res/layout/activity_main.xml index 964f9f0..66fb2ba 100644 --- a/android-app/app/src/main/res/layout/activity_main.xml +++ b/android-app/app/src/main/res/layout/activity_main.xml @@ -29,12 +29,26 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="16dp" - app:layout_constraintBottom_toTopOf="@+id/controlsHint" + app:layout_constraintBottom_toTopOf="@+id/rotationHint" app:layout_constraintDimensionRatio="1:2" app:layout_constraintEnd_toStartOf="@+id/infoPanel" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/gameTitle" /> + +