How can I check a variables value constantly without using setInterval? - javascript

I am building a incremental game. I have a progress bar that fills up 1 point every second.. And when that bar reaches 10 points it resets back to 0..
The problem I am having is checking if the variable is 10 at all times. I am currently using setInterval to run the function every 10 milliseconds but I feel like this is not good for the website.
I have been trying to find a solution for this for months, can someone please help me out here..
In short: How do I check a variables value at all times without causing lag/inefficiency

So, to recap, you're running a setInterval at 10ms which task is just to check if the value of some variable equals 10. There's so many solutions, but hard to answer specifically without seeing any code.
Solution 1: Call a desired function immediately after where you increment your variable
const doTheMagic = (points) => {
console.log(`You reached score: ${points}`)
};
let points = 0; // Start at 0
const incrementPoint = () => {
points += 1;
if (points === 10) doTheMagic(points);
points %= 10; // Loop-back points to 0 when reaches 10
};
// You say you increment `points` at intervals of ~1000ms:
setInterval(incrementPoint, 1000);
Wait 10s... Then again 10s... etc...
Solution 2: Use setter
Solution 3: Use Proxy

Related

Clearing Timeout After Button Clicked

I'm currently trying to code something similar to tamagotchi "care mistakes".
In this case, I'm trying to create a function which checks if the object's hunger stat is above or at 10. Once this occurs, a timer will start, and if it remains above 10 after 10 seconds, it'll be logged as a "mistake".
However, if the user does another action which reduces the hunger below 10, it'll clear the timer.
I'm unable to get the timer to clear properly at the moment despite trying the code below.
var changeHungerMood = setInterval(mistakeCheck, 5000);
function mistakeCheck() {
var mistakeTimer
function addMistake() {
stats.mistakes += 1;
}
if (stats.hunger >= 10) {
var mistakeTimer = setTimeout(addMistake, 10000);
} else {
clearTimeout(mistakeTimer);
console.log("Mistake Cleared!");
}
}
minmaxHunger("hunger", 10, 0);
At the moment, even if hunger goes below 10 after the check, the timer isn't cleared and it's still logged as a mistake. Could anyone please help? Thank you.
You should clarify what you need to accomplish in each case.
Very imperatively, you need:
To set your timer if stats.hunger >= 10, you're doing it well (except that you declare mistakeTimer with var two times... skip the second var).
When the 10 seconds are over, instead of calling addMistake, you need to check if stats.hungeris still 10 or more, and if it's the case, call your addMistake function.
So you need to add a function addMistakeIfNeeded that do the check and call addMistake if needed. And your timer should call this addMistakeIfNeeded function instead of addMistake.
And #Jonas is right, you need to put addMistake and addMistakeIfNeeded out of the mistakeCheck function.

Performence: When animating using requestAnimationFrame, is an interval better than manually calculating the ellasped time?

In examples I see two different ways how to handle animations using requestAnimationFrame():
The first one using setTimeout()
const e = document.getElementById('e');
let count = 0;
function move(timestamp) {
e.style.left = ++count + 'px';
setTimeout(f=>{
requestAnimationFrame(move);
}, 200);
};
requestAnimationFrame(move);
Try it in this jsfiddle.
The second one by calulating the ellapsed time yourself
const e = document.getElementById('e');
let count = 0;
let past = null;
function move(timestamp) {
if (past !== null && timestamp - past < 200) {
requestAnimationFrame(move);
return;
}
past = timestamp;
e.style.left = ++count + 'px';
requestAnimationFrame(move);
};
requestAnimationFrame(move);
Try it in this jsfiddle.
Now my question is: Which one performs better?
My guess is, that if an interval is applicable, it will perform better. There aren't so many logical expressions to evaluate and so many calculations to do. But that's just a guess. So, are their any benefits of one way over the other?
You should do the first one. However you shouldn't assume it will be exactly 200ms. If you need to know exactly how many milliseconds it's been, you must calculate it every time like in your second example, but keep using the structure of your first example.
The problem with the second example is that it calculates the new frames just as often as the first example, but it runs the function just to check that it doesn't need to run the function every other time it runs. Lots of wasted computation there.
You need to calculate the time elapsed (if you need accuracy) because the setTimeout combined with the requestAnimationFrame will not be guaranteed to run in 200ms. The requestAnimationFrame in particular will add time onto that if it feels it needs to before it's ready to give you permission to animate (which is basically what requestAnimationFrame is -- it's giving you permission to animate, saying 'I'm ready now').

Twisted count up timer

I have a simple little javascript count up timer on my page that I want to tweak, but really don't know where to begin.
The goal is that instead of it counting straight up in timed intervals is to have it jump randomly upward.
for example, if my timer is showing 100 and is set to increase again in 1 second, instead of it showing 101, I want it to show some random number between 101 & 106.
Any nods in the right direction would be greatly appreciated.
I appreciate the help you guys gave me (posts 1&2) ... but i'm still missing it somehow.
Here is the link to what i currently have... http://jsfiddle.net/FQSAH/19/
As you see it run, it's moving up by 1, but i'm wanting it to move up by a random number between 1&5 each time.
var x = 0;
setTimeout(function() {
// random interval between 1 and 10
var interval = Math.floor((Math.random() * 10) + 1);
x += interval;
}, 1000);
Tweak 10 as large as you want for a higher variability in intervals.
With a setInterval() you could schedule a function to run every second.
To get the random effect working, you could create a function to update a variable using Math.random().
For example:
var value = 0;
function randomize() {
value += (1 + (Math.random() * 5)); //random value between 1 and 5
}
setInterval(randomize, 1000);

Time based javascript functions with setInterval

I'm using node.js but this question is strictly javascript related. I'm interfacing with an i2c board to fade lights and I'd like to fade them at a specific rate, say 1 second. Now with setInterval, in theory it should work like... if I wanted to fade them 100 steps in 1 second I could just do something like...
var fader = setInterval(function(){
//will fade light 100 steps in 1 second
doFade(something,something);
},10)
But depending on the code inside of the Interval loop, it may take longer than 1 second (I tested and for my application was about 2.5 seconds). I'm sure the fact that function doFade is taking a set amount of time to happen is causing this issue but I'm just curious if there is any real way to make this actually all happen within 1 second.
The closest you'll ever get, AFAIK, relying entirely on JS would be to do something like this:
var fader = (function(now)
{
var timeLeft, end = now + 1000,//aim for 1000 ms
stepsRemaining = 100,
callBack = function()
{//define here, avoid redefining function objects
doSomething(foo, bar);
setter();
},
setter = function()
{//recompute interval, set anew
if (stepsRemaining <= 0)
{//avoid infinite timeouts
return;
}
timeLeft = (end - (+(new Date)));
timeLeft= timeLeft > 0 ? timeLeft : 0;//ensure positive timeleft, if not, 0 intervals ==> ASAP
fader = setInterval(
callback,
Math.floor(
timeLeft/stepsRemaining--
)
);
};
setter();
return fader;
}(+(new Date)));//get ms now
This code, though untested creates all function objects beforehand. Then, using setter, everytime the interval finishes, as long as you haven't set 100 intervals, the new interval will be computed. After the work is done, by the callBack function, setter is called again. Here, the number of remaining steps is checked, then the timeLeft is computed again and based on the remaining steps, which are decremented by 1 on each call to setter.
To avoid setting the intervals too long, or using float-numbers, I'm calling Math.floor, and to avoid setting negative timeout values, I'm checking the value of timeLeft, too, obviously

Testing/validating/evaluating the outcome of every path in a function?

Disclaimer - I've tried finding an answer to this via google/stackoverflow, but I don't know how to define the problem (I don't know the proper term)
I have many small AI snippets such as what follows. There is an ._ai snippet (like below) per enemy type, with one function next() which is called by the finite state machine in the main game loop (fyi: the next function doesn't get called every update iteration, only when the enemy is shifted from the queue).
The question: How do I test every case (taking into account some enemy AI snippets might be more complex, having cases that may occur 1 in 1000 turns) and ensure the code is valid?
In the example below, if I added the line blabla/1 under count++, the error might not crop for a long time, as the Javascript interpreter won't catch the error until it hits that particular path. In compiled languages, adding garbage such as blabla/1 would be caught at compile time.
// AI Snippet
this._ai = (function(commands){
var count = 0;
return {
next: function(onDone, goodies, baddies) {
// If the internal counter reaches
// 2, launch a super attack and
// reset the count
if(count >= 2) {
commands.super(onDone);
count = 0;
}
else {
// If not performing the super attack
// there is a 50% chance of calling
// the `attack` command
if(chance(50)) {
var target = goodies[0];
commands.attack(onDone, target);
}
// Or a 50% chance of calling the
// `charge` command
else {
commands.charge(onDone);
count++;
}
}
}
};
})(this._commands);
I could rig the random generator to return a table of values from 0-n and run next 1000's of times against each number. I just don't feel like that is will concretely tell me every path is error free.
As you say, unit tests must test every path so you will be sure all works well.
But you should be able to decide which path the method will follow before calling it on your tests, so you're be able to know if the method behaviour is the expected one, and if there is any error.
So, for example, if there is a path that will be followed in only one of every 1000 executions, you shouldn't need to test all 0, 1, 2 ... 999 cases. You only one combination of results that behave distinctly.
For example, in the snippet shown you have these cases:
the counter has reached 2
the counter has not reached 2 and chance returns true
the counter has not reached 2 and chance returns false
One way to archieve this is taking control of the counter and of the chance method by mocking them.
If you want to know what happens when the counter has reached 2 and the next method is called, just pass a counter with 2 and call next. You don't need to reach 2 on the counter by really passing for all the code.
As for the randomizer, you don't need to try until the randomizer returns the value you want to test. Make it a mock and configure it to behave as you need for each case.
I hope this helps.

Categories