1

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!!!

timidboy
  • 1,702
  • 1
  • 16
  • 27
D34thSt4lker
  • 447
  • 1
  • 5
  • 12

3 Answers3

0

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.

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
  • 1
    @D34thSt4lker @ray-toal, notice that you can still have a function expression, without pollute the scope: `setTimeout(function shootAliens() { /*.. your code.. */; setTimeout(shootAliens, msec) }, msec)` in that way in the same scope `typeof shootAliens` will be `undefined` but inside the function itself is callable. – ZER0 Sep 09 '12 at 05:55
0

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

Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • hmmm... it seems to be working better but the game seems to slow down when I start shooting at the "aliens"... Also, do you know how to fix up the lag? (freezing) The game seems to freeze when I start shooting too fast or other stuff too – D34thSt4lker Sep 09 '12 at 05:36
  • Without looking at your code (where you call it etc) I can't see what's wrong. The difference is that my loop should be executed only once as it binds an interval to each alien, if you execute the loop more than once you'll have too many intervals. `=]` – Fabrício Matté Sep 09 '12 at 05:38
  • alright, here http://jsbin.com/welcome/21167/edit Images wont show up since I'm not sure if i can upload them or not... – D34thSt4lker Sep 09 '12 at 05:52
  • and... i see that there are many "errors" in my code according to that site... most of them are that I already defined the variable (regarding new for loops)... is that bad coding? or is that fine? – D34thSt4lker Sep 09 '12 at 06:06
  • Hard to test without all the files, but I think the `for` loop should be in the `initAliens` function or where it initializes the aliens. You had a `new Array[]` there too, either use `[]` (recommended) or `new Array()` with round parens. Here's the slightly updated jsbin - [link](http://jsbin.com/welcome/21170/edit) – Fabrício Matté Sep 09 '12 at 06:06
  • @D34thSt4lker Declaring a `var` when it's already declared is unnecessary but doesn't generate any error. It's just superfluous. The `var` statement just indicates that all references inside that scope will reference the local var, so more than one `var` statement is unnecessary but isn't an error per se (it doesn't generate any syntax error nor change the behavior of your code). – Fabrício Matté Sep 09 '12 at 06:08
  • nice nice!!! that works much better!! But still have the problem of the game freezing... Any reasons that you might know of? – D34thSt4lker Sep 09 '12 at 06:14
  • Eh, I can't run the files to test, but let me see. Did it start freezing after my for loop? And freezing as in really slow or stop working? Guess you can host the files folder zipped in [temp-share](https://temp-share.com/) or something and I can take a look. `:P` – Fabrício Matté Sep 09 '12 at 06:19
  • no, its not your code that made it freeze... the game seems to freeze when the user shoots too fast ( i think ) and it completely freezes... Its been happening all night - one sec, im going to upload it now... you can actually play it on d34thst4lker.com/invaders if you want to see what i mean – D34thSt4lker Sep 09 '12 at 06:27
  • Yes, I saw it freezing, gimme a couple mins as I got fix some stuff in the code I added too to don't generate errors :P – Fabrício Matté Sep 09 '12 at 06:30
  • oh yea... just remembered another question I had that you might be able to help me out with... when I press one key and then another key, the first key is "stopped"... how do I make it that you can press two keys at a time (or one and then the 2nd) and it will work that way without any stops? – D34thSt4lker Sep 09 '12 at 06:44
  • Try this code http://jsbin.com/osutec/1/edit I fixed some issues with my own code and fixed the freezing. Not sure what you mean with 2 keys pressed at same time, you mean like left and right or something? – Fabrício Matté Sep 09 '12 at 06:51
  • no i mean like lets say im pressing right and holding it down so it constantly moves, and then press space to hit, the right will stop moving... or lets say if i make a game where my character will move to the right and then press another key to jump, how would i do both instead of one stopping when the other is pressed... and thanks! gonna go through your code now – D34thSt4lker Sep 09 '12 at 06:54
  • The freezing problem was with your loop that calls `isHit` on the aliens, when shooting too many at a time sometimes it'd iterate over an alien which no longer exists and give an error. So I added a `if (!aliens[j]) continue;` to the loop in case they're already destroyed. – Fabrício Matté Sep 09 '12 at 06:54
  • I'm not too sure what's the best approach to make the behavior you want with the keyboard, I think it's a little limited due to how keyboard input works but you can make another question too with a simplified version of what you want in a fiddle. `=]` People with more experience than me will be willing to help too. – Fabrício Matté Sep 09 '12 at 06:56
  • nice no problem. i was just curious and you seem like you know your stuff. but its fine. Ill just ask my professor on tuesday. thanks so much for your help! much appreciated... – D34thSt4lker Sep 09 '12 at 06:58
0

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>
Community
  • 1
  • 1
enhzflep
  • 12,927
  • 2
  • 32
  • 51