import assets from "./assets.js"; import Rect from "./Rect.js"; import Vec2 from "./Vec2.js"; import Texture from "./Texture.js"; function findBounds(arr, bounds) { arr.forEach(e => { let right = (e.x + 1) * assets.tiles.tileWidth; let bottom = (e.y + 1) * assets.tiles.tileHeight; if (right > bounds.size.x) bounds.size.x = right; if (bottom > bounds.size.y) bounds.size.y = bottom; }); } function rightOrBelow(r1, r2) { // r2 right of r1 if ( (r1.top === r2.top && r1.bottom == r2.bottom) && (r1.right + 1 >= r2.left && r1.left <= r2.left)) return true; // r2 below r1 if ( (r1.right === r2.right && r1.left == r2.left) && (r1.bottom + 1 >= r2.top && r1.top <= r2.top)) return true; return false; } function continuous(r1, r2) { return rightOrBelow(r1, r2) || rightOrBelow(r2, r1); } function findGeometry(bounds, arr, geometry) { let allBounds = []; arr.forEach(e => { let eBounds = new Rect(bounds.pos.clone()); eBounds.pos.pixelX += e.x * assets.tiles.tileWidth; eBounds.pos.pixelY += e.y * assets.tiles.tileWidth; eBounds.size.pixelX = assets.tiles.tileWidth; eBounds.size.pixelY = assets.tiles.tileWidth; allBounds.push(eBounds); }); function runPass() { if (allBounds.lenght === 1) { geometry.push(allBounds[0]); allBounds.splice(0, 1); return; } // Find continuous bounds let changed = false; geometry.forEach((g, gi) => { allBounds.forEach((b, bi) => { if (continuous(g, b)) { if (b.left < g.left) g.pixelResizeLeftTo(b.pixelLeft); if (b.right > g.right) g.pixelResizeRightTo(b.pixelRight); if (b.top < g.top) g.pixelResizeTopTo(b.pixelTop); if (b.bottom > g.bottom) g.pixelResizeBottomTo(b.pixelBottom); allBounds.splice(bi, 1); changed = true; } }); }); // If no continuous blocks were found, we need a new rectangle if (!changed) { geometry.push(allBounds[0]); allBounds.splice(0, 1); } } while (allBounds.length > 0) { runPass(); } } function flattened(arr, newArr = []) { arr.forEach(e => { if (e instanceof Array) flattened(e, newArr); else newArr.push(e); }); return newArr; } export default class Structure { constructor(attrs, nestedArr) { this.texture = new Texture(nestedArr); this.attrs = { collides: false, } for (let a of attrs) this.setAttr(a); this.nestedArr = nestedArr; this.bounds = new Rect(); this.geometry = []; } init() { var arr = flattened(this.nestedArr); findBounds(arr, this.bounds); if (this.attrs.collides) { findGeometry(this.bounds, arr, this.geometry); } } draw(ctx) { this.texture.draw(ctx, this.bounds.pos.pixelX, this.bounds.pos.pixelY); } setAttr(attr) { if (this.attrs[attr] == null) throw new Error("Invalid attribute:", attr); this.attrs[attr] = true; return this; } collidesWith(rect) { if (!this.bounds.intersects(rect)) return null; for (let bounds of this.geometry) { if (bounds.intersects(rect)) return bounds; } return null; } }