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.
This commit is contained in:
Brian Fertig 2025-09-03 15:54:27 -06:00
parent b554839537
commit 0dc8fba5db
3 changed files with 63 additions and 4 deletions

View File

@ -4,6 +4,8 @@ import { TowerManager } from '../support/towerManager.js';
export class Level extends Phaser.Scene { export class Level extends Phaser.Scene {
constructor() { constructor() {
super({ key: 'Level' }); super({ key: 'Level' });
this.allowPan = true;
} }
init(data) { init(data) {
@ -81,7 +83,7 @@ export class Level extends Phaser.Scene {
// Add camera panning functionality // Add camera panning functionality
this.input.on('pointerdown', (pointer) => { 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.isPanning = true;
this.panStartX = pointer.x; this.panStartX = pointer.x;
this.panStartY = pointer.y; this.panStartY = pointer.y;

View File

@ -205,6 +205,7 @@ export class InterfaceManager {
openInterface() { openInterface() {
this.interfaceOpen = true; this.interfaceOpen = true;
this.scene.levelScene.allowPan = false;
this.upLeft.setAlpha(0).setRotation(Math.PI); this.upLeft.setAlpha(0).setRotation(Math.PI);
this.upRight.setAlpha(0).setRotation(Math.PI); this.upRight.setAlpha(0).setRotation(Math.PI);
this.interfaceText.setAlpha(0).setText('Click to Close'); this.interfaceText.setAlpha(0).setText('Click to Close');
@ -225,6 +226,7 @@ export class InterfaceManager {
closeInterface() { closeInterface() {
this.interfaceOpen = false; this.interfaceOpen = false;
this.scene.levelScene.allowPan = true;
this.upLeft.setAlpha(0).setRotation(0); this.upLeft.setAlpha(0).setRotation(0);
this.upRight.setAlpha(0).setRotation(0); this.upRight.setAlpha(0).setRotation(0);
this.interfaceText.setAlpha(0).setText('Click to Open'); this.interfaceText.setAlpha(0).setText('Click to Open');

View File

@ -7,16 +7,24 @@ export class TowerManager {
this.scene = scene; this.scene = scene;
this.lastFired = {}; // Track last fire time for each tower this.lastFired = {}; // Track last fire time for each tower
this.following = {}; this.following = {};
this.selectedTower = null;
this.createAnims(); 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) { createTower(type, x, y) {
const posX = this.scene.gridToLocation(x); const posX = this.scene.gridToLocation(x);
const posY = this.scene.gridToLocation(y); const posY = this.scene.gridToLocation(y);
const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7); 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); const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(11);
tower.props = { tower.props = {
'type': type, 'type': type,
'level': 1 'level': 1
@ -29,7 +37,9 @@ export class TowerManager {
this.scene.towers.add(tower); this.scene.towers.add(tower);
tower.setInteractive(); tower.setInteractive();
tower.on('pointerdown', () => { tower.on('pointerdown', () => {
if (!this.selectedTower) {
this.upgradeMenu(tower); this.upgradeMenu(tower);
}
}); });
// Draw range circle // Draw range circle
@ -41,6 +51,25 @@ export class TowerManager {
} }
upgradeMenu(tower) { 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. // TODO: update this asap.
const nextLevel = `level${tower.props.level+1}`; const nextLevel = `level${tower.props.level+1}`;
if (this.scene.UIScene.interfaceManager.gold >= TOWERS_CONFIG[tower.props.type][nextLevel].cost){ 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) { upgradeTower(tower) {
if (tower.props.level === 3) return; if (tower.props.level === 3) return;