1 var jaws = (function(jaws) { 2 3 /** 4 * @class Create and access tilebased 2D maps with very fast access of invidual tiles. "Field Summary" contains options for the TileMap()-constructor. 5 * 6 * @property {array} cell_size Size of each cell in tilemap, defaults to [32,32] 7 * @property {array} size Size of tilemap, defaults to [100,100] 8 * @property {function} sortFunction Function used by sortCells() to sort cells, defaults to no sorting 9 * 10 * @example 11 * var tile_map = new TileMap({size: [10, 10], cell_size: [16,16]}) 12 * var sprite = new jaws.Sprite({x: 40, y: 40}) 13 * var sprite2 = new jaws.Sprite({x: 41, y: 41}) 14 * tile_map.push(sprite) 15 * 16 * tile_map.at(10,10) // [] 17 * tile_map.at(40,40) // [sprite] 18 * tile_map.cell(0,0) // [] 19 * tile_map.cell(1,1) // [sprite] 20 * 21 */ 22 jaws.TileMap = function TileMap(options) { 23 if( !(this instanceof arguments.callee) ) return new arguments.callee( options ); 24 25 jaws.parseOptions(this, options, this.default_options); 26 this.cells = new Array(this.size[0]); 27 28 for(var col=0; col < this.size[0]; col++) { 29 this.cells[col] = new Array(this.size[1]); 30 for(var row=0; row < this.size[1]; row++) { 31 this.cells[col][row] = [] // populate each cell with an empty array 32 } 33 } 34 } 35 36 jaws.TileMap.prototype.default_options = { 37 cell_size: [32,32], 38 size: [100,100], 39 sortFunction: null 40 } 41 42 /** Clear all cells in tile map */ 43 jaws.TileMap.prototype.clear = function() { 44 for(var col=0; col < this.size[0]; col++) { 45 for(var row=0; row < this.size[1]; row++) { 46 this.cells[col][row] = []; 47 } 48 } 49 } 50 51 /** Sort arrays in each cell in tile map according to sorter-function (see Array.sort) */ 52 jaws.TileMap.prototype.sortCells = function(sortFunction) { 53 for(var col=0; col < this.size[0]; col++) { 54 for(var row=0; row < this.size[1]; row++) { 55 this.cells[col][row].sort( sortFunction ) 56 } 57 } 58 } 59 60 /** 61 * Push obj (or array of objs) into our cell-grid. 62 * 63 * Tries to read obj.x and obj.y to calculate what cell to occopy 64 */ 65 jaws.TileMap.prototype.push = function(obj) { 66 var that = this; 67 if(obj.forEach) { 68 obj.forEach( function(item) { that.push(item) } ); 69 return obj; 70 } 71 if(obj.rect) { 72 return this.pushAsRect(obj, obj.rect()); 73 } 74 else { 75 var col = parseInt(obj.x / this.cell_size[0]); 76 var row = parseInt(obj.y / this.cell_size[1]); 77 return this.pushToCell(col, row, obj); 78 } 79 } 80 /** 81 * Push objects into tilemap. 82 * Disregard height and width and only use x/y when calculating cell-position 83 */ 84 jaws.TileMap.prototype.pushAsPoint = function(obj) { 85 if(Array.isArray(obj)) { 86 for(var i=0; i < obj.length; i++) { this.pushAsPoint(obj[i]) } 87 return obj; 88 } 89 else { 90 var col = parseInt(obj.x / this.cell_size[0]); 91 var row = parseInt(obj.y / this.cell_size[1]); 92 return this.pushToCell(col, row, obj); 93 } 94 } 95 96 /** push obj into cells touched by rect */ 97 jaws.TileMap.prototype.pushAsRect = function(obj, rect) { 98 var from_col = parseInt(rect.x / this.cell_size[0]); 99 var to_col = parseInt((rect.right-1) / this.cell_size[0]); // -1 100 //jaws.log("rect.right: " + rect.right + " from/to col: " + from_col + " " + to_col, true) 101 102 for(var col = from_col; col <= to_col; col++) { 103 var from_row = parseInt(rect.y / this.cell_size[1]); 104 var to_row = parseInt((rect.bottom-1) / this.cell_size[1]); // -1 105 106 //jaws.log("rect.bottom " + rect.bottom + " from/to row: " + from_row + " " + to_row, true) 107 for(var row = from_row; row <= to_row; row++) { 108 // console.log("pushAtRect() col/row: " + col + "/" + row + " - " + this.cells[col][row]) 109 this.pushToCell(col, row, obj); 110 } 111 } 112 return obj 113 } 114 115 /** 116 * Push obj to a specific cell specified by col and row 117 * If cell is already occupied we create an array and push to that 118 */ 119 jaws.TileMap.prototype.pushToCell = function(col, row, obj) { 120 this.cells[col][row].push(obj); 121 if(this.sortFunction) this.cells[col][row].sort(this.sortFunction); 122 return this 123 } 124 125 // 126 // READERS 127 // 128 129 /** Get objects in cell that exists at coordinates x / y */ 130 jaws.TileMap.prototype.at = function(x, y) { 131 var col = parseInt(x / this.cell_size[0]); 132 var row = parseInt(y / this.cell_size[1]); 133 // console.log("at() col/row: " + col + "/" + row) 134 return this.cells[col][row]; 135 } 136 137 /** Returns occupants of all cells touched by 'rect' */ 138 jaws.TileMap.prototype.atRect = function(rect) { 139 var objects = []; 140 var items; 141 142 try { 143 var from_col = parseInt(rect.x / this.cell_size[0]); 144 if (from_col < 0) { 145 from_col = 0; 146 } 147 var to_col = parseInt(rect.right / this.cell_size[0]); 148 if (to_col >= this.size[0]) { 149 to_col = this.size[0] - 1; 150 } 151 var from_row = parseInt(rect.y / this.cell_size[1]); 152 if (from_row < 0) { 153 from_row = 0; 154 } 155 var to_row = parseInt(rect.bottom / this.cell_size[1]); 156 if (to_row >= this.size[1]) { 157 to_row = this.size[1] - 1; 158 } 159 160 for(var col = from_col; col <= to_col; col++) { 161 for(var row = from_row; row <= to_row; row++) { 162 this.cells[col][row].forEach( function(item, total) { 163 if(objects.indexOf(item) == -1) { objects.push(item) } 164 }) 165 } 166 } 167 } 168 catch(e) { 169 // ... problems 170 } 171 return objects 172 } 173 174 /** Returns all objects in tile map */ 175 jaws.TileMap.prototype.all = function() { 176 var all = []; 177 for(var col=0; col < this.size[0]; col++) { 178 for(var row=0; row < this.size[1]; row++) { 179 this.cells[col][row].forEach( function(element, total) { 180 all.push(element) 181 }); 182 } 183 } 184 return all 185 } 186 187 /** Get objects in cell at col / row */ 188 jaws.TileMap.prototype.cell = function(col, row) { 189 return this.cells[col][row] 190 } 191 192 /** Debugstring for TileMap() */ 193 jaws.TileMap.prototype.toString = function() { return "[TileMap " + this.size[0] + " cols, " + this.size[1] + " rows]" } 194 195 return jaws; 196 })(jaws || {}); 197 198 // Support CommonJS require() 199 if(typeof module !== "undefined" && ('exports' in module)) { module.exports = jaws.TileMap } 200