Countdown when resuming from Pause

I noticed in my game that if I press the Menu button to pause, when I press it again, I'm immediately thrown into a situation where I'm going to die immediately.

To mitigate this circumstance, I wanted a "countdown", so the player would have a little time to get readjusted to the game and its controls before resuming.

This is the code I wrote to make this happen. I save off my normal playdate.update() routine, swap in a temporary one that displays the countdown, then swap it back in at the end. I'm sure this could be done better, so feel free to post improvements!

Just in case anyone finds this useful!

local gfx <const> = playdate.graphics

…

local lastFrame = nil
function playdate.gameWillPause()
	
	-- conditionally save off the current frame so we can do a countdown animation when coming back
	-- only do this if gameplay is happening (that's what the "ModePlay" check does; your game will need to do a different check)
	if Mode.getCurrentMode().className == "ModePlay" then
		lastFrame = gfx.getDisplayImage()
	end
	
end

function playdate.gameWillResume()
	
	-- only run this routine if a screen image was saved off
	if lastFrame == nil then return end
	
	-- do a countdown so player isn't thrown right back into the middle of things
	-- swap in my own playdate.update routine in favor of the standard one
	local saveOffUpdateFunction = playdate.update
	local frames = 3 * playdate.display.getRefreshRate()
	playdate.update = function()

		gfx.setColor( gfx.kColorBlack )
		gfx.setImageDrawMode( gfx.kDrawModeFillBlack )
		lastFrame:drawFaded( 0, 0, 0.5, gfx.image.kDitherTypeBayer2x2 ) -- draw game image, faded
		gfx.fillCircleAtPoint( 200, 112, 18 ) -- draw background for countdown number

		gfx.setImageDrawMode( gfx.kDrawModeFillWhite )
		gfx.setColor( gfx.kColorWhite )
		gfx.drawCircleAtPoint( 200, 112, 18 ) -- draw outline for circle

		local countdown = ( frames // playdate.display.getRefreshRate() ) + 1
		gfx.drawTextAligned( string.format( "_%d_", countdown ), 200, 105, kTextAlignment.center )

		frames -= 1
		if frames == 0 then
			playdate.update = saveOffUpdateFunction -- restore
			lastFrame = nil -- don't need to save any longer
		end

	end
	
end
6 Likes

I figured out a much simpler way to do this, leveraging playdate.wait():

local gfx <const> = playdate.graphics

function playdate.gameWillResume()

	-- save off the current playdate.update so we can restore it at the end of the countdown
	local saveOffUpdate = playdate.update
	
	playdate.update = 
	function()	
		
		-- draw the countdown
		gfx.clear()
		gfx.drawText( "3", 200, 120 )
		playdate.wait( 1000 )
		gfx.clear()
		gfx.drawText( "2", 200, 120 )
		playdate.wait( 1000 )
		gfx.clear()
		gfx.drawText( "1", 200, 120 )
		playdate.wait( 1000 )
		gfx.clear()
		
		-- restore the "real" playdate.update
		playdate.update = saveOffUpdate

	end
		
end
4 Likes