setting a one minute timer in JavaScript memory aid game - javascript

<div id="counter">1:00</div>
function countdown() {
var secs = 60;
function tick() {
var counter = document.getElementById("counter");
secs--;
counter.innerHTML = "0:" + (secs < 10 ? "0" : "") + String(secs);
if( secs > 0 ) {
setTimeout(tick, 1000);
} else {
alert("Game Over");
}
}
tick();
}
countdown(60);
I am having a problem with this portion of my game. I'm trying to set a 60 seconds timer for the game that starts at 60 and ends at 0, when it gets to 0 the game stops and an alert shows that the game is over.
I am very new to programming, so please give me as many feedbacks as you can. I found this code on the internet, and I figured out most of it, could you also tell me what does the tick() function do over here?

Here is one way you can do it:
First declare a variable you will use for an interval (should be 'global', attached to window):
var countDownInterval = null;
Then, a function to trigger the tick interval, you should call this whenever the game is ready to start:
function startCountDown()
{
countDownInterval = setInterval(tick,1000); //sets an interval with a pointer to the tick function, called every 1000ms
}
which will call the tick function every second:
function tick()
{
// Check to see if the counter has been initialized
if ( typeof countDownInterval.counter == 'undefined' )
{
// It has not... perform the initialization
countDownInterval.counter = 0; //or 60 and countdown to 0
}
else
{
countDownInterval.counter++; //or --
}
console.log(countDownInterval.counter); //You can always check out your count # the log console.
//Update your html/css/images/anything you need to do, e.g. show the count.
if(60<= countDownInterval.counter) //if limit has been reached
{
stopGame(); //function which will clear the interval and do whatever else you need to do.
}
}
and then the function where you can do everything you need to do after game has finished:
function stopGame()
{
clearInterval(countDownInterval);//Stops the interval
//Then do anything else you want to do, call game over functions, etc.
}
You can fire up the counter at any time by calling startCountDown();

Pseudo code of tick:
function tick() {
reduce counter variable;
if counter > 0
wait for 1 second; (This is what setTimeout(tick, 1000) means)
call tick() again (recursively)
}
else {
game over
}
}

Something like this?
var countdown = function(sec, tick, done) {
var interval = setInterval(function(){
if(sec <= 0) {
clearInterval(interval);
done();
} else {
tick(sec)
sec--;
}
}, 1000)
}
countdown(10, console.log, function(){console.log('done')})

Related

How to stop timer and check for value if value is not met continue and else stop timer and do something

So like the title says i have this timer and i would like that once that it reaches 0, it should check if a variable called "user_energy" in this case is equal to 100. If it is than the timer will stop, and it could do something. Like for example just a console.log("It works") and if its not then it should repeat itselfs.
How would you be able to do something like that?
This is the code:
function startTimer() {
var interval = 10000;
{
localStorage.endTime = +new Date + interval;
}
if(!localStorage.endTime)
{
startTimer();
}
setInterval(function()
{
var remaining = localStorage.endTime - new Date;
if( remaining >= 0 )
{
$('#energytimer').text( Math.floor( remaining / 1000 ) );
} else
{
startTimer();
}
}, 100);
}
It's a little unclear how the localStorage stuff fits into the question, but here's a simple countdown timer that does what you are asking. You can adapt this to store the counter in localStorage if that's what you want to do.
The key is to assign a variable to the return value from the timer so that you can call clearTimeout() and pass that variable and stop the timer later.
let timer = null; // <-- This will hold a reference to the timer
var counter = 5;
timer = setInterval(function(){
if(counter === 0){
clearTimeout(timer); // Stop the timer
console.log("Times up!");
} else {
$("#energytimer").text(counter--);
}
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="energytimer"></div>

setInterval continues to run after clearInterval is called

I'm working on a countdown timer for a quiz app I'm building as a homework assignment during bootcamp. Right now everything is functioning properly when rendered except that once the setInterval function inside of startQuiz() hits 0 it's supposed to clear the interval. However, the innerHTML written to the document keeps flashing momentarily as if the countdown is still running. I think it's probably a return in the wrong place but I've tried adding, subtracting, and moving returns throughout the script and am not seeing where the solution is.
var startButton = document.querySelector("#startButton");
var time = document.querySelector("#time");
var countdown = document.querySelector("#countdown");
var timeLeft;
var userScore;
startButton.addEventListener("click", startTimer);
function startTimer() {
var startCount = 5;
setInterval(function(){
if(startCount <= 0) {
clearInterval(startCount=0);
startQuiz();
}
countdown.innerHTML = startCount;
startCount -=1;
}, 1000);
return;
}
function startQuiz() {
timeLeft = 10;
quizQuestions();
setInterval(function(){
if(timeLeft <= 0) {
clearInterval(timeLeft=0);
gameOver();
}
time.innerHTML = timeLeft;
timeLeft -=1;
}, 1000)
return;
}
function gameOver() {
document.getElementById("quizQuestion").innerHTML = "GAME OVER";
return;
}
function quizQuestions() {
document.getElementById("quizQuestion").innerHTML = questionA.question;
return;
}
This is the entire script so far. I only left out the var definition for questionA since it is an object with multiple key value pairs and is not relevant to the issue so I omitted it to save space. The startTimer() function works properly as a separate countdown timer to start the game but I included it in the code in case it's interfering with the startQuiz() function in some way.
setInterval returns integer for interval identification. You must use this integer to clear interval.
var intervalId = setInterval(function(){
if(timeLeft <= 0) {
clearInterval(intervalId);
gameOver();
}
time.innerHTML = timeLeft;
timeLeft -=1;
}, 1000);
// assign to a variable...
const interval = setInterval(callback, timing)
// ...then pass that variable to clearInterval
clearInterval(interval)
In this example, interval will be a number (incremented each time a call to setInterval or setTimeout is made). If you pass someOtherVariable = 0 to clearInterval, you're actually passing 0, because assignment returns the value assigned. The incrementing interval/timeout value starts from 1, so the interval identified by 0 will never exist, thus clearing it is a no-op.

setInterval for stopwatch

I'm trying to make a stopwatch. Here's the code:
var min = 0, sec = 0, censec = 0
$("#startBtn").on("click", function() { // when start button is clicked
$(this).hide(); // start is hidden
$("#stopBtn").show(); // stop is shown
setInterval(add, 10); // the censec will be increased every 10 millisecond.
$("#censec").text(censec);
})
function add() {
censec++;
if (censec == 100) {
censec = 0;
sec++;
if (sec == 60) {
sec = 0;
min++;
}
}
}
The problem is that setInterval() happens only at once. The censec only changes from 00 to 1. That's it.
P.S. I'm new to coding, so if there are other mistakes, please don't hesitate to tell me.
The setInterval calls to add will definitely repeat. But your code is only ever showing the value of censec once, when you start the timer.
If you want to update the display every hundredth of a second, put the code showing the value in add.
Separately, the code as it is in the question won't run at all, because it has a ReferenceError on the first line. Those ; should be ,.
Example (this also stores the timer's handle and clears the timer when you click the stop button):
var min = 0, sec = 0, censec = 0;
// Note ---^--------^
function add() {
censec++;
if (censec == 100) {
censec = 0;
sec++;
if (sec == 60) {
sec = 0;
min++;
}
}
$("#censec").text(censec);
}
var timer = 0;
$("#startBtn").on("click", function() { //when start button is clicked
$(this).hide(); //start is hidden
$("#stopBtn").show(); //stop is shown
timer = setInterval(add,10); //the censec will be increased every 10 millisecond.
});
$("#stopBtn").on("click", function() {
clearInterval(timer);
timer = 0;
$(this).hide();
$("#startBtn").show();
});
<input type="button" id="startBtn" value="Start">
<input type="button" id="stopBtn" value="Stop" style="display: none">
<div id="censec"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note that although it may be mostly fine to use setInterval for displaying, using it to track the elapsed time is a bad idea; it frequently doesn't fire precisely.
Instead, record when you started
var start = Date.now();
...and then when the timer fires, figure out how long it's been since you started
var elapsed = Date.now() - start;
Then use the value (milliseconds) in elapsed to figure out your display.
Your variable declarations have ; instead of , .
Also checking numbers on equality should be done by using === but that is not the problem here.
Your also not updating the view in your timer. So updating of your html should also be in your function that is called by the timer.
If the goal is to use real seconds and milliseconds, I also suggest using the Date type because your timer will be late and not real-time. So still use the timer with the interval you like but in the add function you call the date object. You can replace the 3 vars for one datetime of type Date which will give you the granularity that you like.
var dateTimeStart = null, censecElement = null, timer = null;
$("#startBtn").on("click", function() {//when start button is clicked
$(this).hide(); // start is hidden
$("#stopBtn").show(); // stop is shown
if(timer === null) {
// timer was not started
dateTimeStart = new Date();
timer = setInterval(updateCensec, 10); //the censec will be increased every 10 millisecond.
console.log("Started timer");
}
});
$("#stopBtn").on("click", function() {//when stop button is clicked
$(this).hide(); // stop is hidden
$("#startBtn").show(); // start is shown
if(timer) {
// timer is started/running
clearInterval(timer);
console.log("Stopped timer");
}
timer = null;
});
function updateCensec() {
var sensec = 0, sec = 0, dateTimeNow = new Date(), diffMilliseconds = 0;
diffMilliseconds = dateTimeNow - dateTimeStart;
censec = parseInt((diffMilliseconds % 600 ) / 10); // convert milliseconds to centi seconds
sec = parseInt(diffMilliseconds / 600);
if(censecElement === null) {
censecElement = $("#censec");
}
censecElement.text(sec + ":" + censec);
}
I would like to suggest that you do not update your view every 10 milliseconds even if you want your stopwatch to show time in centiseconds.

jQuery Countdown Each Second

I'm trying to make a jQuery countdown type animation, that once it hits 0 it executes a function. However I'm having problems because I'm unsure how to go about doing this. I thought I'd do a while loop then pause for a second until it hits 0. However it doesn't seem possible to pause a while loop. So I'm wondering what's the best way to do this? Thanks.
countdown takes an HTMLElement to display itself and the number of seconds to count down for
It returns a Promise that resolves when the counter reaches 0
We can use a .then call to apply a function when the count-down has completed
function countdown(elem, s) {
return new Promise(function(resolve) {
function loop(s) {
elem.innerHTML = s
if (s === 0)
resolve(elem)
else
setTimeout(loop, 1000, s - 1)
}
loop(s)
})
}
countdown(document.querySelector('#a'), 3).then(
function(elem) { console.log('done', elem) }
)
countdown(document.querySelector('#b'), 5).then(
function(elem) { console.log('done', elem) }
)
countdown(document.querySelector('#c'), 10).then(
function(elem) { console.log('done', elem) }
)
<p id="a"></p>
<p id="b"></p>
<p id="c"></p>
You should also be aware that setTimeout and setInterval do not guarantee that the milliseconds argument used is 100% accurate …
var last = Date.now()
var interval = setInterval(function() {
var now = Date.now()
var delta = now - last
console.log(delta)
last = now
}, 1000)
setTimeout(clearInterval, 10000, interval)
// 1000
// 1003
// 998
// 1002
// 999
// 1007
// 1001
// ...
If you need a long running timer with high accuracy, I recommend you adapt the solution to use delta-based updates to the clock. If you rely upon setTimeout or setInterval for accuracy, you will be sad.
function countdown(elem, ms) {
return new Promise(function(resolve) {
function loop(ms, last) {
let now = Date.now()
let delta = now - last
if (ms <= 0) {
elem.innerHTML = 0
resolve(elem)
}
else {
elem.innerHTML = (ms/1000).toFixed(3)
setTimeout(loop, 25, ms - delta, now)
}
}
loop(ms, Date.now())
})
}
countdown(document.querySelector('#a'), 3000).then(
function(elem) { console.log('done', elem) }
)
countdown(document.querySelector('#b'), 5000).then(
function(elem) { console.log('done', elem) }
)
countdown(document.querySelector('#c'), 10000).then(
function(elem) { console.log('done', elem) }
)
<p id="a"></p>
<p id="b"></p>
<p id="c"></p>
Code:
var counter = 10;
var yourFunc = function(){}
var interval = setInterval(function(){
counter--;
if(counter <=0){ yourFunc(); clearInterval(interval); }
}, 1000);
I would use a recursive function
var countDown = function(secondsRemaining){
secondsRemaining -= 1;
if(secondsRemaining <= 0){
//execute
} else {
//wait 1 second and call again
setTimeout(function(){
countDown(secondsRemaining);
}, 1000);
}
}
then to initially start countdown (5 seconds)
countDown(5000);
I would use something like the following :
$(document).ready(function(){
var counter=10;
countDown();
function countDown(){
$('#showNumber').text(counter--);
if(counter>=0)
window.setTimeout(countDown,1000)
else
otherFunction();
}
function otherFunction(){
$('#showNumber').text('FINISHED!');
}
});
Try this out. It does not require jQuery.
var count = 5; // Number of times to run 'counter_function'.
// Run 'counter_function' every second (1000ms = 1 second)
var counter = setInterval(function(){
counter_function()
}, 1000);
// The function to run when 'count' hits 0.
var done_function = function() {
console.log('done');
}
// The function to run at each interval.
var counter_function = function() {
console.log('count');
count--;
if(count === 0){
done_function();
clearInterval(counter);
}
}
It will print the word 'count' every second for 5 seconds, and at the last second it will also print 'done'.
Are you looking for something like this OP?
This executes every second. You can use clearInterval() just as I added in the comment section whenever you want it to stop.
var start = 10; // time to countdown from in seconds
var interval = setInterval(
function(){
if (start == 0) {
complete();
clearInterval(interval);
}
$(".update").html("<h4>Countdown "+start+"</h4>");
start--;
}, 1000);
function complete() {
console.log("called the callback, value of start is: "+start);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="update">
</div>

SetTimeout. Stop timer

As in this example to stop setTimout?
var i = 1;
var timerId = setTimeout(function tick() {
if (i == 5) clearTimeout(timerId);
i++;
console.log("Tick");
timerId = setTimeout(tick, 2000);
}, 2000);
I know this code you can change and then everything will work, but I wanted to understand why the first example does not work.
var i = 1;
var timerId = setTimeout(function tick() {
console.log('Tick');
if (i < 5) setTimeout(tick, 2000);
i++;
}, 2000);
The first code snippet continues looping because:
You are changing the timerId with every new timeout you set.
You are clearing the timeout that has already finished executing (because it has called the function), and then creating a new one.
You should be using setInterval() instead of setTimeout(), as an interval will keep repeating indefinitely at the specified frequency, whereas a timeout will only execute once after the specified time has elapsed.
The first example isn't working because you're always setting a timeout, no matter the value of i. Add a return statement if i is equal to 5
var i = 1;
var timerId = setTimeout(function tick() {
if (i == 5) {
return;
}
i++;
console.log("Tick");
timerId = setTimeout(tick, 2000);
}, 2000);
It's OK to clearTimeout after the timer expired, but it's not necessary.
and just because of that, your second code snippet is superior to the first one.
and in your first code snippet, you always set the timeout, even if your if condition is met, and you are suppose to return,
i will re-write the function as shown below
var i = 1;
function tick() {
if (i == 5) {
return;
}
i++;
console.log("Tick");
setTimeout(tick, 2000);
}
setTimeout(tick, 2000);
or using interval as
var i = 1;
function tick() {
if (i == 5) {
clearInterval(timerId);
return;
}
i++;
console.log("Tick");
}
var timerId = setInterval(tick, 2000);

Categories