accessing box2d bodies - javascript

Since now, I've been accessing box2d bodies (to change or to get their values) with this for loop copied from the web:
for (var b = world.GetBodyList(); b != null; b = b.GetNext())
works fine but... Is there any other faster way to do so? Can't I just store a reference to the bodies in an array so then have always access to it?
Thanks!

I don't know which version of Box2DJs you're using but you can do something like this:
var myBodies = [];
var myBox = new b2BoxDef(); // or whatever the name of your body creation function is
myBodies.push(myBox);
console.log(myBodies[0]); // reference to your Box2D object

Related

"push is not a function" error in Google App Script

I have a code that is supposed to read a google sheet and push these into an array but i keep encountering an error that proData.push is not a function What could I be missing in this code?
function getData() {
var values = SpreadsheetApp.getActive().getSheetByName("Projects").getRange("A1:O").getValues();
values.shift();
var proData = [];
values.forEach(function(value) {
var proData = {};
proData.project_state = value[0];
proData.project_name= value[4];
proData.project_code= value[5];
proData.end_date= value[2];
proData.push(proData);
})
Logger.log(JSON.stringify(proData));
return proData;
}
I will appreciate help in looking at this.
This line tells the whole story:
proData.push(proData);
You're trying to push an object onto itself? Clearly this is an indication that something is wrong. So let's look at where you define proData:
var proData = {};
That at least explains the error. proData is an object, not an array. And an object indeed doesn't have a function called push. You may have thought it was an array, because you defined an identically named array here:
var proData = [];
But for the line where you call .push, how is the system to know which variable you intend for what purpose? In a higher scope you have an array named proData, but in the current scope of this operation you obscured that with an object named proData. And in doing so made the array inaccessible within the scope of the function passed to .forEach.
To avoid confusing both the JavaScript engine and yourself in this matter, simply use different variable names. Re-naming the variable in the smaller scope has a lower impact, so that's a good candidate. (Though it's not always the best choice. If the variable in the higher scope is semantically not clear about what it contains then it should be re-named.)
Something like this:
values.forEach(function(value) {
var pd = {};
pd.project_state = value[0];
pd.project_name = value[4];
pd.project_code = value[5];
pd.end_date = value[2];
proData.push(pd);
});

javascript referencing dynamic parent object

I have this object, a 3rd party tracking tool similar to google analytics. I want to extend it with my own "caching" function that saves the data from the previous tracking call so that I can reference stuff on the next tracking call if needed.
This is what I have so far, and it works:
// Current 3rd party tool, can't really mess with this.
// It is loaded from an external script
window.someTool={/* stuff */};
// my code
someTool._cache=someTool._cache||{};
someTool._cache._get=function(variabl) {
var length,index,variabl=(variabl||'').split('.'),
cache=someTool&&someTool._cache&&someTool._cache._dataLayer||{};
for (index=0,length=var.length;index<length;index++){
cache=cache[variabl[index]];
if (!cache) break;
}
return cache;
};
So then I have/do the following
// data layer output on initial page that gets wiped later
var dataLayer = {
'page' : {
'name' : 'foo',
'lang' : 'en'
},
'events' : {
'pageView' : true,
'search' : true
}
}
// I grab the initial data layer and save it here
someTool._cache._dataLayer = dataLayer;
This then allows me to do stuff like
someTool._cache._get('page'); // returns {'page':{'name':'foo','lang':'en'}
someTool._cache._get('page')['name']; // returns 'foo'
someTool._cache._get('page.lang'); // returns 'en'
So this works for me, but here comes the question/goal: I want to improve my _get function. Namely, I don't like that I have to hardcode someTool, or really even _cache, and if I can somehow swing it, _dataLayer.
Ideally, I'd like a reference of someTool._cache._dataLayer passed/exposed to _get (e.g. a parent type reference) so that if someTool,_cache, or _dataLayer were to change namespaces, I don't have to update _get. But I am not sure how to do that.
This is what I have so far:
(function(tool, cache, dataLayer) {
var tool = tool || {},
cache = cache || '_cache',
dataLayer = dataLayer || '_dataLayer';
dataLayer = tool[cache][dataLayer] || {};
tool[cache]._get = function(property) {
var length, index, property = (property || '').split('.');
for (index = 0, length = property.length; index < length; index++) {
dataLayer = dataLayer[property[index]];
if (!dataLayer) break;
}
return dataLayer;
};
})(someTool, '_cache', '_dataLayer');
This seems to work the first time I call it, e.g.
someTool._cache._get('page')['name']; // returns 'foo'
But after that, I get an error:
TypeError: someTool._cache._get(...) is undefined
I feel like it has something to do with dataLayer losing its reference or something, I dunno (though I'm not sure how it's working first time around..). Is what I am doing even possible, and if so, where am I going wrong? Or is what I originally have the best I can do?
I feel like it has something to do with dataLayer losing its reference or something, I dunno (though I'm not sure how it's working first time around..).
The reason this is happening is because you are using the same dataLayer you initialize in the closure of _get to:
store information, and
to use as a temporary loop variable
If you look at your code:
(function(tool, cache, dataLayer) {
// ...
// Here you are initializing (or looking up) the dataLayer
dataLayer = tool[cache][dataLayer] || {};
tool[cache]._get = function(property) {
// ...
for (index = 0, length = property.length; index < length; index++) {
// here you are overwriting the same dataLayer
dataLayer = dataLayer[property[index]];
if (!dataLayer) break;
}
return dataLayer;
};
})(someTool, '_cache', '_dataLayer');
You can see that your loop will overwrite dataLayer on each iteration which means every lookup after the first will most likely be wrong.
Eventually, dataLayer will be overwritten with undefined, and then any further lookups will now break the code.
What you can do is use another variable for the loop iteration:
var temp;
for (index = 0, length = property.length; index < length; index++) {
temp = dataLayer[property[index]];
if (!temp) break;
}
return temp;
This will leave your dataLayer object intact.
Although your code is so obsfucated (one-character variable names, abuse of the comma operator, etc.) that its hard to tell for sure, it seems that you need to fix a few things before moving on.
Properties prefixed with an underscore are meant to be private. They are subject to change, and by change I mean your app randomly breaking. Use the public API.
Parsing strings out by hand is a lot of work for seemingly little gain. Is the use case for get('page.id') over get('page').id really so compelling?
Your code is incomprehensible. This is the kind of output one would expect of a minifier: it makes it hard to understand what any of it does/is supposed to do.
Unless a third-party API is so integral to your application that replacing it would require a rewrite no matter what (e.g. google maps) or so well-known that it has umpteen clones (jquery), its is generally a good idea to wrap third-party library calls so you can change the library later.
I realize this does not answer your question, but its way too long for a comment and it would be remiss of me to not point out the bright red targets (plural) you've painted on your feet prior to polishing your firearm.
As for your actual question (post-edit), you're on the right track. But I'd make it a curried function so that you can dynamically access different properties. We're going to ignore for one minute the huge mistake that is accessing private properties just to get the point across:
function accessDataCache(cache) {
return function(dataLayer) {
return function(namespaceObj) {
return function(property) {
return namespaceObj[cache][dataLayer][property];
};
};
};
};
var getFn = accessDataCache('_cache')('_dataLayer')(someTool);
getFn('page');
You can now also mix and match if you need other stuff:
var getSomeOtherCachedThing = accessDataCache('_cache')('_someOtherThing')(someTool);
All of that is quite tedious to write out by hand, so I recommend using something like lodash or Ramda and .curry to achieve the effect:
var accessCacheData = R.curry(function(cache, dataLayer, namespaceObj, property) {
return namespaceObj[cache][dataLayer][property];
});

Javascript: How to dynamicly add a number to a variable name?

Say I have to following code:
var numb = $(selector).length;
And now I want to dynamicly make variables based on this:
var temp+numb = ...
How would I be able to do this?
Edit:
I know some of you will tell me to use an array. Normally I would agree but in my case the var is already an array and I rly see no other solution than creating dynamic names.
Variables in Javascript are bound to objects. Objects accept both . and [] notation. So you could do:
var num = 3;
window["foo"+num] = "foobar";
console.log(foo3);
PS - Just because you can do that doesn't mean you should, though.
In global scope (not recommended):
window["temp"+numb]='somevalue;
window.console && console.log(temp3);
In a scope you create - also works serverside where there is no window scope
var myScope={};
myScope["temp"+numb]="someValue";
window.console && console.log(myScope.temp3);

Instantiating class in loop in javascript uses last value

First of all, I'm aware there are many questions about closures in JavaScript, especially when it comes to loops. I've read through many of them, but I just can't seem to figure out how to fix my own particular problem. My main experience lies with C#, C++ and some ASM and it is taking some getting used to JavaScript.
I'm trying to populate a 3-dimensional array with new instances of a class (called Tile) in some for loops. All I want to do is pass along a reference to some other class (called Group) that gets instantiated in the first loop (and also added to another array). As you might have guessed, after the loops are done, every instance of the Tile class has a reference to the same Group object, namely the last one to be created.
Apparently instead of passing a reference to the Group object, a reference to some variable local to the function is passed along, which is updated in every iteration of the loop. My assumption is that solving this problem has something to do with closures as this appears to be the case with many similar problems I've come across while looking for a solution.
I've posted some trimmed down code that exposes the core of the problem on jsFiddle:
//GW2 namespace
(function( GW2, $, undefined ) {
//GW2Tile class
GW2.Tile = function(globalSettings, kineticGroup)
{
//Private vars
var tilegroup = kineticGroup;
// console.log(tilegroup.grrr); //Shows the correct value
var settings = globalSettings;
this.Test = function(){
console.log(tilegroup.grrr);
}
this.Test2 = function(group){
console.log(group.grrr);
}
} //Class
}( window.GW2 = window.GW2 || {}, jQuery ));
var zoomGroups = [];
var tiles = [];
var settings = {};
InitArrays();
tiles[0,0,0].Test(); //What I want to work, should give 0
tiles[0,0,0].Test2(zoomGroups[0]); //How I'd work around the issue
function InitArrays(){
var i, j, k, zoomMultiplier, tile;
for(i = 0; i <= 2; i++){
zoomGroups[i] = {};
zoomGroups[i].grrr = i;
tiles[i] = [];
zoomMultiplier = Math.pow(2, i);
for(j = 0; j < zoomMultiplier; j++){
tiles[i,j] = [];
for(k = 0; k < zoomMultiplier; k++){
tile = new GW2.Tile(settings, zoomGroups[i]);
tiles[i,j,k] = tile;
}
}
}
}
Up till now when working with JavaScript, I've generally fiddled with the code a bit to make it work, but I'm tired of using work-arounds that look messy as I know there should actually be some fairly simple solution. I'm just not fond of asking for help, but this is really doing my head in. Any help is very much appreciated.
Multidimensional arrays
The problem
The first issue with your code above is how you are attempting to create multidimensional arrays.
The syntax you are using is:
tiles[0,0,0]
However, the way JavaScript will interpret this is:
tiles[0]
Accessing a multidim array
If you wish to access a multidim array you have to use:
tiles[0][0][0]
And to create a multidim array you would need to do the following:
tiles = [];
tiles[0] = [];
tiles[0][0] = [];
tiles[0][0][0] = 'value';
or:
tiles = [[['value']]];
With respect to your code
In your code you should be using:
tiles[i][j][k] = tile;
But you should also make sure that each sub array actually exists before setting it's value, otherwise you'll get undefined or illegal offset errors.
You can do this by way of:
(typeof tiles[i] === 'undefined') && (tiles[i] = []);
(typeof tiles[i][j] === 'undefined') && (tiles[i][j] = []);
tiles[i][j][k] = tile;
Obviously the above can be optimised depending on how you are traversing your loops i.e. it would be best to make sure the tiles[i] level exists as an array before stepping in to the the [j] loop, and then not worry about checking it's existence again whilst stepping j.
Other options
Depending on what your dataset is, or at least what you hope to do with the tiles array it can be worth considering using an object instead:
/// set up
tiles = {};
/// assignment
tiles[i+','+j+','+k] = 'value';
However this method is likely to be slower, although I've been proved wrong a number of times by my assumptions and differing JavaScript interpreters. This would probably be were jsPerf would be your friend.
Optimisation
One benefit of using the tiles[i][j][k] approach is that it gives you the chance to optimise your references. For example, if you were about to process a number of actions at one level of your multidimensional array, you should do this:
/// set up
var ij = tiles[i][j];
/// use in loops or elsewhere
ij[k] = 'value'
This is only of benefit if you were to access the same level more than once however.

javascript question: functionName.VariableName?

I had the following question in a test today. But i had not see something like functionName.VariableName before. Not sure how that works.
Would be great if you can tell me the solution:
function Item(itemName)
{
var next_item_id = 1;
Item.item_name = itemName;
Item.item_id = next_item_id++;
}
var Item1 = Item('Desktop');
var Item2 = Item('Laptop');
var Item3 = Item('Monitor');
Anything wrong with the code above? if yes fix it. (The problem i would see is next_item_id is always 1, need to make it global?)
Modify the function so that the variable “next_item_id”, cannot be modified during run time.
My own question, how does the variable like Item.item_name work? I want to google it, but not sure what I should search for.
Thanks.
Your thinking is close in that next_item_id will always be 1, but it's generally not recommended to pollute the global namespace. Instead, wrap it in an anonymous function:
(function() {
var next_item_id = 1;
function Item(itemName)
{
//Use "this" to apply the property to the instance only
this.item_name = itemName;
this.item_id = next_item_id++;
}
var Item1 = new Item('Desktop');
var Item2 = new Item('Laptop');
var Item3 = new Item('Monitor');
})()
Also, as in Java, the general best practice in Javascript is to use camelCase rather than under_scores. Constructors are generally in UpperCamelCase. Examples:
Array //UpperCamelCase
Object.prototype.toString //toString is camelCase
This question is ambiguous, and, depending on the interpretation, there can be a number of possible answers. next_item_id is a "var" declared inside a function and naturally has an internal [[DontDelete]] and [[DontEnum]] flag. If it's a "var" and we're not using "this" as shown in my modified code, the variable is inherently not accessible outside of the function or its nested functions and therefore cannot be modified. You can use the non-standard const or you can create an object and use Object.defineProperty to create a setter that returns false assuming an ES5-compatible environment, etc.
Functions are objects in Javascript. All objects can have "properties."
Javascript functions are also objects and can have properties.
They behave like static fields in Java.
You're going about it all wrong. I'm assuming that you want to set internal variables.
If you want to create a 'constructor', do something like this:
function Item(itemName)
{
var next_item_id = 1;
this.item_name = itemName;
this.item_id = next_item_id++;
}
var Item1 = new Item('Desktop');
var Item2 = new Item('Laptop');
var Item3 = new Item('Monitor');
Both item_name and item_id will be publicly available. To make use next_item_id like you want, try this:
Item.next_item_id = 1;
Then in your constructor, do Item.next_item_id++;
Your final code should look something like this:
function Item(itemName)
{
this.item_name = itemName;
this.item_id = Item.next_item_id++;
}
Item.next_item_id = 1;
var Item1 = new Item('Desktop');
var Item2 = new Item('Laptop');
var Item3 = new Item('Monitor');
What this is doing is attaching a property to the object Item. You might be thinking, "Item is a function! How is this possible?!". Nearly everything in JavaScript is an object with mutable properties. The only things that aren't are the keywords null and undefined (AFAIK).
Item is still a function, but it also has a property next_item_id.
Also, using new will create a new instance. This is a similar concept as in Java and other programming languages. Just calling Item is like calling a function, and you'll get back whatever is returned from it (through an explicit return statement, otherwise undefined).
Answer for question 2 : Modify the function so that the variable “next_item_id”, cannot be modified during run time.
If I have interpreted your question correctly, you want to have Item.item_id as a constant that cannot be modified any where outside the constructor. I don't think we can have constants in JS.
Item1.item_id = someValue
Above line, used some where can change the item_id value of Item1.

Categories