Loop Delay Timeout Issue - javascript

I'm working on a HTML5 game, and currently trying to make a weapon that fires 3 projectiles a few seconds after each other. So basically, a 3 burst assault rifle.
I first did:
for(var i = 0; i < 3; i++){
player.bullets.push(bulletInstance);
}
player.shotBullet = true;
which worked, but of course, the projectiles where release at the same time, meaning there was no delay between each shot. So I tried to introduce a setTimeout function:
setTimeout(function (){
i++;
if(i < 3){
var b = new Rectangle( player.x + (player.width / 2) - 4, player.y + (player.height / 2) - 4, 8, 8);
player.bullets.push(bulletInstance);
}
}, 1000)
player.shotBullet = true;
This doesn't do the trick either. Could someone point out my problem here?

One easy way would be like this:
for(var i = 0; i < 3; i++){
window.setTimeout( function(){ player.bullets.push(bulletInstance); }, i * 1000 );
}
This will init 3 functions 1s apart, which each firing a bullet according to your logic.
You probably will have to create separate instances of bulletInstance.
If there are much more than 3 actions to be done, I'd suggest to switch to setInterval() instead. But in such low areas, setTimeout() should be fine.

Being more specific about what is not wouking would help. In your case, the problem is that setTimeout runs only once. You should either create a new settimeout call inside the handler or use setInterval instead (just remember to clearInterval when you are done so it stops)

You can use the delay() from jQuery.

Related

Javascript move target around screen?

So I'm working on a basic shooter, part of which involves moving a target around the screen. I'm using babylon.js as the engine and my goal is to have the target appear for 0.75 seconds on the screen, then disappear for 0.5 seconds, then reappear at a different random location. The current code I have for that is this:
function moveTarget(canvas, scene){
setTimeout( function (){
scene.meshes[10].visibility = 0; //how I access the target object
randX = genRandNum(minX, maxX); //This is a separate function that works
randY = genRandNum(minY, maxY);
scene.meshes[10].position = new BABYLON.Vector3(randX, randY,
scene.meshes[10].position.z);
scene.meshes[10].visibility = 1;
x ++;
if (x < amount){
moveTarget(canvas, scene);
}
}, tarDuration * 1000)
}
which succeeds in everything except the 0.5 second delay between appearances of the target, ie currently it flashes from location to location with no space in between. I'm thinking that I need a second setTimeout but I'm not entirely sure how to include that or where it would go. Any pushes in the right direction would be much appreciated.
The way I would do this is to set a timeout for the full cycle time (0.75 s + 0.5 s) and then another timeout inside that for the 0.5 s delay.
function moveTarget(canvas, scene){
setTimeout( function (){
setTimeout( function(){
// Your other code
x ++;
if (x < amount){
moveTarget(canvas, scene);
}
}, yourDelayHere)
}, tarDuration * 1000)
}
Where yourDelayHere gives the desired 0.5 s delay. I created a Babylon.js playround which shows a simplified example here.

Recursive function to print numbers in JavaScript

I'm trying to make a recursive function to print 1 to 10 in JavaScript, my current code is:
function rec10(x)
{
if (x < 10)
{
$('#text').val(x+1);
x = x+1;
rec10(x);
}
}
The problem is, everytime I activate this function, the text box only shows "10" directly, i want the code to move from 0 to 1, to 2... until 10. Showing each one of them in the text box.
I tried to use setInterval and setTimeout but I didn't figure it out how to work with that. Thank you very much
instead of:
rec10(x);
call
setTimeout(function() { rec10(x); }, 1000);
With setInterval you can using code below:
function rec10(x) {
var interval = setInterval(function() {
if (x >= 10) clearInterval(interval);
$('#text').val(x++);
}, 1000);
}
JavaScript is single threaded, which means while your code runs, the changes you make to the DOM won't be seen on the browser until your code finish.
You need to give control to the browser for couple of seconds, it can be done with setTimeout:
function rec10(x){
if (x < 10){
$('#text').val(++x);
setTimeout(function(){
rec10(x);
},20);
}
}
Did you resort to setInterval/setTimeout only because you can't make a working recursive function?
If that's the case, how about this recursive function below without using setInterval/setTimeout:
function rec10(x) {
if (x <= 10) {
if (x <= 0) x = 1;
//append?
$('#text').val(x);
rec10(x + 1);
}
}
rec10(1);
But the problem with the code above is it will happen so fast you won't notice the printing of numbers 1 up to 9.
If you want to see the those numbers then I suggest you just append the value to your placeholder $('#text').
But if you really wanna see the numbers being printed and then being replaced by the next number, then you can refer to the answers posted by other users which uses setInterval/setTimeout.

Why aren't my ball (objects) shrinking/disappearing?

http://jsfiddle.net/goldrunt/jGL84/42/
this is from line 84 in this JS fiddle. There are 3 different effects which can be applied to the balls by uncommenting lines 141-146. The 'bounce' effect works as it should, but the 'asplode' effect does nothing. Should I include the 'shrink' function inside the asplode function?
// balls shrink and disappear if they touch
var shrink = function(p) {
for (var i = 0; i < 100; i++) {
p.radius -= 1;
}
function asplode(p) {
setInterval(shrink(p),100);
balls.splice(p, 1);
}
}
Your code has a few problems.
First, in your definition:
var shrink = function(p) {
for (var i = 0; i < 100; i++) {
p.radius -= 1;
}
function asplode(p) {
setInterval(shrink(p),100);
balls.splice(p, 1);
}
}
asplode is local to the scope inside shrink and therefore not accessible to the code in update where you are attempting to call it. JavaScript scope is function-based, so update cannot see asplode because it is not inside shrink. (In your console, you'll see an error like: Uncaught ReferenceError: asplode is not defined.)
You might first try instead moving asplode outside of shrink:
var shrink = function(p) {
for (var i = 0; i < 100; i++) {
p.radius -= 1;
}
}
function asplode(p) {
setInterval(shrink(p),100);
balls.splice(p, 1);
}
However, your code has several more problems that are outside the scope of this question:
setInterval expects a function. setInterval(shrink(p), 100) causes setInterval to get the return value of immediate-invoked shrink(p). You probably want
setInterval(function() { shrink(p) }, 100)
Your code for (var i = 0; i < 100; i++) { p.radius -= 1; } probably does not do what you think it does. This will immediately run the decrement operation 100 times, and then visually show the result. If you want to re-render the ball at each new size, you will need to perform each individual decrement inside a separate timing callback (like a setInterval operation).
.splice expects a numeric index, not an object. You can get the numeric index of an object with indexOf:
balls.splice(balls.indexOf(p), 1);
By the time your interval runs for the first time, the balls.splice statement has already happened (it happened about 100ms ago, to be exact). I assume that's not what you want. Instead, you should have a decrementing function that gets repeatedly called by setInterval and finally performs balls.splice(p,1) after p.radius == 0.
setInterval(shrink(p),100);
This doesn't do what you think it does. This calls shrink, passes it p, and then passes the result to setInterval. shrink(p) returns undefined, so this line doesn't actually put anything on an interval.
You probably want:
setInterval(function(){
shrink(p)
}, 100);

Javascript pause in WinRT for animation

I want to pause execution in javascript so that I can animate the appearance of text on the screen. My code is currently this:
function AnimateWord(word) {
for (var i = 0; i <= word.length; i++) {
myTest.textContent += word.charAt(i);
// need to pause here and then continue
}
}
I've done some research and the preferred method to do this in javascript seems to be setTimeout, although I can't really see how that would work in this case without creating a recursive loop (which just doesn't seem like the right solution to me).
Is there a way around this, or am I stuck with setTimeout and a recursive loop?
EDIT:
Based on some additional tests, I've tried using the Promise.timeout:
for (var i = 0; i <= word.length; i++) {
WinJS.Promise.timeout(1000).then(TypeLetter(word.charAt(i)));
}
function TypeLetter(letter) {
myTest.textContent += letter;
}
But this doesn't seem to actually pause. In fact, it seems to completely ignore the timeout. I've also tried:
setTimeout(TypeLetter(word.charAt(i)), 1000);
With basically the same results. this page seems to imply that it should wait and then execute the task. I'm quite new to WinJS, but am equating a promise to an await keyword in C#.
setTimeout/setIngerval/requestAnimationFrame are pretty much your only choices. I wouldn't call them recursive perse - while you do call your same function over & over. The calls tack is completely independent.
What kind of animation are you really trying to create? It may be better to create a span for each character, have them hidden, and then fade/translate the, in using CSS animations.
var i = 0;
var str = "plz send teh codez";
var intervalId = setInterval(function(){
myTest.textContent += str.charAt(i);
if (++i >= str.length)
clearInterval(intervalId);
}, 1000);
demo http://jsfiddle.net/qxfVu/1/
Does this do what you are looking for:
var array1 = [];
function AnimateWord(word) {
var test = $('#test');
for (var i = 0; i <= word.length; i++) {
array1.push(word.charAt(i));
test.delay(100).queue(function() {
this.innerHTML += array1[0];
array1.splice(0, 1);
$(this).dequeue();
});
}
}
please see fiddle link as well: http://jsfiddle.net/7Ea9u/

JS setTimeout Not Delaying

Alright guys, I'm trying to add numbers on my page every 1/4 second or so. So the change is visible to the user. I'm using setTimeout and all my calculations are occurring correctly but without any delay. Here's the code:
for(var i = 0; i < 10; i++)
{
setTimeout(addNum(i),250);
}
I've also tried capturing the return value:
for(var i = 0; i < 10; i++)
{
var t = setTimeout(addNum(i),250);
}
I've also tried using function syntax as part of the setTimeout params:
for(var i = 0; i < 10; i++)
{
var t = setTimeout(function(){array[j].innerHTML + 1},250);
}
I've also tried putting code in a string & the function call in a string. I can't ever get it to delay. Help Please!
How about:
var i=0;
function adder() {
if(i>=10) {return;}
addNum(i++);
setTimeout(adder,250);
}
adder();
When you did setTimeout(addNum(i),250); you executed the function straight away (function name followed by () will execute it right away and pass the return value to the timeout to be executed 1/4 second later). So in a loop that would just execute all 10 immediately. Which is what you saw.
Capturing the return value var t = setTimeout(...); is helpful, but not in your use case; the value is the timer id number, used for cancelling the timeout.
Not sure what your last attempt is, although presumably it's the function body of your addNum routine, so the same logic applies as above.
Perhaps instead, since you're running the same method multiple times, you should use the setInterval method instead? Here's an example of how you might do that.
Try setTimeout("addNum(" + i + ")", 250); the reason its not working is because its evaluating the parameter and executing it and changing it to something like setTimeout(result of addNum(i), 250);

Categories

Resources