Fix piece freezing at spawn after returning from background - #49
Open
nilsauf wants to merge 2 commits into
Open
Conversation
pauseGame() cancelled the grace-period/clear/trail timers but left the fields non-null, so resumeGame()'s timer == null guards skipped restarting them — the piece could freeze permanently after switching apps. Also locks a grounded piece immediately on resume if its lock delay expired while backgrounded, and resumes music independent of pause state.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hej,
I experienced this bug while playing on android: backgrounding the app mid-game (switching to the launcher and back) could leave the current piece permanently stuck — no gravity, no input response — forcing a restart and losing all progress.
Root cause:
GameLogic.pauseGame()cancelledgracePeriodTimer,clearAnimationTimer, andtrailAnimationTimeron backgrounding, but never reset the fields back to null. resumeGame()only restarts each timer when its field is null:Since the field still held the cancelled (dead) Timer object, this guard was always false, so the timer never restarted. If the app was backgrounded during the ~200ms spawn grace window or a line-clear animation,
isNewPieceGracePeriod/isAnimatingClearstayed true forever, andmovePieceDown()starts with:if (isAnimatingClear || isNewPieceGracePeriod) return;so every gravity tick became a no-op — matching the reported "stuck at the top, won't fall" symptom. Because it only triggers when backgrounding lands inside one of those short windows, it reproduced intermittently rather than every time.
The Fix:
pauseGame()now nulls outgameTimer,clearAnimationTimer,trailAnimationTimer, andgracePeriodTimerafter cancelling them, soresumeGame()'s guards correctly restart them._lockDelayPausedflag so a grounded piece whose lock delay deadline expired entirely while backgrounded locks immediately on resume, instead of silently doing nothing.Added test/lifecycle_timer_restart_test.dart: 7 tests covering spawn grace period, hard drop, gravity, line-clear animation, trail animation, and lock delay all across a pause/resume cycle. Confirmed each test fails against the old code and passes with the fix.