mirror of
https://github.com/cmclark00/mintris.git
synced 2025-05-18 00:05:21 +01:00
Fix auto-drop issue for pieces near top of board, add spawn grace period and hard drop cooldown
This commit is contained in:
parent
a47d83d905
commit
1c57c438ce
2 changed files with 91 additions and 13 deletions
|
@ -133,6 +133,10 @@ class GameView @JvmOverloads constructor(
|
|||
private var lastTapTime = 0L
|
||||
private var lastRotationTime = 0L
|
||||
private var lastMoveTime = 0L
|
||||
private var lastHardDropTime = 0L // Track when the last hard drop occurred
|
||||
private val hardDropCooldown = 250L // Reduced from 500ms to 250ms
|
||||
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 minTapTime = 100L // Minimum time for a tap (in milliseconds)
|
||||
|
@ -171,7 +175,12 @@ class GameView @JvmOverloads constructor(
|
|||
|
||||
// Connect our callbacks to the GameBoard
|
||||
gameBoard.onPieceMove = { onPieceMove?.invoke() }
|
||||
gameBoard.onPieceLock = { onPieceLock?.invoke() }
|
||||
gameBoard.onPieceLock = {
|
||||
// Freeze touch events for a brief period after a piece locks
|
||||
touchFreezeUntil = System.currentTimeMillis() + pieceLockFreezeTime
|
||||
Log.d(TAG, "Piece locked - freezing touch events until ${touchFreezeUntil}")
|
||||
onPieceLock?.invoke()
|
||||
}
|
||||
gameBoard.onLineClear = { lineCount, clearedLines ->
|
||||
Log.d(TAG, "Received line clear from GameBoard: $lineCount lines")
|
||||
try {
|
||||
|
@ -697,6 +706,13 @@ class GameView @JvmOverloads constructor(
|
|||
return true
|
||||
}
|
||||
|
||||
// Ignore touch events during the freeze period after a piece locks
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime < touchFreezeUntil) {
|
||||
Log.d(TAG, "Ignoring touch event - freeze active for ${touchFreezeUntil - currentTime}ms more")
|
||||
return true
|
||||
}
|
||||
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
// Record start of touch
|
||||
|
@ -781,21 +797,34 @@ class GameView @JvmOverloads constructor(
|
|||
val moveTime = System.currentTimeMillis() - lastTapTime
|
||||
val deltaY = event.y - startY
|
||||
val deltaX = event.x - startX
|
||||
val currentTime = System.currentTimeMillis()
|
||||
|
||||
// Only allow hard drops with a deliberate downward swipe
|
||||
// Requires: predominantly vertical movement, minimum distance, and minimum velocity
|
||||
if (moveTime > 0 &&
|
||||
deltaY > blockSize * minHardDropDistance && // Require longer swipe for hard drop
|
||||
// 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) { // Require more purely vertical movement (reduced from 0.5f to 0.3f)
|
||||
gameBoard.hardDrop()
|
||||
invalidate()
|
||||
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("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
|
||||
invalidate()
|
||||
}
|
||||
} else if (moveTime < minTapTime &&
|
||||
abs(deltaY) < maxTapMovement &&
|
||||
abs(deltaX) < maxTapMovement) {
|
||||
// Quick tap with minimal movement (rotation)
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - lastRotationTime >= rotationCooldown) {
|
||||
Log.d("GameView", "Rotation detected")
|
||||
gameBoard.rotate()
|
||||
lastRotationTime = currentTime
|
||||
invalidate()
|
||||
|
|
|
@ -63,6 +63,10 @@ class GameBoard(
|
|||
// Store the last cleared lines
|
||||
private val lastClearedLines = mutableListOf<Int>()
|
||||
|
||||
// Add spawn protection variables
|
||||
private var pieceSpawnTime = 0L
|
||||
private val spawnGracePeriod = 250L // Changed from 150ms to 250ms
|
||||
|
||||
init {
|
||||
spawnNextPiece()
|
||||
spawnPiece()
|
||||
|
@ -122,6 +126,8 @@ class GameBoard(
|
|||
* Spawns the current tetromino at the top of the board
|
||||
*/
|
||||
fun spawnPiece() {
|
||||
Log.d(TAG, "spawnPiece() started - current states: isHardDropInProgress=$isHardDropInProgress, isPieceLocking=$isPieceLocking")
|
||||
|
||||
currentPiece = nextPiece
|
||||
spawnNextPiece()
|
||||
|
||||
|
@ -130,9 +136,15 @@ class GameBoard(
|
|||
x = (width - getWidth()) / 2
|
||||
y = 0
|
||||
|
||||
Log.d(TAG, "spawnPiece() - new piece spawned at position (${x},${y}), type=${type}")
|
||||
|
||||
// Set the spawn time for the grace period
|
||||
pieceSpawnTime = System.currentTimeMillis()
|
||||
|
||||
// Check if the piece can be placed (Game Over condition)
|
||||
if (!canMove(0, 0)) {
|
||||
isGameOver = true
|
||||
Log.d(TAG, "spawnPiece() - Game Over condition detected")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +185,13 @@ class GameBoard(
|
|||
onPieceMove?.invoke()
|
||||
true
|
||||
} else {
|
||||
// Check if we're within the spawn grace period
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - pieceSpawnTime < spawnGracePeriod) {
|
||||
Log.d(TAG, "moveDown() - not locking piece due to spawn grace period (${currentTime - pieceSpawnTime}ms < ${spawnGracePeriod}ms)")
|
||||
return false
|
||||
}
|
||||
|
||||
lockPiece()
|
||||
false
|
||||
}
|
||||
|
@ -191,8 +210,19 @@ class GameBoard(
|
|||
* Hard drop the current piece
|
||||
*/
|
||||
fun hardDrop() {
|
||||
if (isHardDropInProgress || isPieceLocking) return // Prevent multiple hard drops
|
||||
if (isHardDropInProgress || isPieceLocking) {
|
||||
Log.d(TAG, "hardDrop() called but blocked: isHardDropInProgress=$isHardDropInProgress, isPieceLocking=$isPieceLocking")
|
||||
return // Prevent multiple hard drops
|
||||
}
|
||||
|
||||
// Check if we're within the spawn grace period
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - pieceSpawnTime < spawnGracePeriod) {
|
||||
Log.d(TAG, "hardDrop() - blocked due to spawn grace period (${currentTime - pieceSpawnTime}ms < ${spawnGracePeriod}ms)")
|
||||
return
|
||||
}
|
||||
|
||||
Log.d(TAG, "hardDrop() started - setting isHardDropInProgress=true")
|
||||
isHardDropInProgress = true
|
||||
val piece = currentPiece ?: return
|
||||
|
||||
|
@ -202,12 +232,16 @@ class GameBoard(
|
|||
dropDistance++
|
||||
}
|
||||
|
||||
Log.d(TAG, "hardDrop() - piece will drop $dropDistance cells, position before: (${piece.x},${piece.y})")
|
||||
|
||||
// Move piece down until it can't move anymore
|
||||
while (canMove(0, 1)) {
|
||||
piece.y++
|
||||
onPieceMove?.invoke()
|
||||
}
|
||||
|
||||
Log.d(TAG, "hardDrop() - piece final position: (${piece.x},${piece.y})")
|
||||
|
||||
// Add hard drop points (2 points per cell)
|
||||
score += dropDistance * 2
|
||||
|
||||
|
@ -298,7 +332,12 @@ class GameBoard(
|
|||
* Lock the current piece in place
|
||||
*/
|
||||
private fun lockPiece() {
|
||||
if (isPieceLocking) return // Prevent recursive locking
|
||||
if (isPieceLocking) {
|
||||
Log.d(TAG, "lockPiece() called but blocked: isPieceLocking=$isPieceLocking")
|
||||
return // Prevent recursive locking
|
||||
}
|
||||
|
||||
Log.d(TAG, "lockPiece() started - setting isPieceLocking=true, current isHardDropInProgress=$isHardDropInProgress")
|
||||
isPieceLocking = true
|
||||
|
||||
val piece = currentPiece ?: return
|
||||
|
@ -324,15 +363,25 @@ class GameBoard(
|
|||
// Find and clear lines immediately
|
||||
findAndClearLines()
|
||||
|
||||
// IMPORTANT: Reset the hard drop flag before spawning a new piece
|
||||
// This prevents the immediate hard drop of the next piece
|
||||
if (isHardDropInProgress) {
|
||||
Log.d(TAG, "lockPiece() - resetting isHardDropInProgress=false BEFORE spawning new piece")
|
||||
isHardDropInProgress = false
|
||||
}
|
||||
|
||||
// Log piece position before spawning new piece
|
||||
Log.d(TAG, "lockPiece() - about to spawn new piece at y=${piece.y}, isHardDropInProgress=$isHardDropInProgress")
|
||||
|
||||
// Spawn new piece immediately
|
||||
spawnPiece()
|
||||
|
||||
// Allow holding piece again after locking
|
||||
canHold = true
|
||||
|
||||
// Reset both states after everything is done
|
||||
// Reset locking state
|
||||
isPieceLocking = false
|
||||
isHardDropInProgress = false
|
||||
Log.d(TAG, "lockPiece() completed - reset flags: isPieceLocking=false, isHardDropInProgress=$isHardDropInProgress")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue