diff --git a/app/games/fast-piggie/index.js b/app/games/fast-piggie/index.js index cbe4db0..e11b213 100644 --- a/app/games/fast-piggie/index.js +++ b/app/games/fast-piggie/index.js @@ -240,6 +240,9 @@ let _clickEnabled = false; let _selectedWedge = -1; // for keyboard navigation let _hoveredWedge = -1; // for mouse hover highlighting let _roundTimer = null; // setTimeout handle +let _imageFlashTimer = null; // setTimeout handle before image flash +// Give the board a small lead-in so previous wedge highlights clear before image flash starts. +const ROUND_IMAGE_FLASH_DELAY_MS = 15; /** * Updates the score, round count, and display time in the UI. @@ -302,6 +305,15 @@ function _highlightKeyboardSelection() { function _runRound() { if (!game.isRunning()) return; + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } + if (_roundTimer) { + clearTimeout(_roundTimer); + _roundTimer = null; + } + _clickEnabled = false; _selectedWedge = -1; const round = game.generateRound(game.getLevel(), game.getSpeedLevel()); @@ -319,19 +331,23 @@ function _runRound() { _currentRound = { ...round, slotAssignment }; const { width, height } = _canvas; - drawBoard( - _ctx, width, height, wedgeCount, imageCount, _images, - outlierWedgeIndex, true, slotAssignment, - ); + clearImages(_ctx, width, height, wedgeCount); + _imageFlashTimer = setTimeout(() => { + _imageFlashTimer = null; + drawBoard( + _ctx, width, height, wedgeCount, imageCount, _images, + outlierWedgeIndex, true, slotAssignment, + ); - _roundTimer = setTimeout(() => { - clearImages(_ctx, width, height, wedgeCount); - _currentRound._imagesHiddenAt = Date.now(); - _clickEnabled = true; - _hoveredWedge = -1; - _selectedWedge = -1; - _canvas.focus(); - }, displayDurationMs); + _roundTimer = setTimeout(() => { + clearImages(_ctx, width, height, wedgeCount); + _currentRound._imagesHiddenAt = Date.now(); + _clickEnabled = true; + _hoveredWedge = -1; + _selectedWedge = -1; + _canvas.focus(); + }, displayDurationMs); + }, ROUND_IMAGE_FLASH_DELAY_MS); } /** @@ -614,6 +630,10 @@ export default { * @returns {Promise} Game result */ async stop() { + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } if (_roundTimer) { clearTimeout(_roundTimer); _roundTimer = null; @@ -652,6 +672,10 @@ export default { * Reset the game to its initial state. */ reset() { + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } if (_roundTimer) { clearTimeout(_roundTimer); _roundTimer = null; diff --git a/app/games/fast-piggie/tests/index.test.js b/app/games/fast-piggie/tests/index.test.js index 93e70d9..8cef8eb 100644 --- a/app/games/fast-piggie/tests/index.test.js +++ b/app/games/fast-piggie/tests/index.test.js @@ -1185,6 +1185,22 @@ describe('_triggerFlash and next-round timers', () => { }); }); +describe('_runRound image flash timing', () => { + const mockedDisplayDurationMs = 2000; + + it('schedules the image flash 15ms after wedges are hidden', () => { + const setTimeoutSpy = jest.spyOn(globalThis, 'setTimeout'); + try { + plugin.start(); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 15); + jest.advanceTimersByTime(15); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), mockedDisplayDurationMs); + } finally { + setTimeoutSpy.mockRestore(); + } + }); +}); + // =========================================================================== // loadImages onerror path and init() .catch() fallback // (f[4] and f[33] in index.js)