diff --git a/app/src/main/java/com/mintris/MainActivity.kt b/app/src/main/java/com/mintris/MainActivity.kt
index 8b4602e..3e94bac 100644
--- a/app/src/main/java/com/mintris/MainActivity.kt
+++ b/app/src/main/java/com/mintris/MainActivity.kt
@@ -172,15 +172,6 @@ class MainActivity : AppCompatActivity() {
binding.nextPieceView.invalidate()
}
- // Set up hold piece preview
- binding.holdPieceView.setGameView(gameView)
- gameBoard.onPieceLock = {
- binding.holdPieceView.invalidate()
- }
- gameBoard.onPieceMove = {
- binding.holdPieceView.invalidate()
- }
-
// Set up music toggle
binding.musicToggle.setOnClickListener {
isMusicEnabled = !isMusicEnabled
diff --git a/app/src/main/java/com/mintris/game/GameView.kt b/app/src/main/java/com/mintris/game/GameView.kt
index f1608f4..1095af8 100644
--- a/app/src/main/java/com/mintris/game/GameView.kt
+++ b/app/src/main/java/com/mintris/game/GameView.kt
@@ -140,21 +140,15 @@ 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 = 30f // Increased from 20f to 30f for more lenient tap detection
+ 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 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.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 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 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"
@@ -809,33 +803,46 @@ 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
- lastTapTime = currentTime // Set the tap time when touch starts
+ lockedDirection = null // Reset direction lock
- // Reset direction lock
- lockedDirection = null
+ // 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
}
MotionEvent.ACTION_MOVE -> {
val deltaX = event.x - lastTouchX
val deltaY = event.y - lastTouchY
+ val currentTime = System.currentTimeMillis()
- // Check if we should lock direction
+ // Determine movement direction if not locked
if (lockedDirection == null) {
val absDeltaX = abs(deltaX)
val absDeltaY = abs(deltaY)
- if (absDeltaX > blockSize * directionLockThreshold ||
- absDeltaY > blockSize * directionLockThreshold) {
- // Lock to the dominant direction
- lockedDirection = if (absDeltaX > absDeltaY) {
- Direction.HORIZONTAL
- } else {
- Direction.VERTICAL
+ // 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 strict direction lock is enabled and we couldn't determine a clear direction, don't set one
+ // This prevents diagonal movements from being recognized
}
}
@@ -874,43 +881,38 @@ class GameView @JvmOverloads constructor(
}
MotionEvent.ACTION_UP -> {
- val deltaX = event.x - startX
+ // Calculate movement speed for potential fling detection
+ val moveTime = System.currentTimeMillis() - lastTapTime
val deltaY = event.y - startY
- val moveTime = currentTime - lastTapTime
+ val deltaX = event.x - startX
+ val currentTime = System.currentTimeMillis()
- // 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 hold
- Log.d(TAG, "Hold detected - deltaY: $deltaY, ratio: ${abs(deltaX) / abs(deltaY)}")
- gameBoard.holdPiece()
- lastHoldTime = currentTime
- gameHaptics?.vibrateForPieceMove()
- invalidate()
- }
- }
- // 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")
+ // 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")
} else {
// Process the hard drop
- Log.d(TAG, "Hard drop detected - deltaY: $deltaY, velocity: ${(deltaY / moveTime) * 1000}, ratio: ${abs(deltaX) / abs(deltaY)}")
+ Log.d("GameView", "Hard drop detected - deltaY: $deltaY, velocity: ${(deltaY / moveTime) * 1000}, ratio: ${abs(deltaX) / abs(deltaY)}")
gameBoard.hardDrop()
- lastHardDropTime = currentTime
+ lastHardDropTime = currentTime // Update the last hard drop time
invalidate()
}
- }
- // Check for rotation (quick tap with minimal movement)
- else if (moveTime < minTapTime &&
+ } else if (moveTime < minTapTime &&
abs(deltaY) < maxTapMovement &&
abs(deltaX) < maxTapMovement) {
+ // Quick tap with minimal movement (rotation)
if (currentTime - lastRotationTime >= rotationCooldown) {
- Log.d(TAG, "Rotation detected - moveTime: $moveTime, deltaX: $deltaX, deltaY: $deltaY")
+ Log.d("GameView", "Rotation detected")
gameBoard.rotate()
lastRotationTime = currentTime
invalidate()
@@ -952,11 +954,6 @@ 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/java/com/mintris/game/HoldPieceView.kt b/app/src/main/java/com/mintris/game/HoldPieceView.kt
deleted file mode 100644
index 6f51022..0000000
--- a/app/src/main/java/com/mintris/game/HoldPieceView.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.mintris.game
-
-import android.content.Context
-import android.graphics.BlurMaskFilter
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.Paint
-import android.util.AttributeSet
-import android.view.View
-import com.mintris.model.GameBoard
-import com.mintris.model.Tetromino
-import kotlin.math.min
-
-/**
- * View that displays the currently held piece
- */
-class HoldPieceView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : View(context, attrs, defStyleAttr) {
-
- private var gameView: GameView? = null
- private var gameBoard: GameBoard? = null
-
- // Rendering
- private val blockPaint = Paint().apply {
- color = Color.WHITE
- isAntiAlias = true
- style = Paint.Style.FILL
- }
-
- private val glowPaint = Paint().apply {
- color = Color.WHITE
- alpha = 40
- isAntiAlias = true
- style = Paint.Style.STROKE
- strokeWidth = 1.5f
- maskFilter = BlurMaskFilter(8f, BlurMaskFilter.Blur.OUTER)
- }
-
- private val blockGlowPaint = Paint().apply {
- color = Color.WHITE
- alpha = 60
- isAntiAlias = true
- style = Paint.Style.FILL
- maskFilter = BlurMaskFilter(12f, BlurMaskFilter.Blur.OUTER)
- }
-
- /**
- * Set the game view reference
- */
- fun setGameView(view: GameView) {
- gameView = view
- gameBoard = view.getGameBoard()
- }
-
- /**
- * Get the game board reference
- */
- private fun getGameBoard(): GameBoard? = gameBoard
-
- override fun onDraw(canvas: Canvas) {
- super.onDraw(canvas)
-
- // Get the held piece from game board
- gameBoard?.let {
- it.getHoldPiece()?.let { piece ->
- val width = piece.getWidth()
- val height = piece.getHeight()
-
- // Calculate block size for the preview (smaller than main board)
- val previewBlockSize = min(
- canvas.width.toFloat() / (width + 2),
- canvas.height.toFloat() / (height + 2)
- )
-
- // Center the piece in the preview area
- val previewLeft = (canvas.width - width * previewBlockSize) / 2
- val previewTop = (canvas.height - height * previewBlockSize) / 2
-
- // Draw subtle background glow
- val glowPaint = Paint().apply {
- color = Color.WHITE
- alpha = 10
- maskFilter = BlurMaskFilter(previewBlockSize * 0.5f, BlurMaskFilter.Blur.OUTER)
- }
- canvas.drawRect(
- previewLeft - previewBlockSize,
- previewTop - previewBlockSize,
- previewLeft + width * previewBlockSize + previewBlockSize,
- previewTop + height * previewBlockSize + previewBlockSize,
- glowPaint
- )
-
- // Draw the held piece
- for (y in 0 until height) {
- for (x in 0 until width) {
- if (piece.isBlockAt(x, y)) {
- val left = previewLeft + x * previewBlockSize
- val top = previewTop + y * previewBlockSize
- val right = left + previewBlockSize
- val bottom = top + previewBlockSize
-
- // Draw outer glow
- blockGlowPaint.color = Color.WHITE
- canvas.drawRect(
- left - 2f,
- top - 2f,
- right + 2f,
- bottom + 2f,
- blockGlowPaint
- )
-
- // Draw block
- blockPaint.color = Color.WHITE
- canvas.drawRect(left, top, right, bottom, blockPaint)
-
- // Draw inner glow
- glowPaint.color = Color.WHITE
- canvas.drawRect(
- left + 1f,
- top + 1f,
- right - 1f,
- bottom - 1f,
- glowPaint
- )
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/preview_border.xml b/app/src/main/res/drawable/preview_border.xml
deleted file mode 100644
index a28f95b..0000000
--- a/app/src/main/res/drawable/preview_border.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 9b2b84a..2224e92 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -99,28 +99,12 @@
-
-
-
-
-
-
+ android:layout_gravity="end" />
-
-
-