let's suppose I have a game loop like this
function update(){
myTime = Date.now() - myTime
// use myTime as you wish...
// reset myTime
myTime = Date.now()
}
stuff happens there, ideally at 60fps but not always. Using Date.now() I need to know how many milliseconds happens between one frame and the other. Here's why:
I have a variable X, this variable should lineary increase so that every 1 second it is increased of 480 units. This increasing should be as smooth as possible so, I think, it should be of 0,48 every millisecond.
How can I do that considering that I just draw to the screen every 16,6 milliseconds (60fps)? Do I need to compensate that by adding 0,48 * 16,6 ? Or... what kind of forumla? I'm getting crazy on this, thanks in advance!
I'm not sure I get the question, but maybe this will help?
To just get the time since the function last ran, you could do:
var lastTime = Date.now();
function update(){
//do stuff here
var myTime = Date.now(),
timePassed = myTime - lastTime; //time passed since last time
lastTime = Date.now(); //set for next time
}
To see how many times the function runs each second you could do:
var lastTime = Date.now(), framerate=1;
function update(){
//do stuff
framerate++;
if ((Date.now()-1000)>lastTime) { //if a second or more has passed
console.log(framerate); //log number of times function has ran
framerate=0; //and reset values
lastTime = Date.now();
}
}
To join those functions, do:
var lastTimeEach = Date.now(), lastTimeSecond = Date.now(), framerate=1, x=480;
function update(){
//do game logic
var myTime = Date.now(), //time now
timePassed = myTime - lastTimeEach; //time passed since last iteration
lastTimeEach = Date.now(); //reset for next iteration
framerate++;
if ((myTime-1000)>lastTimeSecond) { //one second has passed
x += 480; //add 480 to x
framerate=0; //reset framerate
lastTimeSecond = Date.now(); //reset for next second
}
}
Here's a DEMONSTRATION
Related
I'm using moment.js to create a three minute countdown. However, every time the page loads, the timer decrements by one second and stops at 2:59. Printing out variables such as future and difference seems to yield normal results, however, so I believe that my error lies in the countdown. What is wrong with my countdown?
Here's my code:
<script type="text/javascript">
$(document).ready(function(){
var now = moment();
var future = moment(now).add(3, 'm');
var difference = future - now;
var duration = moment.duration(difference, 's');
var interval = 1000;
setInterval(function() {
if(duration.asSeconds() <= 0) {
clearInterval(intervalId);
document.getElementById("clock").innerHTML = moment(duration.asSeconds()).format("m:s");
}
duration = moment.duration(duration.asSeconds() - 1, 's');
document.getElementById("clock").innerHTML = moment(duration.asSeconds()).format("m:s");
}, interval);
});
</script>
you can change that to be something like this:
if (moment.duration(future - moment()).asSeconds() <= 0) {
and change
duration = moment.duration(duration.asSeconds() - 1, 's');
to be
duration = moment.duration(moment.duration(future - moment()).asSeconds(), 's');
because you're closure is capturing the value of duration above but never really updating it.
I'm trying to make a timer that functions like the one on this website: http://www.gaiacoin.com/ The timer starts at 7 Billion and counts down at a rate of 2.5 points per second.
How should I write this Javascript function?
Thanks!
in javascript the function setInterval will call a specific function every X milliseconds based on the 2nd parameter.
var myNumber = 7000000000;
var myInterval = setInterval(function(){
myNumber -= 2.5;
},1000);
the 1000 is miliseconds.. so.. 1000 miliseconds per second.
You would use the setInterval function to create the timer, and then use getElementById to find the spot in the HTML document to write the text.
var x = 7000000000;
setInterval(function() {
x = Math.max(0, x - 2.5);
document.getElementById("field_name").innerHTML = "Gaiacoin Clock " + x;
}, 1000);
Ignore all the down votes. Everyone that has down voted your question at some point didn't know the answer either, and how do we learn unless we ask for help.
Here's how I'd do it
var startValue = 7000000000;
// arbitrarily started at midnight 7th November 2015 UTC
// change to whatever you want,
// or even read something from a cookie if you want
var startTime = new Date(2015, 10, 7, 0, 0, 0);
var perSec = 2.5;
var beginOffset = new Date() - startTime;
var startPerform = performance.now();
var displayValue;
var go = function() {
var elapsed = beginOffset + (performance.now() - startPerform);
var value = Math.floor(startValue - perSec * elapsed / 1000);
if(value != displayValue) {
console.log(displayValue = value); // do your output here
}
}
setInterval(go, 100);
Okay so in relation to my last question. I currently have this code:
var secs = 100;
setInterval(function() {
var $badge = $('#nhb_01');
$badge.text((parseFloat($badge.text())+0.01).toFixed(2));
}, secs);
Basically, I need the counter to increase by a certain value every minute.
So one of the values I need is 0.17.
So I need the counter to increase by 0.17 every minute. So after 2 minutes, the counter will read 0.34 and so on.
How would I go about this, because working out how many milliseconds it should take over the minute is becoming such a pain and confusing!
Thank you for any help!
Demo.
Instead of grabbing the text from the element each time it would be slightly better (more efficient) to just keep a JS counter incremented instead:
var secs = 1000 * 60;
var count = 0;
setInterval(function() {
var $badge = $('#nhb_01');
count += 0.17;
$badge.text(count.toFixed(2));
}, secs);
DEMO - runs a little faster than normal so you can see the effect.
var secs = 60 * 1000;
setInterval(function() {
var $badge = $('#nhb_01');
$badge.text((parseFloat($badge.text())+0.17).toFixed(2));
}, secs);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="nhb_01">0</div>
If you're keeping track of the time elapsed, here is a function that will give you the value of the badge given a rate of increase and time elapsed. Just call it periodically when you update the value displayed on the badge.
function calcIntervalValue(ratePerMinute, elapsedTimeInMilliseconds) {
var elapsedTimeInMinutes = elapsedTimeInMilliseconds / 60000; //60000 miliseconds in a minute
return ratePerMinute * elapsedTimeInMinutes
}
var twoMinutes = 120000 //in milliseconds
alert( calcIntervalValue(0.17, twoMinutes) )
The setInterval takes the last arguments in this setup as milliseconds, and it should be an easy equation: 1000 milliseconds * 60 = 1 minute
So make a variable that is just that:
var ms = 1000 * 60;
Now you have to define how much you want to add to a certain value
var toAdd = 0.17;
Here are som basic markup for an example
<!DOCTYPE html>
<html>
<head>
<title>Increasing a number with setInterval</title>
</head>
<body>
<h2>Increasing a number with setInterval</h2>
Number: <span id="counter"></span>
</body>
</html>
And here are som commented JavaScript with the variables we just made
// make a reference to the element which should hold the updated value
var counterElem = document.getElementById('counter');
// define a variable with the value you want to add to
var toAdd = 0.17;
// define the interval for the task. I made this frequency faster for demonstration purpose.
var ms = 10 * 60;
//now make the setInterval
setInterval(function() {
// parse the innerHTML to a float
var count = parseFloat(counterElem.innerHTML);
// Check that the count variable actually is a number and add the toAdd and the count together, and if not just add the initial value to id (0.17) because then it is probably the first time the interval checks the element.
counterElem.innerHTML = (!isNaN(count) == true ? count + toAdd : toAdd);
}, ms);
Here is an example of the script in use: https://jsfiddle.net/whyyc81a/
Increment from Starting Value to Ending Value Over Duration with a Given Framerate.
Inspired heavily by #Dan-Levi Tømta's answer.
HTML
<h2>Increment Value over a Duration with a given framerate</h2>
Value: <span id="value">0</span>
JS
var valueElement = document.getElementById('value');
var start = 0;
var end = 100;
var duration = 10000; // In milliseconds (divide by 1000 to get seconds).
var framerate = 50; // In milliseconds (divide by 1000 to get seconds).
var toAdd = ( ( end - start ) * framerate ) / duration;
var interval = setInterval(function() {
var currentValue = parseFloat(valueElement.innerHTML);
if (currentValue >= end) {
clearInterval(interval);
return;
}
valueElement.innerHTML = (!isNaN(currentValue) == true ? currentValue + toAdd : toAdd);
}, framerate);
jsFiddle
https://jsfiddle.net/L3Ln1f7b/
From this base, you can do a lot. Adjusting framerate helps with performance issues and duration allows you to speed things up or slow things down
I am making a countdown timer that should be reseting and starting anew every 10 seconds.
This is the code I came up with by now:
function count(){
var end_date = new Date().getTime()+10*1000;
setInterval(function(){
var current_date = new Date().getTime();
var seconds_left = parseInt((end_date - current_date) / 1000);
document.getElementById("countdown").innerHTML = seconds_left + " seconds ";
}, 1000);
}
setInterval(function(){count()}, 10*1000);
It is supposed to function as follows:
+ I set interval that will restart count() every 10 seconds.
+ count() defines end_date - a date 10 seconds from now.
+ then count() sets interval that will restart every 1 second.
+ every 1 second seconds_left variable is changed according to how current_date changed with respect to end_date.
+ as soon as seconds_left becomes 0, setInterval from step 1 fires and starts count() anew.
Which step am I implementing the wrong way? Do I misunderstand the functioning of setInterval()?
Here is my JsFiddle: http://jsfiddle.net/sy5stjun/ .
My guess is that each call is in its own new object and you get multiple instances of itself fighting ever 10 seconds.
Using your approach using date objects here is a possible re-write:
var tmr = null;
var time;
function bigInterval() {
clearInterval(tmr);
time = (new Date()).valueOf() + (10 * 1000);
smallInterval();
tmr = setInterval(smallInterval, 500);
}
function smallInterval() {
var cur = (new Date()).valueOf();
var seconds_left = parseInt((time - cur) / 1000);
document.getElementById("countdown").innerHTML = seconds_left + " seconds";
}
bigInterval();
setInterval(bigInterval, 10*1000);
In the above code I've updated the small timer to be 500ms instead of 1000ms as it won't exactly line up with the system clock at 1000 and you get visual jumps in the numbers.
If exact timing isn't 100% important then here is a possible shorter method:
var t = 10;
setInterval(function() {
document.getElementById("countdown").innerHTML = t + " seconds";
t--;
if (t <= 0) {
t = 10;
}
}, 1000);
There are a few things going on, here. You're not specific why you have to set another interval inside your loop, but there are a lot easier ways to accomplish what you're going for. Another approach follows:
HTML:
<!-- string concatenation is expensive in any language.
Only update what has to change to optimize -->
<h1 id='countdown'><span id="ct"></span> seconds </h1>
JS:
// For one thing, grabbing a new reference to the
// dom object each interval is wasteful, and could interfere with
// timing, so get it outside your timer, and store it in a var scoped
// appropriately.
var ct = document.getElementById("ct");
// set your start
var ctStart = 10;
// set your counter to the start
var ctDown = ctStart;
var count = function() {
// decrement your counter
ctDown = ctDown - 1;
// update the DOM
ct.innerHTML = ctDown;
// if you get to 0, reset your counter
if(ctDown == 0) { ctDown = ctStart; }
};
// save a reference to the interval, in case you need to cancel it
// Also, you only need to include a reference to the function you're
// trying to call, here. You don't need to wrap it in an anonymous function
var timer = window.setInterval(count, 1000);
My jsFiddle available for tinkering, here: http://jsfiddle.net/21d7rf6s/
In our application, we have a need for a robust countdown timer. When the timer counts down to zero, we move the user on to the next page.
There are a LOT of questions on here about making a countdown timer in JavaScript. I've weeded through a lot of them, looked at a lot of the code samples, tried a lot of plugins, and all of them fail for this one test case: If you adjust your computers system clock, all of these timers mess up (gain time, lose time, or just freeze). The reason is that most of them base their logic on saving some initial start time and then at some interval (either via setTimeout or setInterval) getting the current time and doing a diff between it and the start time. When you adjust your system time, the "current" time can be an hour or days before your start time, or hours or days later.
So, I've come up with the following code to try to handle these system change scenarios. The main thing I do is check if the "diff" between my start and current is negative (or greater than roughly one hour to handle an automatic daylight savings adjustment) to just use the tick interval as an approximation. Also, reset the start time to be current time on each tick, so that elapsed time is the sum of the time between differences, not just the diff between an initial start time and current time. Anyone see any flaws with this approach?
var timeLeft = 60000, // time left in ms, 1 minute for this example
startTime,
totalElapsedTime = 0,
TICK_INTERVAL = 500; // the setTimeout interval
var timerTick = function () {
var now = new Date(),
elapsedTime = now.getTime() - startTime.getTime();
// if the elapsed time was positive and less than approximately an hour, then add the elapsed time to the total
// otherwise, add the TICK_INTERVAL, which we know is the theoretical minimum between timerTick() calls
totalElapsedTime = (elapsedTime > 0 && elapsedTime < 3590000) ? totalElapsedTime + elapsedTime : totalElapsedTime + TICK_INTERVAL;
// reset start time
startTime = now;
// there is time left, so set up another tick
if (totalElapsedTime < timeLeft) {
// update the html that is displaying remaining time
setTimeout(timerTick, TICK_INTERVAL);
}
else {
// time ran out, so do whatever you do when it runs out
}
}
// start the timer
startTime = new Date();
setTimeout(timerTick, TICK_INTERVAL);
Why does the following not work for you?
var timeleft = 60000,
tick = 1000,
intervalID = window.setInterval(function () {
timeleft = timeleft - tick;
if (timeleft <= 0) {
// clear the interval
clearInterval(intervalID);
// do something
}
}, tick);
Update
Using setTimeout (this will drift, but probably be ok unless you are using it for animation):
var timeleft = 60000,
tick = 1000;
window.setTimeout(function timerFn() {
timeleft = timeleft - tick;
if (timeleft > 0) {
// set the next timeout
setTimeout(timerFn, tick);
} else {
// do something
}
}, tick);