I am making a boon system where the player gets a random boon/buff for 30 seconds and then it removes itself. I have the initial boon in place where it lasts 30 seconds, then removes itself. I push the boon name "Healing Boon" to a empty player.boons = [] array.
However I am running into difficulty the other way around. Lets say the enemy wants to "debuff" my character, and REMOVE the boon instantly. Well because the countdown for my boon lasts 30 seconds, it continues to work until the 30 seconds is up, even if I give the appearance of removal. (I still keep gaining health up to 30 seconds).
I am attributing this to the setTimeout function. If I input 30 seconds, even if later down the line (say 5-10 seconds later), make setTimeout = 0; it will still continue on for the next 30 seconds. It is only on the initial 2nd attempt is setTimeout set to 0. But this is not what I want. I want a system that stops the boon entirely in its tracts and removes any current health buffs it gives the player.
function applyBoonHealing(){
var blessedWind = setInterval(function(){
player.cc.hp += 1;
dom.setText("healthcounter", player.cc.hp);
}, 1000);
player.boons.push("Healing Boon");
postPlayerStatusEffectImage("images/lowerstrengthicon.jpg", "buff", "0", "2", "no");
dom.setText("healthcounter", player.cc.hp);
setTimeout(clearBoon, 30000);
function clearBoon(){
clearInterval(blessedWind);
if (player.boons.includes("Healing Boon", 0)){
var arrayIndex = player.boons.indexOf("Healing Boon", 0);
player.boons.splice(arrayIndex, 1);
}
dom.setText("healthcounter", player.cc.hp);
postPlayerStatusEffectImage("images/lowerstrengthicon.jpg", "buff", "0", "2", "yes");
}
}
clearTimeout() method is solution to this problem:
var boonHandle = setTimeout(clearBoon, 30000);
(...)
clearTimeout(boonHandle); //To cancel your timer
you can use clearTimeout() method,
var mySetTimeoutFunc = setTimeout(clearBoon, 30000);
to stop this you will just have to clearTimeout(mySetTimeoutFunc);
for more info see this http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_settimeout_cleartimeout2
clearTimeout is a event to stop Timeout, see below
function myStopFunction() {
clearTimeout(myVar);
}
Related
Hi,
I have this code:
//<![CDATA[
$(window).load(function(){
setInterval(function(){
// toggle the class every 10 seconds
$('body').addClass('new');
setTimeout(function(){
// toggle back after 10 seconds
$('body').removeClass('new');
},10000)
},10000);
});//]]>
This code is supposed to add the class "new" to body 10 seconds later after the page first loads and then remove it after 10 seconds again to start all over going into an endless loop. But it wont work as expected. Sometimes it takes way longer than 10 seconds to add the class and it removes it too soon. Some other times it does it only once and then the loop ends just like that.
Whats wrong here? A more effective and reliable alternative will be also welcome.
Thank you.
You've told the code adding the class to run every 10 seconds. Every 10 seconds, you also schedule a timer to remove the class 10 seconds later. So as of the 20th second, you have a race — will the first timer get there first, or will the second? In any case, it won't have the result you want.
Use a single timer that toggles:
setInterval(function() {
$("body").toggleClass("new");
}, 10000);
As for it taking a long time to start, remember that the window load event doesn't occur until all resources have finished downloading, including all of your images and such. So the whole process may be starting quite a bit later than you expect.
Also note that browsers are increasingly "dialing back" timers in inactive tabs, so your timer may not be running, or may run infrequently, when the window it's in doesn't have focus.
From your comment:
But just as a bonus. What if I want to have the class to last 20 seconds but keep the interval in 10 seconds?
That complicates things. You could have a flag that you toggle, and only toggle the class when the flag is in one state or the other. E.g., something like:
(function() { // Scoping function so the flag isn't a global
var flag = true;
setInterval(function() {
if (flag) {
$("body").toggleClass("new");
}
flag = !flag;
}, 10000);
})();
That will add the class at 10 seconds, toggle the flag at 20, remove the class at 30, toggle the class at 40, then start the cycle again. Adjust as needed.
The second parameter in the setInterval function is for delaying the executing in milliseconds. and as expected 1000 millisecond will trigger the function every second. but here's a strange thing that I don't really understant. In the second interval, I've set the delay parameter to 1 millisecond and put inside the function incremental number and condition to check for every passed 1000 number.. I was expecting it to behave just like the seconds interval timer. but It doesn't quite run as I hoped.
Is there any explanation for that?
// detect seconds in a second interval timer (works as expected)
setInterval(function() {
console.log('passed second from the secondInterval');
}, 1e3);
// detect seconds in a millisecond interval timer (I don't have any explanation for the behavior).
(function() {
var i = 0;
setInterval(function() {
if (i === 0) {
i++;
return;
}
if (i % 1000 === 0) console.log('passed second from the millisecondInterval');
i++;
}, 1);
})();
check out the example in jsfiddle to see what I mean
http://jsfiddle.net/dwh82zos/
This happens. The sentence is not logged every second, or whatever your machine can. You are running out of memory, can't resolve, first time 6 operations per 1ms and second 3 operations per 1ms.
Take a look of this What is minimum millisecond value of setTimeout? it is about setTimeout but it useful.
I need to be able to call this function to reset the interval.
I know this has been asked before. But the answer given at
Javascript - Reset setInterval back to 0
is not working for me.
Here is the code that I tried:
function startTimer(){
clearInterval(interval);
var interval = setInterval(function(){
advanceSlide();
}, 5000);
};
I call that at the beginning of my page to start a slideshow that changes every 5 seconds. and I use this code to call it again, witch I expected would reset that 5 seconds.
onclick=startTimer();>
The onclick does one other thing too, but this is what is not working. The other action takes place but the interval does not change, its still going based off the same portion of 5 seconds that was left before I clicked.
You need to declare the variable outside the function...
var interval;
function startTimer() {
clearInterval(interval);
interval = setInterval(advanceSlide, 5000);
}
Otherwise it is lost when the function exits.
I am working on a module in which there is a requirement to show a timer which shows only seconds. The timer must start from 30 and keep on decrementing down to 0; and after that fire some action and again start from 30. How can I achieve this in javascript?
There you go :)
var timer = 30;
function decrementAfter1Second(){
setTimeout(function(){
timer--;
if(timer==0){
doWhateverYouWantAfter30Seconds();
timer = 30;
}
decrementAfter1Second();
}, 1000);
}
decrementAfter1Second();
Now next time you want to do something in javascript don't be a slacker and read something about the language first ;) because right now i'm assuming you either don't know how to program or you don't know how to use google.
You could use setTimeout and clearTimeout. Have the timeout fire every 1 second and then invoke clearTimeout when seconds == 0.
You can find examples of both functions here.
base ={time:0};
var loop = 0;
setInterval(function(){
if(base.time === 9000){
move();
base.time = 0;
}
base.time ++;
},1);
Shouldn't the move(); function occur every 9s? I timed it and its much less, why is that?
setInterval will not run every millisecond. There is a minimum possible interval that is longer than that.
If you want something to run in nine seconds, you should use setTimeout() for 9 seconds. Plus your code doesn't reset base.time back to zero so it would only match 9000 once anyway.
If you want it to run every 9 seconds, then you can use setInterval(handler, 9000) or you can use setTimeout(handler, 9000) and then set the next setTimeout in your handler function.
This will execute move() every nine seconds:
var intervalTimer = setInterval(function(){
move();
}, 9000);
Here's a useful article on the topic: http://www.adequatelygood.com/2010/2/Minimum-Timer-Intervals-in-JavaScript.
To reset the time back to 9 seconds when a button is clicked use this code:
var intervalTimer;
function startTimer() {
intervalTimer = setInterval(function(){
move();
}, 9000);
}
function handleClick() {
clearInterval(intervalTimer); // stop currently running interval
startTimer();
}
startTimer();
See it in action here: http://jsfiddle.net/jfriend00/sF2by/.
Intervals are easy as pie!
var move = function(){
alert("move!");
};
setInterval(move, 9000);
See it work here on jsFiddle
You can't count on setInterval actually running every 1 ms. If the CPU is used for another process, it might not run for 1 second. Instead, use one of the following:
function move() {
// Do stuff.
}
// The obvious solution.
// Certain browsers (Chrome) may put the script in "inactive" mode which will
// pause setInterval code. This means move will be run too few times, if you
// actually depend on it being called X times for Y time.
setInterval(move, 9000);
// The other solution.
// Get the delta between each loop and run the move loop as necessary.
// WARNING: This is not efficient, and you should only use this if you have a
// good reason to do so.
// EXTRA WARNING: This code is actually retarded in its current form. It's just
// here to show you how you'd do it. Since you didn't post your
// original problem, it's hard to know what you're really after.
var time = +new Date, frequency = 9000;
setInterval(function () {
var dt = new Date - time;
// Check if we've waited long enough.
if (dt >= frequency) {
// If the process hangs for 20 seconds, this value would be 2. Usually,
// it will be 1.
// Also, Chrome will pause interval counters, so if a tab is inactive,
// this count could be really high when the tab gets focus again.
var times = Math.floor(dt / frequency);
console.log('Moving', times, 'time(s)!');
for (var i = 0; i < times; i++) {
move();
}
// Start counting time from the last update.
time += times * frequency;
}
}, 1); // 1 could probably be much higher here. Depends on your use case.
You wrote in a comment that there is a button which resets the time, and that's why you don't want to just setTimeout for the full delay. Here's how to handle that:
var running;
function start() {
clearInterval(running);
running = clearInterval(function () {
move();
}, 9000);
}
Every time start() is called, the time will be reset to 9 seconds from now, and if 9 seconds elapse, move() will be called and another 9-second interval will start. If you don't actually want it to happen repeatedly, just use setTimeout instead.
The key is using clearInterval (or clearTimeout) to cancel your previous 9-second-delay and start a new one. It is harmless to call clearInterval with a junk value.