Trouble optimizing some code - javascript

I'm trying to right a function with three.js. every thing is working as intended but the FPS considerably drops after like 20-30 seconds of running the function. The function is set up to move a sprite then destroy the sprite after it reaches it's destination. Then it spawns a new sprite at a random location. Before moving the sprite it's moving at about 30 FPS. When I start moving the sprite the FPS drops to low 20's. After about 20 to 30 seconds it's at about 9. If I stop moving the sprite the FPS is back up at 30. But if I try to move the sprite again instead of repeating the earlier process it just goes right back to about 9. Now I know that javascript is a garbage collected langue so I figured it just needs some time to clean things up. But even if I let it sit for 10 minutes it still just goes right back down to 9 FPS. On the other had if I reload the page the process starts all over. I also tried just moving the sprite instead of destroying it and respawing but I get the same issue. Also I tried to use the .dispose method but had no luck. Here's the code.
function spriteAI1() {
//console.log(c2Sprite.position.x);
//console.log(ranLocX);
//console.log(ranTen);
console.log(c2Sprite.position);
//var ranTen = Math.floor((Math.random()*8)+2);
if (c2Sprite.position.x > 30 && c2Sprite.position.x <= 450) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateX( -6 );
} else if (c2Sprite.position.y > 30 && c2Sprite.position.y <= 250) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateY( -6 );
} else if (c2Sprite.position.z > 30 && c2Sprite.position.z <= 350) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateZ( -6 );
} else if (c2Sprite.position.x < -30 && c2Sprite.position.x >= -450) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateX( 6 );
} else if (c2Sprite.position.y < -30 && c2Sprite.position.y >= -250) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateY( 6 );
} else if (c2Sprite.position.z < -30 && c2Sprite.position.z >= -350) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateZ( 6 );
} else if (c2Sprite.position.x < 31 && c2Sprite.position.y < 31 && c2Sprite.position.z < 31 && c2Sprite.position.x > -31 && c2Sprite.position.y > -31 && c2Sprite.position.z > -31) {
var locX = Math.floor((Math.random()*450)+1);
locX *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locY = Math.floor((Math.random()*250)+1);
locY *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locZ = Math.floor((Math.random()*350)+1);
locZ *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
//c2Sprite.delete;
scene.remove(c2Sprite);
//console.log("AI1");
//geometry.dispose();
//material.dispose();
//texture.dispose();
c2ImgMaterial.dispose();
c2Sprite.position.set( locX, locY, locZ );
scene.add( c2Sprite );
//c2Sprite.clone;
}
}

Related

Recursively setting a value depending on range using JavaScript

I don't know how to word this but this is what I'm trying to do:
if (score >= 0 && score <= 10) overallScore = 0;
else if (score >= 11 && score <= 20) overallScore = 1;
else if (score >= 21 && score <= 30) overallScore = 2;
else if (score >= 31 && score <= 40) overallScore = 3;
else if (score >= 91 && score <= 100) overallScore = 9;
...
Is there any way to recursively do this using a function?
overallScore = Math.max(0, Math.floor((score - 1) / 10));
no need for recursion. But if you need that:
const getOverall = score => score <= 10 ? 0 : getOverall(score - 10) + 1;
Recursion is not really appropriate here, since you can get the required value in constant time. Recursion becomes interesting when you need at least O(logn) time.
But as you ask for it, here is one way to make it recursive:
function range(score, depth = 0) {
return score <= 10 || depth >= 9 ? 0 : range(score-10, depth+1) + 1;
}
console.log(range(0)); // 0
console.log(range(10)); // 0
console.log(range(11)); // 1
console.log(range(60)); // 5
console.log(range(91)); // 9
console.log(range(110)); // 9

Parse course in textual way from course in degrees?

So im making a compass in node-red, it should have course in degrees (int) as input and string(course) as output:
So i need function that takes in integer and gives me heading in string. How to do it simple and reliable?
I have to convert course 0-360 degrees in string for example: NORTH, NORTH-EAST, EAST......
I tried the following:
var course = parseInt(courseFloatDegrees);
var courseTxt = "";
if (course >= 349 && course <= 11 || course <= 359 && course >= 349 || course === 0) courseTxt = "N";
else if (course >= 11 && course <= 33) courseTxt = "NNE";
else if (course >= 33 && course <= 56) courseTxt = "NE";
else if (course >= 56 && course <= 78) courseTxt = "ENE";
else if (course >= 78 && course <= 101 || course == 90) courseTxt = "E";
else if (course >= 101 && course <= 124) courseTxt = "ESE";
else if (course >= 124 && course <= 146) courseTxt = "SE";
else if (course >= 146 && course <= 168) courseTxt = "SSE";
else if (course >= 168 && course <= 191 || course == 180) courseTxt = "S";
else if (course >= 191 && course <= 214) courseTxt = "SSW";
else if (course >= 214 && course <= 236) courseTxt = "SW";
else if (course >= 236 && course <= 258) courseTxt = "WSW";
else if (course >= 258 && course <= 281 || course == 270) courseTxt = "W";
else if (course >= 281 && course <= 303) courseTxt = "WNW";
else if (course >= 303 && course <= 326) courseTxt = "NW";
else if (course >= 326 && course <= 349) courseTxt = "NNW";
else courseTxt = "INVALID"
But sometimes i get nothing(null-empty string) or "INVALID". Does anybody know fast and simple way to do this without that much else if statements?
There could be ways of doing this more 'simply' in code, but your approach should work. The reason it doesn't is because your if statements are messed up around the 'N' region.
if ((course >= 349 && course <= 11) || (course <= 359 && course >= 349) || (course === 0)) courseTxt = "N";
If you look at the very first two conditions, they are illogical. More than 349 but less than 11? That's never going to happen. If you have a course of 7 degrees, that doesn't meet any of the specified criteria currently.
So the first thing to do is resolve that problem. You need to adjust the line to use OR instead of AND
if(course < 11 || course > 349) courseTxt = "N";
Now your code will be able to handle the settings either side of 360/0 degrees.
That should be enough to get your current code to work, assuming course is always less or equal to 360.
You asked if there is a way to avoid all the if statements. There are probably hundreds of ways to do this, but the simplest, other than if or case statements would probably be to use an array to look up the heading. Here is an example of how it could be done. You could obviously hardcode the step value, but this way you could update your array with any number of more granular headings, and it will still work.e
function getCourse(course)
{
// define our values
var degs = 360;
var strs =
["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"];
// make sure course is always within the expected range in case it is incremented past 360
course = course % degs;
// get the step amount based on the number of compass headings we have
var step = degs/strs.length;
// adjust for the last few degrees on the scale which will be north
if(course > degs - (step/2)) course += step/2;
// now just divide the course by the step and read off the relevant heading
var index = Math.floor(course / step);
return strs[index];
}
Nicky,
I used an approach similar to Toby's -- calculating an index into an array of course strings:
var deg = course % 360;
var dirs = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"];
var idx = Math.round(deg * (dirs.length-1)/360);
var dir = dirs[idx];
The trick is to repeat the "N" element at the beginning and end of the array, and use Math.round(...) to jump to the closest integer index number.

Javascript: + 1 Limit for Counter/Conditional Statement

In my javascript game i have a function that is called every 0.1 seconds with setInterval:
updateTimerID = setInterval(function(e) {checkProgress();}, 100);
I store a users score in a variable and have a conditional statement inside the checkProgress function which checks when my slider x position falls between 45 - 48:
var score = 0;
function checkProgress(){
if( slider_1.x => 45 && slider_1.x <= 48 ) {
score = score + 1
}
}
I then increase the score variable by one when this happens. The problem i have is i only want the score to be updated by 1 every time, not everytime - so with my function being called every .1 seconds - at the moment my score is adding at least 3 each time
if( slider_1.x => 50 && slider_1.x <= 60 ) {
score ++;
}
Can i limit it to 1 each time?
Something like this maybe?:
var isOver = false;
function checkProgress(){
if( slider_1.x => 45 && slider_1.x <= 48 && !isOver ) {
score = score + 1;
isOver = true;
} else if( slider_1.x < 45 && slider_1.x > 48 ) {
isOver = false;
}
}
you can do that by storing the score update time at a variable than substract it from current time to look for the time passed from last update is greater than 1 second
var score = 0;
var last_update =0;
function checkProgress(){
if( slider_1.x => 45 && slider_1.x <= 48 && ((new Date().getTime()-last_update) > 1000) ) {
score = score + 1
last_update=new Date().getTime();
}
}
Something like this will do the trick
var score = 0;
var inc = true;
function checkProgress(){
if( slider_1.x => 45 && slider_1.x <= 48 ) {
if(inc)
{
score = score + 1
inc = false;
}
}
if(slider_1.x < 45 || slider_1.x > 48)
{
inc = true;
}
}

Updating the random number within a variable?

How can a variable with a random number be updated. I'm using three.js. Here is my code. It works the first time it's called generating a sprite to a random location but then it just keeps going back to the same location. I thought that by calling the variables before they were used I would be updating them but it's not working.
var locX = Math.floor((Math.random()*450)+1);
locX *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locY = Math.floor((Math.random()*250)+1);
locY *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locZ = Math.floor((Math.random()*350)+1);
locZ *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
function spriteAI1() {
//console.log(c2Sprite.position.x);
//console.log(ranLocX);
//console.log(ranTen);
if (c2Sprite.position.x > 30 && c2Sprite.position.x <= 450) {
c2Sprite.translateX( -10 );
} else if (c2Sprite.position.x < -31 && c2Sprite.position.x >= -450) {
c2Sprite.translateX( 10 );
} else if (c2Sprite.position.z < 31 && c2Sprite.position.x < 31 && c2Sprite.position.z > -29 && c2Sprite.position.x > -29) {
locX;
locY;
locZ;
//c2Sprite.delete;
//scene.remove(c2Sprite);
//console.log("AI1");
c2Sprite.position.set( locX, locY, locZ );
//scene.add( c2Sprite );
//c2Sprite.clone;
}
}
If you want different values each call, declare the vars inside the function, not outside of it. As you currently have it, the vars are set once, and the function, however many times it's called, will reference those once-set values.

Else if statement with 3 or more conditions?

I have been trying for a long time and cant seem to figure out what i'm doing wrong. The first too conditions seem to work but the third fails.
function spriteAI1() {
if (c2Sprite.position.x >= 30 && c2Sprite.position.x <= 450) {
c2Sprite.translateX( -10 );
} else if (c2Sprite.position.x <= 30 && c2Sprite.position.x >= -450) {
c2Sprite.translateX( 10 );
} else if (c2Sprite.position.z = 30 && c2Sprite.position.x = 30) {
c2Sprite.remove;
c2Sprite.clone;
}
else{}
}
function spriteAI2() {
if (c2Sprite.position.z >= 30 && c2Sprite.position.z <= 350) {
c2Sprite.translateZ( -10 );
} else if (c2Sprite.position.z <= -30 && c2Sprite.position.z >= -350) {
c2Sprite.translateZ( 10 );
} else if (c2Sprite.position.x = 30 && c2Sprite.position.z = 30) {
c2Sprite.remove;
c2Sprite.clone;
}
else{}
}
I'm getting an error on the line
else if (c2Sprite.position.x = 30 && c2Sprite.position.z = 30)
the error says invalid left hand in assignment. But the other function has basically the same line and doesn't generate a error.
I can see two problems in your code.
First, comparison is done using == (double equal signs), not a single one (that's assigning a value). That's probably the source of your problem.
In second place, your last two conditions match a common group of values (they are intersected), in the case when c2Sprite.position.x equals 30, it will enter the second "if". It will match the condition for the third one, but it will not run it.
Make sure you always define well-separated groups of conditions (unless that's the behavior that you want).
Just to make it clear:
if (x >= 30) {
/* this matches 30 and above */
}
else if (x == 30) {
/* this won't execute on x == 30, because it entered the first "if" */
}
You should have done this:
if (x > 30) {
/* this matches numbers strictly greater than 30, i.e. 31, 32, 33... */
}
else if (x == 30) {
/* this will match x == 30 */
}
else {
/* any other value for x */
}

Categories

Resources