A simple stopwatch / timer example

I needed a stopwatch / timer with pause and restart functionality for my game. So I created a simple test main.lua file and I thought some of you might find it useful. It’s using the concept of enterFrame to keep track of time. I know there are examples but this is just another one that might be helpful to a fellow solar 2d developer. It’s been influenced by older posts a few years ago.

Simply copy and paste the code below and save it as main.lua to see it in action. It could be improved but it’s a good starter for somebody that might need this kind of functionality in their game / app. You can also modify the number of decimals / precision really easily.

local widget = require("widget")

local prevFrameTime, currentFrameTime
local deltaFrameTime = 0
local totalTime = 0
local timeAtPause = 0
local lengthOfPause = 0
local totalPauseTime = 0

local pauseButton
local resumeButton
local resetButton
local startButton

local DECIMAL_PLACES = 3

local title = display.newText( "Example stop watch using enterFrame", 0, 0, native.systemFont, 35 )
title.x = display.contentCenterX
title.y = display.contentCenterY - 200

local txt_counter = display.newText( totalTime, 0, 0, native.systemFont, 55 )
txt_counter.x = display.contentCenterX
txt_counter.y = title.y + 100
txt_counter:setTextColor( 255, 255, 255 )

local function enterFrame(e)
    local currentFrameTime

    currentFrameTime = system.getTimer() - totalPauseTime

    if prevFrameTime then
        --calculate how many milliseconds since last frame
        deltaFrameTime = currentFrameTime - prevFrameTime
    end
    
    prevFrameTime = currentFrameTime

    --this is the total time in milliseconds
    totalTime = totalTime + deltaFrameTime

    txt_counter.text = string.format("%." .. DECIMAL_PLACES .. "f",(totalTime * 0.001))
end

Runtime:addEventListener( "enterFrame", enterFrame )

local function pauseStopWatch(event)
    if (event.phase == "ended") then
        Runtime:removeEventListener("enterFrame",enterFrame)
        timeAtPause = system.getTimer()
        resumeButton:setEnabled(true)
        pauseButton:setEnabled(false)
    end
end

local function resumeStopWatch(event)
    if (event.phase == "ended") then
        Runtime:addEventListener( "enterFrame", enterFrame )
        lengthOfPause = system.getTimer() - timeAtPause
        totalPauseTime = totalPauseTime + lengthOfPause
        resumeButton:setEnabled(false)
        pauseButton:setEnabled(true)
    end
end

local function resetStopWatch(event)
    if (event.phase == "ended") then
        Runtime:removeEventListener("enterFrame",enterFrame)
        txt_counter.text = string.format("%." .. DECIMAL_PLACES .. "f", 0)
        startButton:setEnabled(true)
        pauseButton:setEnabled(false)
        resumeButton:setEnabled(false)
    end
end

local function startStopWatch(event)
    if (event.phase == "ended") then
        prevFrameTime, currentFrameTime = nil
        deltaFrameTime = 0
        totalTime = 0
        timeAtPause = 0
        lengthOfPause = 0
        totalPauseTime = 0
        Runtime:addEventListener( "enterFrame", enterFrame )
        startButton:setEnabled(false)
        pauseButton:setEnabled(true)
    end
end

pauseButton = widget.newButton(
    {
        left = 100,
        top = 200,
        id = "button1",
        label = "Pause",
        onEvent = pauseStopWatch,
        fontSize = 40
    }
)

pauseButton.x = display.contentCenterX - 100
pauseButton.y = txt_counter.y + 100

resumeButton = widget.newButton(
    {
        left = 100,
        top = 200,
        id = "button1",
        label = "Resume",
        onEvent = resumeStopWatch,
        fontSize = 40
    }
)

resumeButton.x = display.contentCenterX + 100
resumeButton.y = pauseButton.y

resetButton = widget.newButton(
    {
        left = 100,
        top = 200,
        id = "button1",
        label = "Reset",
        onEvent = resetStopWatch,
        fontSize = 40
    }
)

resetButton.x = pauseButton.x
resetButton.y = pauseButton.y + 100

startButton = widget.newButton(
    {
        left = 100,
        top = 200,
        id = "button1",
        label = "Start",
        onEvent = startStopWatch,
        fontSize = 40
    }
)

startButton.x = resumeButton.x
startButton.y = resetButton.y

resumeButton:setEnabled(false)
startButton:setEnabled(false)
1 Like