(function(re){ /* Searches through all entities using the selector conditions //identifiers * identifies all ^ identifies a bind # identifies an id ! identifies not //select all entities re('*'); //select all entities with 2d and ai components re('2d ai'); //select all 2d entities without the monster component re('2d -monster'); //select all draw entities and entities with the id equal to asset re('draw #asset') //returns a random entity .random(); //select all entities with id of bob and player //warning you cannot query for two ids re('#bob player') //takes values from all objects and returns an array .pluck('width height'); //find all bitmap entities with update event. re('bitmap ^update'); //add color comp to all text components re('text').comp('color'); //custom entity search re(function(index){ if(entity.has('health') && entity.health > 0){ //add to query return true; } //skip entity return false; }) //calls reset method on all entities .method('reset'); re('#player')[0].health = 100; */ var q = function(selector){ if(selector){ this.query(selector); } } /* Sort a query string into objects */ q._toObj = function(query){ //check if its caught if(q.c[query]){ return q.c[query]; } //convert to object var temp = query.split(' '); var comps = []; var binds = []; var minus = []; var id = ''; //split string var fl; var val; for(var j = temp.length; j--;){ fl = temp[j].charAt(0); val = temp[j].substr(1); if(fl == '^'){ binds.push(val); } else if(fl == '!'){ minus.push(val); } else if(fl == '#'){ id = val; } else { comps.push(temp[j]); } } var comp = { comp:comps, on:binds, not:minus, id:id }; //catch it q.c[query] = comp; return comp; } q.c = {}; var p = q.prototype = new Array; p.query = function(select){ select = select || ''; var l = re._e.length, i = -1, e; if(re.is(select, 'string')){ if(select == '*'){ this.push.apply(this, re._e.slice()); return this; } //optimize search and cache var obj = q._toObj(select); while(++i < l && (e = re._e[i])){ if(e.has(obj)) this.push(e); } } else if(re.is(select, 'function')){ while(++i < l && (e = re._e[i])){ if(select.call(e, i, l)) this.push(e); } } else if(re.is(select, 'array')){ this.push.apply(this, select); } return this; } /* Calls the given method name on all entities. re('enemies').invoke('rest'); */ p.invoke = function(m){ var b = Array.prototype.slice.call(arguments, 1); return this.each(function(e){ e[m].apply(e, b); }); } /* example re('draw').each(function(index, length){ }); returning false will break the loop */ p.each = function(m, context){ var l = this.length, i = -1, e; while(++i < l && (e = this[i]) != null && m.call(context || this, e, i, this) !== false); return this; }; /* The map method allows multidimensional loops. //map through and increase y every 3 entities. re('draw').tilemap(3, function(e, x, y){ e.x(x * width); e.y(Y * height); }); //so instead of getting this back [e,e,e,e,e...] //you will get this [ [e,e,e], [e,e,e], [e,e,e] ... ] returning false will break the loop */ p.tilemap = function(w, method, context){ var x = 0; var y = 0; return this.each(function(i, l){ if(method.call(context, this[i], x, y, i, this) == false) return false; x++; if(x == w){ x = 0; y++; } }); } /* Returns an array of all components in the query. */ p.comps = function(){ var l = []; this.each(function(e){ var k = e.comps(); for(var i=0; i lowest){ lowest = next; val = e; } }); return val; } //without this filter would return a normal array. p.filter = function(){ return re(Array.prototype.filter.apply(this, arguments)); } //Removes all elements in the array that pass the truth test p.reject = function(it, c){ for(var i=0; i