Adding delay to function during drawing objects - javascript

i placed setInterval into the code but this obviously delaying all the lasers by 1 second.
I want it to be working in the following sequence:
- at start laser1 and laser2 are fired.
- 1 second break and fire another set of lasers etc.
Also if someone could teach me how to move all block of code by four spaces on forum, that would be amazing, as none of the ways i found in google solve this ridiculous problem.
Code shortcut:
let laser1;
let lasers1 = [];
let laser2;
let lasers2 = [];
function createLaser() {
laser1 = new Laser(bossOne.x, bossOne.y + bossOne.sizeY, 10, 50, 5);
lasers1.push(laser1);
laser2 = new Laser(bossOne.x + bossOne.sizeX - 10, bossOne.y +
bossOne.sizeY, 10, 50, 5);
lasers2.push(laser2);
}
function draw() {
requestAnimationFrame(draw);
setInterval(createLaser, 1000);
for (i = 0; i < lasers1.length; i++) {
lasers1[i].show();
lasers1[i].move();
}
for (i = 0; i < lasers2.length; i++) {
lasers2[i].show();
lasers2[i].move();
}
}
requestAnimationFrame(draw);
Remote host for full code if needed:
https://stacho163.000webhostapp.com/
lasers are red
I think i should work with booleans, but can't handle to set it there.
Got a similar topic with key activation, but i lost contact with the one who proposed a solution on the basis of booleans (as it didn't work well) so i took the easiest part first without involving the keys.
Any tips are appreciated :)

Try changing setInterval to setTimeout, as it's already looping recursively - just add a delay to it. Also move the requestAnimationFrame call to the bottom of draw, not the top:
function draw()
setTimeout(createLasers, 1000);
//Loops
requestAnimationFrame(draw);
}

Related

How to rotate from different titles

No, I am not talking about <h1> or something like that. I am talking about the <title> element. I created a function, that delays every .5 seconds or so, and changes titles.
The script I have developed reads the array, which includes the titles, and rotates from it. The first time I have ran it, I did not use setTimeout, and it ran instantly, I couldnt read anything.
But when I tried using the setTimeout function, it started to return undefined. What is the problem with this code?
for(var i = 0; i < titles.length ; i++){
setTimeout(function () {document.title = titles[i]}, 500)
}
You're going about this the wrong way (IMO). Using a loop you'll fire off all your timeouts at once. You'd be better off using setInterval
let i = 0, titles = ['title1', 'title2', 'title3'];
let int = setInterval(() => {
document.title = titles[i];
console.log('doc.title: ', document.title);
if (i++ >= titles.length - 1) clearInterval(int);
}, 500)

Matter.js: Method to count how many times that an object has rotated?

I am creating a project in which a body is picked up and thrown by the user (with a mouse constraint). The body is set so that it can pivot about the constrain point. I need to find out, from the moment that it is let go, how many times it fully rotates (+-360 degrees) before landing. Reading the documentation, the only thing that I could find regarding the rotation was Matter.Body.rotate() which actually just sets the rotation of a body instead of recording it. How should I go about this?
Basically: How can I count an objects rotations?
This worked for me tbh:
var rad = 6.28;
var nrad = -6.28;
Events.on(engine, "tick", function () {
if(boxA.angle > rad){
rad+=6.28;
nrad+=6.28;
hrt +=1;
//hrt is the rotation c0unter
}
if (boxA.angle < nrad){
nrad-=6.28;
rad-=6.28;
hrt +=1;
}
rnum.innerHTML = "Spins: " + hrt;
fnum.innerHTML = fcounter; });

Javascript using a For Loop with setTimeout (or another delay)

I apparently don't fully understand how the setTimeout function works in Javascript:
function move() {
var a;
for(a = 0; a < 101; a++){
setTimeout(function(){
block.style.marginTop = (750 - a) + 'px');
}, 1000);
}
for(a = 0; a < 101; a++){
setTimeout(function(){
block.style.marginTop = (650 + a) + 'px');
}, 1000);
}
}
I have tried writing this out in many different ways, but the For Loops always execute instantly every single time. How can I make a For Loop wait for 1 second between each value of 'a'? So, when a = 0, the code executes and then waits for 1 second before running when a = 1, etc. until the first For Loop is finished, then the second For Loop executes in the same way.
Also, is there a more efficient way of doing this than using setTimeout? Like a way of just writing
sleep(1000);
or something like that. This whole setTimeout feature seems very overly complicated if it is the only way of producing delays in javascript. I tried this once but it didn't work at all in any way
await sleep(1000);
Any help with Timeouts and delays in Javascript, especially within a loop, would be greatly appreciated!
You may find value in the answer I posted here. That will explain setTimeout in loops a little more.
Separately, you may want to explain what you are trying to accomplish. It looks like you are either
trying to move an element one pixel per second
trying to move an element ~100 pixels after one second
For the first option I would use CSS Transitions instead. You'll have a lot more flexibility over how the element moves and you only need to dictate the direction and distance.
For the second option, you could toss the loop and keep the stuff inside, setting the new marginTop to the full value after some timeout.
setTimeout(function(){
block.style.marginTop = (750 - a) + 'px');
}, 1000);
this part of your code use 'a' variable after 1000 miliseconds. in this time 'a' is 100, because your loop not stoped for run setTimeout function, and it happened because javascript is asyncronous.
one solution for solving this problem in js is using recursive functions. if is not necessary to use for loop, you can use this code:
var a = 0;
function my_loop(a) {
if (a < 101) {
setTimeout(function() {
block.style.marginTop = (750 - a) + 'px');
my_loop(a);
}, 100);
a++;
}
}
my_loop(a);
but if you want do your question's job, i seriously recommened you to use CSS.
As #squint mentioned, you can use setInterval for your task.
Here's an example:
// create an element
const width = 10;
const el = document.createElement('div');
el.setAttribute('id', 'main');
document.body.appendChild(el);
el.style.width = width + 'px';
// question-relevant code starts here
const a = [...Array(101).keys()]; // fancy way to create [0, 1, 2, 3, ...]
const it = a[Symbol.iterator](); // for convenience
const int = setInterval(() => {
const { value, done } = it.next(); // next iteration
if (done) { clearInterval(int); return }; // finished?
el.style.width = width + value + 'px'; // adjust width
}, 10);
#main {
height: 100px;
width: 10px;
background: green;
}

How to cycle through an array of Audio objects

I've recently started learning Javascript, and I'm working on my first web-embedded game, which is a musical puzzle game that uses the basic principals of twelve-tone serialist music. My game is mostly done, and you can find it here. But I'm having trouble with audio. I did manage to get it to play a sound when the user solves the puzzle, but I can't get it to actually play through the notes that appear on the game board.
Here's what I did: I created an array of 12 Audio objects, which contains every note from C to B. Then I created a method called "playToneRow()" which plays through them all, with the order determined by the numeric array ToneRow.notes[]. Here's the code:
this.playToneRow = function()
{
for (var i in this.notes)
{
noteSound[this.notes[i]].play();
}
};
But this method only plays the last note of the tone row. Now I should mention that my knowledge of Javascript has been cobbled together from various tutorials I've found online, and I'm fairly certain that there are significant gaps in my admittedly rudimentary coding skills. But I figured that the problem was that I wasn't putting any space in between the sounds, so it was trying to play them all at once, but it didn't have enough channels so it only played the last one. So then I tried this:
this.playToneRow = function()
{
var x = 0;
for (var i in this.notes)
{
x = this.notes[i];
setTimeout(function()
{
noteSound[x].play();
}, 700);
}
};
Now I'm really not sure if I'm using setTimeout() properly, but I'm guessing not, because once again, it only played the last note. I know that all 12 wav files are getting loaded, because if I change the tone row, it will play a different note. So it does have access to all the audio files; it's just a matter of getting it to play them all (and in the right order).
Thanks!
for won't really care about your setTimeout, try:
this.playToneRow = function()
{
var x = 0,
length = 0,
j = 0;
for (var i in this.notes)
{
length += 1;
}
function runIteration () {
x = this.notes[j];
setTimeout(function()
{
noteSound[x].play();
}, 700);
if (j === length) return;
j += 1;
setTimeout(runIteration, 700);
}
runIteration();
};
Hopefully that does it. I've taken a look at your code but its a bit complex so I wasn't able to determine if this.notes was an object or an array
http://jsfiddle.net/kgvgcsg3/14/
var notes = [{'0':'tone1'},{'1':'tone2'}]
var playToneRow = function(i)
{
setTimeout(function()
{
//notes[i].play(); goes here
console.log(notes[i])
if (i < notes.length-1){
i++;
playToneRow(i)
}
}, 700);
};
playToneRow(0)

How to speed up this moving algorithm? In Javascript

I have an Array of 16 billiard balls in JS and want to move each ball smoothly with its direction and speed.
For that I set up a timer, calling UpdateThis() every 42ms (for 24 fps).
The problem is that UpdateThis() takes 53ms as firebug states.
Now UpdateThis iterates over every ball and calls UpdateBall(ball).
I assume that the problem lies there.UpdateBall looks like this:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
it seems that the most time is spent in ball.MoveTo() which looks like this:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
-- UPDATE --
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
and onload looks like
nx = setInterval(function() { UpdateThis(); }, 42);
Does somebody have any ideas on how to speed this up?
-- UPDATE 2 --
You can download the folder with the HTML file here (the password is password)
What about separating the position updates from the drawing? So have something like this (untested code):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
If indeed it's the moving of the position that's slow, this way the logic update still happens at 42ms, and the framerate is no faster than 42ms but it can skip frames. (I haven't actually tried this, so this is all theoretical and you may need to tweak some stuff)
Why moving may be (and most probably is) slow?
Move functionality could be slow, because it has more things to do than simple variable assignment. It has to actually render some element to some other place. You could test this if you run this on IE9. I anticipate it should run faster since it uses hardware video acceleration.
As for the other routine I hope others will dissect it. :)
Questions for you
Can you please describe how do balls move? Sporadically? How do you call UpdateBall() for each ball? Do you queue those calls?
Provide VMul and VAdd functionality
Have you played with styling? Maybe relative positioning of balls' immediate parent may speed up rendering. And setting overflow:hidden on it as well. I don't know. Depends on how you've done it. Hence a JSFiddle would be very helpful.
A suggestion
Instead of using setInterval to call your function you should maybe just queue them and let them execute as fast as it gets. And just for the sake of it, provide a central setInterval with some watcher that they don't run too fast.
But I guess that it still utilizes your processor to 100% which isn't good anyway.
Very important note: Don't run you app while Firebug's enabled because it's a well known fact that Javascript executes much slower when Firebug is running.
That's tough, if MoveTo() is in fact your bottleneck, since there is not a whole lot going on there. About the only things I can think of, right off hand, are
1) Cache the style property of the image and position for faster lookups. Everytime you see a dot in the object chain it's requires stepping through the scope chain. Ideally you can cache this property at the time the parent of MoveTo() is constructed.
2) Are the 'px' strings required? It may result in an invalid CSS specification, but it may still work. I have a hard time believing 2 string concats would really change all that much though.
The main problem here is likely the fact that anytime you change the DOM, the browsers re-flows the entire page. Your only other option may be to refactor such that instead of changing the styles, you actually remove the previous contents, and replace it with the a document fragment describing the new state. This would result in only 2 re-flows for the entire step (1 for removal, 1 for addition), instead of 2 for each ball.
EDIT: Regarding #1 above, when I say cache, I don't mean just locally in the function call. But perhaps as a closure in the parent object. For example:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};

Categories