/* Code for configuring and appending tiles. Every item and block in the game is represented in one unified Tile class. A prototype of an API is provided for players who wish to modify the game, to prevent conflicts from manually setting sections of an array. */ var canGravity = [ ]; function getContrast(r, g, b) { var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; return (yiq >= 128) ? 'black' : 'white'; } function Tile(color, id, isAbstract = false, copyFrom = false, copyFromName = false) { if (copyFrom) { let that = this; this.hook = function () { let oldie = mainTiles.resolve(copyFrom, copyFromName); Object.assign(that, Object.assign({}, oldie, that)); that.attributes = Object.assign({}, that.attributes); that.interactions = that.interactions.concat(oldie.interactions) } } this.color = color; this.id = id; this.number = -1; this.interactions = []; this.attributes = {}; this.attributes.temperature = 0; this.attributes.conduct = 0.01; this.isAbstract = isAbstract; this.color = (color == 'none') ? [181, 204, 253, 1 / 255] : color.replace(/^[^\(]+\(/, '').replace(/\)$/, '').split(',').map(x => 1 * x) if (color == 'random') this.color = [-1, -1, -1]; // ugly and hard-coded, but somehow faster? /* Interactions are used for dynamic functions that depend on world state, while attributes are used for block attributes that are static, or modified by other interactions. I highly suggest you define certain modifiers as a prototype of Tile that returns itself. This allows for prototype chaining within tile definitions. */ } function TileManager(row, row2) { this.tiles = []; this.row = row; this.row2 = row2; this.sel = 0; this.used = {}; } TileManager.prototype.loadSet = function (namespace, tiles) { let path = namespace.split('/'); let elem = document.createElement('a'); elem.textContent = namespace; //elem.href = `#${namespace}` //elem.id = namespace this.row.appendChild(elem); let elem2 = document.createElement('section'); elem2.id = namespace; this.row2.appendChild(elem2); elem.onclick = function (e) { document.querySelectorAll(".selected-group").forEach(function (e) { e.classList.remove("selected-group") }) e.target.classList.add("selected-group"); elem2.classList.add("selected-group"); } for (let tile of tiles) { if (tile.isAbstract) continue; tile.namespace = namespace; tile.number = this.tiles.length; this.tiles.push(tile); canGravity[tile.number] = !tile.attributes.noGravity; if (path.indexOf('secret') != -1) continue; elem = document.createElement('button'); elem.textContent = tile.id; elem.style.color = getContrast(tile.color[0], tile.color[1], tile.color[2]); elem.style.backgroundColor = `rgb(${tile.color[0]}, ${tile.color[1]}, ${tile.color[2]})` elem2.appendChild(elem); elem.addEventListener('click', () => { this.sel = tile.number; }) } } TileManager.prototype.resolveID = function (namespace, name) { let resolved = this.tiles .findIndex(tile => tile.namespace == namespace && tile.id == name ); return resolved } TileManager.prototype.resolve = function (namespace, name) { let id = this.resolveID(namespace, name); return this.tiles[id]; } var mainTiles = new TileManager( document.querySelector('.menu'), document.querySelector('.buttons') ); /* You can theoretically add more tile managers if desired, but you probably shouldn't if you don't know what you are doing. */