From 0dc8fba5db895025749da8034bcfa34e744e3825 Mon Sep 17 00:00:00 2001 From: Brian Fertig Date: Wed, 3 Sep 2025 15:54:27 -0600 Subject: [PATCH] feat: Implement tower selection and upgrade system with pan control - Added allowPan flag to level scene to control camera panning - Implemented interface manager to disable/enable panning when interfaces open/close - Enhanced tower manager with: * Tower selection functionality * Visual range circle and rotating line indicator * Global click handler to close upgrade menu when clicking outside towers * Depth management for tower sprites * Pointer overlap detection for UI interactions This enables proper tower selection, visual feedback during upgrades, and prevents camera panning while interacting with the UI. --- src/levels/level.js | 4 ++- src/support/interfaceManager.js | 2 ++ src/support/towerManager.js | 61 +++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/levels/level.js b/src/levels/level.js index 4fdfcb8..d3f4164 100644 --- a/src/levels/level.js +++ b/src/levels/level.js @@ -4,6 +4,8 @@ import { TowerManager } from '../support/towerManager.js'; export class Level extends Phaser.Scene { constructor() { super({ key: 'Level' }); + + this.allowPan = true; } init(data) { @@ -81,7 +83,7 @@ export class Level extends Phaser.Scene { // Add camera panning functionality this.input.on('pointerdown', (pointer) => { - if (pointer.button === 0) { // Left mouse button + if (pointer.button === 0 && this.allowPan === true) { // Left mouse button this.isPanning = true; this.panStartX = pointer.x; this.panStartY = pointer.y; diff --git a/src/support/interfaceManager.js b/src/support/interfaceManager.js index 0526913..86336fe 100644 --- a/src/support/interfaceManager.js +++ b/src/support/interfaceManager.js @@ -205,6 +205,7 @@ export class InterfaceManager { openInterface() { this.interfaceOpen = true; + this.scene.levelScene.allowPan = false; this.upLeft.setAlpha(0).setRotation(Math.PI); this.upRight.setAlpha(0).setRotation(Math.PI); this.interfaceText.setAlpha(0).setText('Click to Close'); @@ -225,6 +226,7 @@ export class InterfaceManager { closeInterface() { this.interfaceOpen = false; + this.scene.levelScene.allowPan = true; this.upLeft.setAlpha(0).setRotation(0); this.upRight.setAlpha(0).setRotation(0); this.interfaceText.setAlpha(0).setText('Click to Open'); diff --git a/src/support/towerManager.js b/src/support/towerManager.js index 3808acb..8c3e574 100644 --- a/src/support/towerManager.js +++ b/src/support/towerManager.js @@ -7,16 +7,24 @@ export class TowerManager { this.scene = scene; this.lastFired = {}; // Track last fire time for each tower this.following = {}; + this.selectedTower = null; this.createAnims(); + + // Add global click handler to close upgrade menu + this.scene.input.on('pointerdown', (pointer) => { + if (this.selectedTower && !this.isPointerOverTower(pointer)) { + this.closeUpgradeMenu(); + } + }); } createTower(type, x, y) { const posX = this.scene.gridToLocation(x); const posY = this.scene.gridToLocation(y); - const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7); - const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart); + const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7).setDepth(10); + const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(11); tower.props = { 'type': type, 'level': 1 @@ -29,7 +37,9 @@ export class TowerManager { this.scene.towers.add(tower); tower.setInteractive(); tower.on('pointerdown', () => { - this.upgradeMenu(tower); + if (!this.selectedTower) { + this.upgradeMenu(tower); + } }); // Draw range circle @@ -41,6 +51,25 @@ export class TowerManager { } upgradeMenu(tower) { + this.selectedTower = tower; + const camera = this.scene.cameras.main; + const towerLocX = tower.x - camera.scrollX; + const towerLocY = tower.y - camera.scrollY; + this.rangeCircle = this.scene.add.circle(tower.x, tower.y, TOWERS_CONFIG[tower.props.type].level1.range, 0xc009900, 0.2) + .setOrigin(0.5) + .setDepth(5); + // Add a line from center to edge of range circle + this.centerToEdgeLine = this.scene.add.line(tower.x, tower.y, 0, 0, TOWERS_CONFIG[tower.props.type].level1.range, 0, 0x00ff00) + .setOrigin(0) + .setDepth(6); + this.scene.tweens.add({ + targets: this.centerToEdgeLine, + angle: 360, + duration: 8000, + repeat: -1 + }); + console.log('here'); + // TODO: update this asap. const nextLevel = `level${tower.props.level+1}`; if (this.scene.UIScene.interfaceManager.gold >= TOWERS_CONFIG[tower.props.type][nextLevel].cost){ @@ -48,6 +77,32 @@ export class TowerManager { } } + isPointerOverTower(pointer) { + // Check if pointer is over any tower + let isOverTower = false; + this.scene.towers.children.iterate((tower) => { + if (tower.getBounds().contains(pointer.x, pointer.y)) { + isOverTower = true; + return false; // Break iteration + } + }); + return isOverTower; + } + + closeUpgradeMenu() { + if (this.rangeCircle) { + this.rangeCircle.destroy(); + this.rangeCircle = null; + } + + if (this.centerToEdgeLine) { + this.centerToEdgeLine.destroy(); + this.centerToEdgeLine = null; + } + + this.selectedTower = null; + } + upgradeTower(tower) { if (tower.props.level === 3) return;