import Field from "./Field.js"; import Tileset from "./Tileset.js"; import TilorswiftEvent from "./events/TilorswiftEvent.js"; import GraphicSet from "../../js/GraphicSet.js"; export default class Terrain { constructor(tileset, tilesX, tilesY, backgroundColor = 'black') { this.tileset = tileset; this.fields = []; this.tilesX = tilesX; this.tilesY = tilesY; this.entranceTileX = undefined; this.entranceTileY = undefined; this.targetTileX = undefined; this.targetTileY = undefined; this.backgroundColor = backgroundColor; this.backgroundImage = undefined; this.htmlElement = document.createElement('table'); this.brushTileIndex = 0; this.init(); } init() { this.htmlElement.id = 'level'; this.htmlElement.style.width = this.tileset.getTileWidth() * this.tilesX + 'px'; this.htmlElement.style.height = this.tileset.getTileHeight() * this.tilesY + 'px'; for (let r = 0; r < this.tilesY; r++) { this._insertRow(); } window.addEventListener( TilorswiftEvent.BUTTON_TILE_CLICKED, (event) => { this.brushTileIndex = event.button.index; } ) } getElement() { return this.htmlElement; } getTileset() { return this.tileset; } getWidth() { return this.tilesX * this.tilest.getTileWidth(); } getHeight() { return this.tilesY * this.tilest.getTileHeight(); } addRows(index, quantity = 1) { for (let q = 0; q < quantity; q++) { this._insertRow(index); this.tilesY++; this.entranceTileY = this.entranceTileY === undefined ? undefined : this.entranceTileY + 1; this.targetTileY = this.targetTileY === undefined ? undefined : this.targetTileY + 1; } this.htmlElement.style.height = this.tileset.getTileHeight() * this.tilesY + 'px'; } _insertRow(index = undefined) { const row = []; const tr = document.createElement('tr'); for (let col = 0; col < this.tilesX; col++) { const field = new Field(this.tileset, col, this.fields.length); row.push(field); tr.appendChild(field.getElement()); } if (index === undefined || index >= this.tilesY - 1) { this.fields.push(row); this.htmlElement.appendChild(tr); } else if (index === 0) { this.fields = [row].concat(this.fields); this.htmlElement.insertBefore(tr, this.htmlElement.childNodes[index]); } else { this.fields = this.fields.slice(0, index).concat([row]).concat(this.fields.slice(index)); this.htmlElement.insertBefore(tr, this.htmlElement.childNodes[index]); } } addColumns(index, quantity = 1) { for (let c = 0; c < quantity; c++) { this._insertColumn(index); this.tilesX++; this.entranceTileX = this.entranceTileX === undefined ? undefined : this.entranceTileX + 1; this.targetTileX = this.targetTileX === undefined ? undefined : this.targetTileX + 1; } this.htmlElement.style.width = this.tileset.getTileWidth() * this.tilesX + 'px'; } _insertColumn(index = undefined) { if (index === undefined || index > this.tilesX - 1) { index = this.tilesX; } for (let y = 0; y < this.tilesY; y++) { let field = new Field(this.tileset); this.fields[y] = this.fields[y].slice(0, index).concat(field).concat(this.fields[y].slice(index)); let htmlRow = this.htmlElement.childNodes[y]; htmlRow.insertBefore(field.getElement(), htmlRow.childNodes[index]); } } setFieldIndex(x, y, index) { this.fields[y][x].setIndex(index); } setEntrancePoint(tileX, tileY) { if (this.fields[tileY][tileX].index === -1) { if (this.entranceTileX !== undefined && this.entranceTileY !== undefined) { this.fields[this.entranceTileY][this.entranceTileX].setEntrancePoint(false); } this.entranceTileX = tileX; this.entranceTileY = tileY; this.fields[tileY][tileX].setEntrancePoint(true); } } setTargetPoint(tileX, tileY) { if (this.fields[tileY][tileX].index === -1) { if (this.targetTileX !== undefined && this.targetTileY !== undefined) { this.fields[this.targetTileY][this.targetTileX].setTargetPoint(false); } this.targetTileX = tileX; this.targetTileY = tileY; this.fields[tileY][tileX].setTargetPoint(true); } } getFieldCoordinates(field) { for (let y = 0; y < this.fields.length; y++) { for (let x = 0; x < this.fields[y].length; x++) { if (this.fields[y][x] === field) { return {x: x, y: y}; } } } return undefined; } hasEntrancePoint() { return this.entranceTileX !== undefined && this.entranceTileY !== undefined; } hasTargetPoint() { return this.targetTileX !== undefined && this.targetTileY !== undefined; } static createFromJson(levelData) { const graphicSet = GraphicSet[levelData.tileset]; const tileset = new Tileset(levelData.tileset); const terrain = new Terrain(tileset, levelData.columns, levelData.rows, graphicSet.backgroundColor); terrain.backgroundImage = graphicSet.backgroundImage ?? undefined; for (let y = 0; y < levelData.rows; y++) { for (let x = 0; x < levelData.columns; x++) { terrain.setFieldIndex(x, y, levelData.matrix[y][x]); if (x === levelData.startX && y === levelData.startY) { terrain.setEntrancePoint(x, y); } else if (x === levelData.targetX && y === levelData.targetY) { terrain.setTargetPoint(x, y); } } } return terrain; } getFieldNeighbours(field) { const neighbours = []; for (let x = Math.max(0, field.x - 1); x < Math.min(this.tilesX, field.x + 2); x++) { for (let y = Math.max(0, field.y - 1); y < Math.min(this.tilesY, field.y + 2); y++) { if (field.x === x && field.y === y) { continue; } neighbours.push(this.fields[y][x]); } } return neighbours; } hasFieldNeighbour(field, offsetX, offsetY) { const x = field.x + offsetX; const y = field.y + offsetY; if (x < 0 || x > this.tilesX - 1) { return true; } if (y < 0 || y > this.tilesY - 1) { return true; } return this.fields[y][x].index > -1; } getFieldNeighbourCode(field) { let code = ''; if (!this.hasFieldNeighbour(field, -1, 0)) { code += 'l'; } if (!this.hasFieldNeighbour(field, 0, -1)) { code += 't'; } if (!this.hasFieldNeighbour(field, 1, 0)) { code += 'r'; } if (!this.hasFieldNeighbour(field, 0, 1)) { code += 'b'; } return code; } }