import TilePropertyHelper, { COLOR_TILES } from './TilePropertyHelper.js'; export default class ButtonBarrierSystem { /** * @param {Phaser.Scene} scene * @param {Phaser.Tilemaps.TilemapLayer} barriersLayer */ constructor(scene, barriersLayer) { this._scene = scene; this._barriersLayer = barriersLayer; this._buttons = []; // [{ col, row, color }] this._barriers = []; // [{ col, row, color }] this._activeColor = null; } /** * Scan the barriers layer to build button/barrier registries and set initial * collision state. Call once after the layer is created. */ init() { const layer = this._barriersLayer; layer.forEachTile((tile) => { if (tile.index <= 0) return; const props = TilePropertyHelper.getPropsByGID(tile.index); if (props.button) { this._buttons.push({ col: tile.x, row: tile.y, color: props.color }); if (props.pressed) { this._activeColor = props.color; } } else if (props.barrier) { this._barriers.push({ col: tile.x, row: tile.y, color: props.color }); } }); this._rebuildCollision(); } /** * Press the button at the given tile coordinates. * Updates button/barrier tile indices and rebuilds collision. * @param {number} col Tile column * @param {number} row Tile row */ pressButton(col, row) { const entry = this._buttons.find(b => b.col === col && b.row === row); if (!entry) return; if (entry.color === this._activeColor) return; // Already active this._activeColor = entry.color; // Update all button tiles for (const btn of this._buttons) { const gids = COLOR_TILES[btn.color]; const newGID = btn.color === this._activeColor ? gids.btn_on : gids.btn_off; this._barriersLayer.putTileAt(newGID, btn.col, btn.row); } // Update all barrier tiles for (const bar of this._barriers) { const gids = COLOR_TILES[bar.color]; const newGID = bar.color === this._activeColor ? gids.barrier_open : gids.barrier_solid; this._barriersLayer.putTileAt(newGID, bar.col, bar.row); } this._rebuildCollision(); } /** * Returns true if the given GID is an unpressed button (a valid press target). * @param {number} gid */ isButtonTile(gid) { const props = TilePropertyHelper.getPropsByGID(gid); return !!(props.button && !props.pressed); } /** * Rebuild which tiles in the barriers layer have active collision. * Solid: all unpressed buttons + all non-active-color solid barriers. * Passable: active-color barriers + pressed button. */ _rebuildCollision() { const solidGIDs = []; for (const [color, gids] of Object.entries(COLOR_TILES)) { if (color !== this._activeColor) { solidGIDs.push(gids.btn_off); solidGIDs.push(gids.barrier_solid); } // Active color's btn_on and barrier_open remain passable (not added) } // setCollision(indices, collides, recalculate) // Passing false to a second call clears existing, then we set only solidGIDs this._barriersLayer.setCollision(solidGIDs, true, true); // Explicitly remove collision from active-color tiles (in case of leftovers) if (this._activeColor) { const gids = COLOR_TILES[this._activeColor]; this._barriersLayer.setCollision( [gids.btn_on, gids.barrier_open], false, true ); } } }