mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 00:25:20 +01:00
feat: change hold piece to swipe up gesture and improve movement sensitivity
This commit is contained in:
parent
103a21d9b7
commit
47c9bbddec
2 changed files with 86 additions and 57 deletions
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -99,12 +99,28 @@
|
|||
</LinearLayout>
|
||||
|
||||
<!-- Next Piece Preview -->
|
||||
<com.mintris.game.NextPieceView
|
||||
android:id="@+id/nextPieceView"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="end" />
|
||||
android:layout_gravity="end"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NEXT"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="sans-serif"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<com.mintris.game.NextPieceView
|
||||
android:id="@+id/nextPieceView"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Settings button -->
|
||||
<ImageButton
|
||||
|
@ -119,6 +135,16 @@
|
|||
android:src="@drawable/ic_pause" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Hold Piece Preview -->
|
||||
<com.mintris.game.HoldPieceView
|
||||
android:id="@+id/holdPieceView"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- Game Over overlay -->
|
||||
<LinearLayout
|
||||
android:id="@+id/gameOverContainer"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue