HelloWorld!
I’m coding a Memory Game that display the time you’re taking to finish the game.
My code provided is just a more basic Vue template of the feature I use, but it’s a fairly similar use case.
My problematics are in the comments of each functions. basically i’m encountering issues with stopping the timer and un-stoping it.
What Do I need?
- Display the formatted time on my html since you started a click interaction represented here by the startChrono() function.
- Automatically stop the time if you’re not interacting for a period of time OR if the game is finished.
- Automatically resume the time if you interact again.
- resetting the time completely in the code and the DOM.
<script setup>
import { ref } from 'vue';
const startTime = ref(0); // Initial TimeStamp
const endTime = ref(false); // Boolean to stop the Chrono
const elapsedTime = ref(0); // Chrono Time
const isGameActive = ref(false);
function startChrono() {
/*
I want pauseChrono() to be used here IF the startChrono() function hasnt been called since "x" time
or IF the isGameActive boolean is set to false
(auto pause if you're not clicking on the start button in other words)
In my mind I should use a Debounce but cant really figure how to do it properly...
*/
isGameActive.value = true;
startTime.value = new Date().getTime();
endTime.value = false;
updateChrono();
}
function pauseChrono() {
/*
Issue here is when you stop the pause it still uses the initial timestamp
so the delta time is still counted instead of
adding the time elapsed before the pause to a new timestamp chrono time...
*/
if (endTime.value === true) endTime.value = false;
if (endTime.value === false) endTime.value = true;
updateChrono();
}
function updateChrono() {
const intervalId = setInterval(() => {
const currentTime = new Date().getTime();
elapsedTime.value = Math.floor((currentTime - startTime.value) / 1000);
if (endTime.value == true) {
clearInterval(intervalId);
}
}, 1000);
}
function formatTime(seconds) {
if (seconds < 0 || seconds > 3600) {
return;
}
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
if (minutes === 0) {
return `${remainingSeconds} s`;
} else {
return `${minutes} min ${remainingSeconds} s`;
}
}
function resetChrono() {
isGameActive.value = false;
startTime.value = 0;
endTime.value = true;
elapsedTime.value = 0;
updateChrono();
}
</script>
<template>
<main>
<h1>
Time:<span>{{ formatTime(elapsedTime) }}</span>
</h1>
<button @click="startChrono()">Start</button>
<button @click="pauseChrono()">Pause</button>
<button @click="resetChrono()">Reset</button>
</main>
</template>
<style scoped>
main {
background-color: lightslategray;
padding: 5rem;
}
button {
font-weight: bold;
font-size: 18px;
padding: 0.2rem 1rem;
margin-right: 1rem;
margin-block: 1rem 0;
cursor: pointer;
}
span {
color: rgb(2, 255, 120);
margin-left: 1rem;
}
</style>
2
Answers
Fixing the pause/unpause issue:
To pause the timer, call clearInterval on the
setInterval
return value. In the code below, when the timer starts, assign the return value to a new valueisRunning
.Then in the pause function, if
isRunning
has a value, clearing the interval and settingisRunning
back to null/undefined will pause the game. Else, unpause by calling updateChrono again (which assigns a new setTimeout value toisRunning
). Also, thestartTime
will need to be set to the current time minus elapsed time for the timer to continue running from it’s previous value.Vue Playground #1
I think there are multiple ways you could handle an "idle timer"
One basic idea would be a function that has a setTimeout function that calls
pauseChrono
after some X amount of time.It also clears its own timer every time it’s called, restarting the countdown for as long as it continues to be called. If this function is called every time the user interacts with the game, and the user interacts more than once every X seconds, then the timer is never hit. Otherwise, the game will pause after X seconds of no interactions.
Vue Playground #2
Date.now();
to some variable when paused and take it into account when resumed.const pausedTime = 5; // pauseChrono after 5s,
compare the value ofelapsedTime.value
when updating the timer.Here’s your starting point: Vue SFC Playground