UNPKG

@spearwolf/twopoint5d

Version:

a library to create 2.5d realtime graphics and pixelart with three.js

145 lines 6.22 kB
export class RepeatingTilesProvider { #tileIds; #rows = 0; #cols = 0; get tileIds() { return this.#tileIds; } set tileIds(tileIds) { this.#tileIds = tileIds; this.#rows = tileIds.length; this.#cols = tileIds[0].length; } constructor(tileIds, limitToAxis = 'none') { if (typeof tileIds === 'number') { this.tileIds = [[tileIds]]; } else if (Array.isArray(tileIds)) { if (typeof tileIds[0] === 'number') { this.tileIds = [tileIds]; } else if (Array.isArray(tileIds[0]) && typeof tileIds[0][0] === 'number') { this.tileIds = tileIds; } } if (!this.tileIds) { this.tileIds = [[]]; } this.limitToAxis = limitToAxis; } getTileIdAt(col, row) { switch (this.limitToAxis) { case 'vertical': if (col >= 0 && col < this.#cols) { row = row < 0 ? row + Math.ceil(-row / this.#rows) * this.#rows : row; return this.#tileIds[row % this.#rows][col]; } break; case 'horizontal': if (row >= 0 && row < this.#rows) { col = col < 0 ? col + Math.ceil(-col / this.#cols) * this.#cols : col; return this.#tileIds[row][col % this.#cols]; } break; case 'none': default: col = col < 0 ? col + Math.ceil(-col / this.#cols) * this.#cols : col; row = row < 0 ? row + Math.ceil(-row / this.#rows) * this.#rows : row; return this.#tileIds[row % this.#rows][col % this.#cols]; } return 0; } getTileIdsWithin(left, top, width, height, target) { target = target ?? new Uint32Array(width * height); if (this.#cols === 0 || this.#rows === 0) { target.fill(0); return target; } const right = left + width - 1; const bottom = top + height - 1; switch (this.limitToAxis) { case 'vertical': if (right < 0 || left >= this.#cols) { target.fill(0); } else { const leftOffset = -left; let tilesRowOffset = top < 0 ? top + Math.ceil(-top / this.#rows) * this.#rows : top; for (let y = 0; y < height; y++) { const tiles = this.tileIds[tilesRowOffset++ % this.#rows].slice(0, width - leftOffset); const rowOffset = y * width; if (leftOffset > 0) { target.fill(0, rowOffset, rowOffset + leftOffset); } target.set(tiles, rowOffset + leftOffset); const lastCol = rowOffset + width; const tilesCount = tiles.length; target.fill(0, rowOffset + leftOffset + tilesCount, lastCol); } } break; case 'horizontal': if (bottom < 0 || top >= this.#rows) { target.fill(0); } else { let skipPatternRows = 0; if (top < 0) { skipPatternRows = -top; target.fill(0, 0, skipPatternRows * width); } for (let y = skipPatternRows; y < height; y++) { const patternRow = y + top; const targetRowOffset = y * width; if (patternRow < this.#rows) { if (this.#cols === 1) { target.fill(this.tileIds[patternRow][0], targetRowOffset, targetRowOffset + width); } else { let x = 0; let col = (left < 0 ? left + Math.ceil(-left / this.#cols) * this.#cols : left) % this.#cols; while (x < width) { const tiles = this.tileIds[patternRow].slice(col, col + width - x); target.set(tiles, targetRowOffset + x); x += tiles.length; col = (col + x) % this.#cols; } } } else { target.fill(0, targetRowOffset); break; } } } break; case 'none': if (this.#cols === 1 && this.#rows === 1) { target.fill(this.tileIds[0][0]); } else { const topOffset = top < 0 ? top + Math.ceil(-top / this.#rows) * this.#rows : top; for (let y = 0; y < height; y++) { const patternRow = (y + topOffset) % this.#rows; const targetRowOffset = y * width; if (this.#cols === 1) { target.fill(this.tileIds[patternRow][0], targetRowOffset, targetRowOffset + width); } else { let x = 0; let col = (left < 0 ? left + Math.ceil(-left / this.#cols) * this.#cols : left) % this.#cols; while (x < width) { const tiles = this.tileIds[patternRow].slice(col, col + width - x); target.set(tiles, targetRowOffset + x); x += tiles.length; col = (col + x) % this.#cols; } } } } break; } return target; } } //# sourceMappingURL=RepeatingTilesProvider.js.map