import RetroSprite from "./RetroSprite.js"; import RetroArchitectureTile from "./RetroArchitectureTile.js"; import GeometryRectCollection from "../geometry/GeometryRectCollection.js"; import GeometryPoint from "../geometry/GeometryPoint.js"; export default class RetroArchitecture { constructor(tilesetSprite, tiles, columns, rows) { this.tileset = tilesetSprite; this.tiles = tiles; this.rows = rows; this.columns = columns; this.matrix = []; this.tileWidth = this.tileset.getWidth() / this.tiles; this.tileHeight = this.tileset.getHeight(); this.init(); } init() { for (let y = 0; y < this.rows; y++) { this.matrix.push(Array(this.columns).fill(null)); } } getCollisionRects(rect) { let posX = Math.floor(rect.position.x / this.tileWidth) - 2; let posY = Math.floor(rect.position.y / this.tileHeight) - 2; let rangeX = parseInt( posX + rect.width / this.tileWidth) + 4; let rangeY = parseInt(posY + rect.height / this.tileHeight) + 4; let collection = new GeometryRectCollection(); for (let y = Math.max(0, posY); y < rangeY; y++) { for (let x = Math.max(0, posX); x < rangeX; x++) { if (y < this.matrix.length && x < this.matrix[y].length && this.matrix[y][x] !== null) { let intersection = this.matrix[y][x].rect.getRectIntersection(rect); if (intersection !== null) { collection.addRect(intersection); } } } } return collection; } hasRectCollision(rect) { let posX = Math.floor(rect.position.x / this.tileWidth) - 2; let posY = Math.floor(rect.position.y / this.tileHeight) - 2; let rangeX = parseInt( posX + rect.width / this.tileWidth) + 4; let rangeY = parseInt(posY + rect.height / this.tileHeight) + 4; for (let y = Math.max(0, posY); y < rangeY; y++) { for (let x = Math.max(0, posX); x < rangeX; x++) { if (this.matrix[y][x] !== null) { if (this.matrix[y][x].rect.getRectIntersection(rect) !== null) { return true; } } } } return false; } getTileForPosition(position, offsetX = 0, offsetY = 0) { let x = parseInt(position.x / this.tileWidth) + offsetX; let y = parseInt(position.y / this.tileHeight) + offsetY; if (x < 0 || x >= this.columns || y < 0 || y >= this.rows) { return null; } return {x: x, y: y}; } getCeilingHeight(position) { let tilePosition = this.getTileForPosition(position, 0); while (tilePosition !== null && tilePosition.y > 0) { if (this.matrix[tilePosition.y][tilePosition.x] !== null) { return tilePosition.y * this.tileHeight + this.tileHeight; } tilePosition.y--; } return 0; } getGroundHeight(position) { let tilePosition = this.getTileForPosition(position); while (tilePosition !== null && tilePosition.y < this.rows) { if (this.matrix[tilePosition.y][tilePosition.x] !== null) { return tilePosition.y * this.tileHeight; } tilePosition.y++; } return this.tileHeight * this.rows; } getWallRight(position) { let tilePosition = this.getTileForPosition(new GeometryPoint(position.x, position.y), 1, 0); while (tilePosition !== null && tilePosition.x < this.columns) { if (this.matrix[tilePosition.y][tilePosition.x] !== null) { return tilePosition.x * this.tileWidth; } tilePosition.x++; } return this.tileWidth * this.columns; } getWallLeft(position) { let tilePosition = this.getTileForPosition(new GeometryPoint(position.x, position.y), -1,0); while (tilePosition !== null && tilePosition.x > 0) { if (this.matrix[tilePosition.y][tilePosition.x] !== null) { return tilePosition.x * this.tileWidth + this.tileWidth; } tilePosition.x--; } return 0; } draw(context) { for (let y = 0; y < this.rows; y++) { for (let x = 0; x < this.columns; x++) { let field = this.matrix[y][x]; if (field !== null) { context.drawImage( this.tileset.canvas, field.tile * this.tileWidth, 0, this.tileWidth, this.tileHeight, x * this.tileWidth, y * this.tileHeight, this.tileWidth, this.tileHeight ); } } } } static createFromJson(json) { let data = JSON.parse(json); let tileset = new RetroSprite(data.tileset, data.scale); let architecture = new RetroArchitecture( tileset, data.tiles, data.columns, data.rows ); for (let y = 0; y < data.rows; y++) { for (let x = 0; x < data.columns; x++) { if (data.matrix[y][x] !== null) { architecture.matrix[y][x] = new RetroArchitectureTile( data.matrix[y][x], x * architecture.tileWidth, y * architecture.tileHeight, architecture.tileWidth, architecture.tileHeight ) } } } return architecture; } }