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