Make minimap toggleable
This commit is contained in:
@@ -20,9 +20,10 @@ export class DungeonRenderer {
|
||||
// Minimap
|
||||
private minimapGfx!: Phaser.GameObjects.Graphics;
|
||||
private minimapContainer!: Phaser.GameObjects.Container;
|
||||
private minimapBg!: Phaser.GameObjects.Graphics;
|
||||
private minimapScale = 2; // pixels per tile
|
||||
private minimapPadding = 8;
|
||||
private minimapBg!: Phaser.GameObjects.Rectangle;
|
||||
private minimapPanelWidth = 340; // Match menu size
|
||||
private minimapPanelHeight = 220; // Match menu size
|
||||
private minimapVisible = false; // Off by default
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
this.scene = scene;
|
||||
@@ -35,13 +36,24 @@ export class DungeonRenderer {
|
||||
private initMinimap() {
|
||||
this.minimapContainer = this.scene.add.container(0, 0);
|
||||
this.minimapContainer.setScrollFactor(0); // Fixed to camera
|
||||
this.minimapContainer.setDepth(100);
|
||||
this.minimapContainer.setDepth(1001); // Same as menu
|
||||
|
||||
// Background panel (like menu)
|
||||
this.minimapBg = this.scene.add
|
||||
.rectangle(0, 0, this.minimapPanelWidth, this.minimapPanelHeight, 0x000000, 0.8)
|
||||
.setStrokeStyle(1, 0xffffff, 0.9)
|
||||
.setInteractive(); // Capture clicks
|
||||
|
||||
this.minimapBg = this.scene.add.graphics();
|
||||
this.minimapGfx = this.scene.add.graphics();
|
||||
|
||||
this.minimapContainer.add(this.minimapBg);
|
||||
this.minimapContainer.add(this.minimapGfx);
|
||||
|
||||
// Position in center
|
||||
this.positionMinimap();
|
||||
|
||||
// Start hidden
|
||||
this.minimapContainer.setVisible(false);
|
||||
}
|
||||
|
||||
initializeLevel(world: World) {
|
||||
@@ -61,14 +73,17 @@ export class DungeonRenderer {
|
||||
|
||||
private positionMinimap() {
|
||||
const cam = this.scene.cameras.main;
|
||||
const minimapWidth = this.world.width * this.minimapScale + this.minimapPadding * 2;
|
||||
const minimapHeight = this.world.height * this.minimapScale + this.minimapPadding * 2;
|
||||
// Center on screen like menu
|
||||
this.minimapContainer.setPosition(cam.width / 2, cam.height / 2);
|
||||
}
|
||||
|
||||
// Position in bottom right corner (accounting for zoom)
|
||||
const x = cam.width / cam.zoom - minimapWidth - 10;
|
||||
const y = cam.height / cam.zoom - minimapHeight - 10;
|
||||
toggleMinimap() {
|
||||
this.minimapVisible = !this.minimapVisible;
|
||||
this.minimapContainer.setVisible(this.minimapVisible);
|
||||
}
|
||||
|
||||
this.minimapContainer.setPosition(x, y);
|
||||
isMinimapVisible(): boolean {
|
||||
return this.minimapVisible;
|
||||
}
|
||||
|
||||
computeFov(playerId: EntityId) {
|
||||
@@ -178,21 +193,24 @@ export class DungeonRenderer {
|
||||
}
|
||||
|
||||
private renderMinimap() {
|
||||
this.minimapBg.clear();
|
||||
this.minimapGfx.clear();
|
||||
|
||||
if (!this.world) return;
|
||||
|
||||
const minimapWidth = this.world.width * this.minimapScale + this.minimapPadding * 2;
|
||||
const minimapHeight = this.world.height * this.minimapScale + this.minimapPadding * 2;
|
||||
// Calculate scale to fit map within panel
|
||||
const padding = 20;
|
||||
const availableWidth = this.minimapPanelWidth - padding * 2;
|
||||
const availableHeight = this.minimapPanelHeight - padding * 2;
|
||||
|
||||
// Background
|
||||
this.minimapBg.fillStyle(0x000000, 0.7);
|
||||
this.minimapBg.fillRect(0, 0, minimapWidth, minimapHeight);
|
||||
const scaleX = availableWidth / this.world.width;
|
||||
const scaleY = availableHeight / this.world.height;
|
||||
const tileSize = Math.floor(Math.min(scaleX, scaleY));
|
||||
|
||||
// Border
|
||||
this.minimapBg.lineStyle(1, 0x666666, 1);
|
||||
this.minimapBg.strokeRect(0, 0, minimapWidth, minimapHeight);
|
||||
// Center the map within the panel
|
||||
const mapPixelWidth = this.world.width * tileSize;
|
||||
const mapPixelHeight = this.world.height * tileSize;
|
||||
const offsetX = -mapPixelWidth / 2;
|
||||
const offsetY = -mapPixelHeight / 2;
|
||||
|
||||
// Draw only seen tiles
|
||||
for (let y = 0; y < this.world.height; y++) {
|
||||
@@ -207,10 +225,10 @@ export class DungeonRenderer {
|
||||
|
||||
this.minimapGfx.fillStyle(color, 1);
|
||||
this.minimapGfx.fillRect(
|
||||
this.minimapPadding + x * this.minimapScale,
|
||||
this.minimapPadding + y * this.minimapScale,
|
||||
this.minimapScale,
|
||||
this.minimapScale
|
||||
offsetX + x * tileSize,
|
||||
offsetY + y * tileSize,
|
||||
tileSize,
|
||||
tileSize
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -222,10 +240,10 @@ export class DungeonRenderer {
|
||||
if (this.seen[exitIdx] === 1) {
|
||||
this.minimapGfx.fillStyle(0xffd166, 1);
|
||||
this.minimapGfx.fillRect(
|
||||
this.minimapPadding + ex * this.minimapScale,
|
||||
this.minimapPadding + ey * this.minimapScale,
|
||||
this.minimapScale,
|
||||
this.minimapScale
|
||||
offsetX + ex * tileSize,
|
||||
offsetY + ey * tileSize,
|
||||
tileSize,
|
||||
tileSize
|
||||
);
|
||||
}
|
||||
|
||||
@@ -234,10 +252,10 @@ export class DungeonRenderer {
|
||||
if (player) {
|
||||
this.minimapGfx.fillStyle(0x66ff66, 1);
|
||||
this.minimapGfx.fillRect(
|
||||
this.minimapPadding + player.pos.x * this.minimapScale,
|
||||
this.minimapPadding + player.pos.y * this.minimapScale,
|
||||
this.minimapScale,
|
||||
this.minimapScale
|
||||
offsetX + player.pos.x * tileSize,
|
||||
offsetY + player.pos.y * tileSize,
|
||||
tileSize,
|
||||
tileSize
|
||||
);
|
||||
}
|
||||
|
||||
@@ -250,10 +268,10 @@ export class DungeonRenderer {
|
||||
|
||||
this.minimapGfx.fillStyle(0xff6666, 1);
|
||||
this.minimapGfx.fillRect(
|
||||
this.minimapPadding + a.pos.x * this.minimapScale,
|
||||
this.minimapPadding + a.pos.y * this.minimapScale,
|
||||
this.minimapScale,
|
||||
this.minimapScale
|
||||
offsetX + a.pos.x * tileSize,
|
||||
offsetY + a.pos.y * tileSize,
|
||||
tileSize,
|
||||
tileSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,18 +59,41 @@ export class GameScene extends Phaser.Scene {
|
||||
|
||||
// Menu Inputs
|
||||
this.input.keyboard?.on("keydown-I", () => {
|
||||
// Close minimap if it's open
|
||||
if (this.dungeonRenderer.isMinimapVisible()) {
|
||||
this.dungeonRenderer.toggleMinimap();
|
||||
}
|
||||
this.events.emit("toggle-menu");
|
||||
// Force update UI in case it opened
|
||||
this.emitUIUpdate();
|
||||
});
|
||||
this.input.keyboard?.on("keydown-ESC", () => {
|
||||
this.events.emit("close-menu");
|
||||
// Also close minimap
|
||||
if (this.dungeonRenderer.isMinimapVisible()) {
|
||||
this.dungeonRenderer.toggleMinimap();
|
||||
}
|
||||
});
|
||||
this.input.keyboard?.on("keydown-M", () => {
|
||||
// Close menu if it's open
|
||||
this.events.emit("close-menu");
|
||||
this.dungeonRenderer.toggleMinimap();
|
||||
});
|
||||
|
||||
// Mouse click -> compute path (only during player turn, and not while menu is open)
|
||||
// Listen for Map button click from UI
|
||||
this.events.on("toggle-minimap", () => {
|
||||
this.dungeonRenderer.toggleMinimap();
|
||||
});
|
||||
|
||||
// Listen for UI update requests
|
||||
this.events.on("request-ui-update", () => {
|
||||
this.emitUIUpdate();
|
||||
});
|
||||
|
||||
// Mouse click -> compute path (only during player turn, and not while menu/minimap is open)
|
||||
this.input.on("pointerdown", (p: Phaser.Input.Pointer) => {
|
||||
if (!this.awaitingPlayer) return;
|
||||
if (this.isMenuOpen) return;
|
||||
if (this.isMenuOpen || this.dungeonRenderer.isMinimapVisible()) return;
|
||||
|
||||
const tx = Math.floor(p.worldX / TILE_SIZE);
|
||||
const ty = Math.floor(p.worldY / TILE_SIZE);
|
||||
@@ -99,7 +122,7 @@ export class GameScene extends Phaser.Scene {
|
||||
|
||||
update() {
|
||||
if (!this.awaitingPlayer) return;
|
||||
if (this.isMenuOpen) return;
|
||||
if (this.isMenuOpen || this.dungeonRenderer.isMinimapVisible()) return;
|
||||
|
||||
// Auto-walk one step per turn
|
||||
if (this.playerPath.length >= 2) {
|
||||
|
||||
@@ -12,6 +12,7 @@ export default class GameUI extends Phaser.Scene {
|
||||
private menuText!: Phaser.GameObjects.Text;
|
||||
private menuBg!: Phaser.GameObjects.Rectangle;
|
||||
private menuButton!: Phaser.GameObjects.Container;
|
||||
private mapButton!: Phaser.GameObjects.Container;
|
||||
|
||||
constructor() {
|
||||
super({ key: "GameUI" });
|
||||
@@ -49,10 +50,10 @@ export default class GameUI extends Phaser.Scene {
|
||||
private createMenu() {
|
||||
const cam = this.cameras.main;
|
||||
|
||||
// Button (top-right)
|
||||
const btnW = 90;
|
||||
const btnH = 28;
|
||||
|
||||
// Menu Button
|
||||
const btnBg = this.add.rectangle(0, 0, btnW, btnH, 0x000000, 0.6).setStrokeStyle(1, 0xffffff, 0.8);
|
||||
const btnLabel = this.add.text(0, 0, "Menu", { fontSize: "14px", color: "#ffffff" }).setOrigin(0.5);
|
||||
|
||||
@@ -63,10 +64,25 @@ export default class GameUI extends Phaser.Scene {
|
||||
this.menuButton.setPosition(cam.width - btnW / 2 - 10, btnH / 2 + 10);
|
||||
};
|
||||
placeButton();
|
||||
this.scale.on("resize", placeButton); // Use scale manager resize
|
||||
this.scale.on("resize", placeButton);
|
||||
|
||||
btnBg.setInteractive({ useHandCursor: true }).on("pointerdown", () => this.toggleMenu());
|
||||
|
||||
// Map Button (left of Menu button)
|
||||
const mapBtnBg = this.add.rectangle(0, 0, btnW, btnH, 0x000000, 0.6).setStrokeStyle(1, 0xffffff, 0.8);
|
||||
const mapBtnLabel = this.add.text(0, 0, "Map", { fontSize: "14px", color: "#ffffff" }).setOrigin(0.5);
|
||||
|
||||
this.mapButton = this.add.container(0, 0, [mapBtnBg, mapBtnLabel]);
|
||||
this.mapButton.setDepth(1000);
|
||||
|
||||
const placeMapButton = () => {
|
||||
this.mapButton.setPosition(cam.width - btnW / 2 - 10 - btnW - 5, btnH / 2 + 10);
|
||||
};
|
||||
placeMapButton();
|
||||
this.scale.on("resize", placeMapButton);
|
||||
|
||||
mapBtnBg.setInteractive({ useHandCursor: true }).on("pointerdown", () => this.toggleMap());
|
||||
|
||||
// Panel (center)
|
||||
const panelW = 340;
|
||||
const panelH = 220;
|
||||
@@ -98,6 +114,11 @@ export default class GameUI extends Phaser.Scene {
|
||||
|
||||
private toggleMenu() {
|
||||
this.setMenuOpen(!this.menuOpen);
|
||||
// Request UI update when menu is opened to populate the text
|
||||
if (this.menuOpen) {
|
||||
const gameScene = this.scene.get("GameScene");
|
||||
gameScene.events.emit("request-ui-update");
|
||||
}
|
||||
}
|
||||
|
||||
private setMenuOpen(open: boolean) {
|
||||
@@ -109,6 +130,13 @@ export default class GameUI extends Phaser.Scene {
|
||||
gameScene.events.emit("menu-toggled", open);
|
||||
}
|
||||
|
||||
private toggleMap() {
|
||||
// Close menu and toggle minimap
|
||||
this.setMenuOpen(false);
|
||||
const gameScene = this.scene.get("GameScene");
|
||||
gameScene.events.emit("toggle-minimap");
|
||||
}
|
||||
|
||||
private updateUI(world: World, playerId: EntityId, levelIndex: number) {
|
||||
this.updateHud(world, playerId, levelIndex);
|
||||
if (this.menuOpen) {
|
||||
|
||||
Reference in New Issue
Block a user