JavaScript setInterval problems

Hey guys I'm trying to run a loop with a setInterval but I would like each element in the array to use a random interval instead of the entire array doing so... this is the code I am using so far

setInterval(function() {
        for ( var j = 0; j < aliens.length; j++ ){
            aliens[j].shootIt();
        }
    }, 1000+Math.floor(Math.random() * 4000)
);

but I'm kind of stuck here... Thanks in advance!!!

Answers


Move the for loop to outside the interval, then call a function on each iteration to have a fixed j for each interval instance.

var shootIntervals = []; //this goes in the "global" context of your game

for ( var j = 0; j < aliens.length; j++ ) {
    intervals(j);
}

function intervals(j) {
    shootIntervals[j] = setInterval(function() {
        if (!aliens[j]) return;
        aliens[j].shootIt();
    }, 1000+Math.floor(Math.random() * 4000));
}

//clearInterval(shootIntervals[j]) when they're destroyed

This will give a static random interval to each item in the array.

Fiddle


Assuming you want to call the function at random intervals, the reason setInterval does not work for you is that the random number is computed before the timer is set up. In particular, when you call setInterval both the function expression and the timer interval are computed (once), then the function is called at the computed interval.

In other words, when evaluating your code the random number evaluation might result in an interval of 2.5 seconds. Then your function will be called at 2.5 second intervals.

You should use setTimeout instead.

var shootAliens = function () {
    // code to shoot aliens goes here
    // ...
    setTimeout(shootAliens, 1000+Math.floor(Math.random() * 4000));
};

Now after shooting all of the aliens, this code will schedule the next alien shooting after some random amount of time between 1 and 5 seconds. After that shooting, a new random delay is computed for the next shooting.


See here: how many javascript setTimeout/ setInterval call can be set simultaneously in one page? Basically, you need to assign the result of setInterval to a variable. Doing so will allow you to then use clearInterval with that variable

I've used that technique in this example. Doing it this way allows you to change the interval assigned to different elements - we first check to see if we have any saved values. If so, we call clearTimeout on them.

From there, we call setInterval on each target item, saving the result to the array - ready to be cleared next time the user presses the button.

<!DOCTYPE html>
<html>
<head>
<title>Moving a couple of spans with different intervals</title>
<script type="text/javascript">
var myIntervals = [];
function Init()
{
    if (myIntervals.length != 0)
    {
        for (var i=0, n=myIntervals.length; i<n; i++)
        {
            clearInterval(myIntervals.pop());
        }
    }
    myIntervals.push(setInterval(function(){onMove('sp1');}, (Math.random()*500)>>0 ));
    myIntervals.push(setInterval(function(){onMove('sp2');}, (Math.random()*500)>>0 ));
    myIntervals.push(setInterval(function(){onMove('sp3');}, (Math.random()*500)>>0 ));
}

function constructStyleString(xPos, yPos)
{
    var result = "margin-top: " + yPos + "px;";
    result += "margin-left: " + xPos + "px;";
    return result;
}

function onMove(tgtId)
{
    var xPos, yPos;
    xPos = Math.random() * 640;
    yPos = Math.random() * 480;
    var elem = document.getElementById(tgtId);
    elem.setAttribute("style", constructStyleString(xPos, yPos));
}
</script>
<style>
span
{
    position: absolute;
}
</style>
</head>
<body onload="Init();">
    <button onclick="Init();">(Re)set item intervals</button>
    <span id='sp1'>This is the first item</span>
    <span id='sp2'>This is the second item</span>
    <span id='sp3'>This is the third item</span>
</body>
</html>

Need Your Help

Converting the name of a character (i.e. comma) to an actual character (i.e. ,)

c# .net fonts kerning

I am currently attempting to get kerning information out of a font file. I have got kerning pairs so far using Font Forge. It gives you a list of kerning pairs like so: