114 lines
3.8 KiB
JavaScript
114 lines
3.8 KiB
JavaScript
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
|
|
);
|
|
}
|
|
}
|
|
}
|