Files

280 lines
8.5 KiB
JavaScript

// ui/MiniMap.js
import { selectedUnits, setCameraLocked, cameraLocked } from '../systems/ControlMode.js';
export class MiniMap {
constructor(scene, options = {}) {
this.scene = scene;
this.worldSize = options.worldSize || 2000;
this.mapSize = options.mapSize || 200;
this.x = options.x || 10;
this.y = options.y || 10;
// 计算缩放比例(将世界坐标转换为小地图坐标)
this.scale = this.mapSize / (this.worldSize * 2);
// 创建小地图容器
this.container = scene.add.container(this.x, this.y);
this.container.setScrollFactor(0, 0); // 小地图固定在屏幕上
// 创建小地图背景
this.background = scene.add.rectangle(0, 0, this.mapSize, this.mapSize, 0x000000, 0.5);
this.background.setOrigin(0, 0);
this.background.setStrokeStyle(1, 0xffffff, 0.8);
this.container.add(this.background);
// 创建视口指示器
this.viewport = scene.add.rectangle(0, 0, 0, 0, 0xffffff, 0.3);
this.viewport.setOrigin(0, 0);
this.viewport.setStrokeStyle(1, 0xffffff, 1);
this.container.add(this.viewport);
// 创建单位标记数组
this.unitMarkers = [];
// 锁定按钮相关属性
this.lockButton = null;
this.lockButtonText = null;
this.lockHint = null;
// 设置交互
this.setupInteractions();
// 更新小地图(初始调用)
this.update();
}
setupInteractions() {
// 启用容器交互
this.container.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.mapSize, this.mapSize), Phaser.Geom.Rectangle.Contains);
// 点击小地图移动相机
this.container.on('pointerdown', (pointer) => {
this.handleMapClick(pointer);
});
// 拖动小地图移动相机
this.container.on('pointermove', (pointer) => {
if (pointer.isDown) {
this.handleMapDrag(pointer);
}
});
}
handleMapClick(pointer) {
// 将小地图坐标转换为世界坐标
const worldX = (pointer.x - this.x) / this.scale - this.worldSize;
const worldY = (pointer.y - this.y) / this.scale - this.worldSize;
// 移动相机到点击位置
this.scene.cameras.main.centerOn(worldX, worldY);
}
handleMapDrag(pointer) {
// 将小地图坐标转换为世界坐标
const worldX = (pointer.x - this.x) / this.scale - this.worldSize;
const worldY = (pointer.y - this.y) / this.scale - this.worldSize;
// 移动相机到拖动位置
this.scene.cameras.main.centerOn(worldX, worldY);
}
createLockButton() {
// 移除旧的按钮(如果存在)
this.destroyLockButton();
// 创建锁定按钮背景,直接添加到场景中
const buttonX = this.x; // 按钮x坐标与小地图对齐
const buttonY = this.y + this.mapSize + 5; // 按钮位于小地图下方
this.lockButton = this.scene.add.rectangle(buttonX, buttonY, 100, 25, 0x444444, 0.8);
this.lockButton.setOrigin(0, 0);
this.lockButton.setStrokeStyle(1, 0xffffff, 0.8);
this.lockButton.setInteractive(); // 使用默认的点击区域
this.lockButton.setScrollFactor(0, 0); // 固定在屏幕上
// 创建锁定按钮文本,直接添加到场景中
this.lockButtonText = this.scene.add.text(buttonX + 5, buttonY + 6, '锁定角色', {
fontSize: '12px',
fill: '#ffffff',
fontFamily: 'Arial'
});
this.lockButtonText.setOrigin(0, 0);
this.lockButtonText.setScrollFactor(0, 0); // 固定在屏幕上
// 添加按钮点击事件
this.lockButton.on('pointerdown', () => {
console.log('锁定按钮被点击'); // 添加调试日志
this.toggleLock();
});
// 添加悬停效果
this.lockButton.on('pointerover', () => {
this.lockButton.setFillStyle(cameraLocked ? 0x22ff22 : 0x666666, 0.8);
});
this.lockButton.on('pointerout', () => {
this.lockButton.setFillStyle(cameraLocked ? 0x00ff00 : 0x444444, 0.8);
});
// 初始隐藏按钮
this.lockButton.setVisible(false);
this.lockButtonText.setVisible(false);
}
// 销毁锁定按钮
destroyLockButton() {
if (this.lockButton) {
this.lockButton.destroy();
this.lockButton = null;
}
if (this.lockButtonText) {
this.lockButtonText.destroy();
this.lockButtonText = null;
}
}
toggleLock() {
// 切换锁定状态
const newLockedState = !cameraLocked;
// 更新全局锁定状态
setCameraLocked(newLockedState);
this.updateLockButton();
// 立即将相机中心绑定到选中角色
if (newLockedState && selectedUnits.length === 1) {
const selectedUnit = selectedUnits[0];
this.scene.cameras.main.centerOn(selectedUnit.x, selectedUnit.y);
// 添加锁定提示
this.showLockHint(newLockedState);
} else {
// 移除锁定提示
this.hideLockHint();
}
}
updateLockButton() {
if (selectedUnits.length === 1) {
// 如果按钮不存在,创建按钮
if (!this.lockButton) {
this.createLockButton();
}
// 更新按钮状态
this.lockButton.setVisible(true);
this.lockButtonText.setVisible(true);
this.lockButtonText.setText(cameraLocked ? '取消锁定' : '锁定角色');
this.lockButton.setFillStyle(cameraLocked ? 0x00ff00 : 0x444444, 0.8);
} else {
// 销毁按钮
this.destroyLockButton();
// 移除锁定提示
this.hideLockHint();
}
}
// 添加锁定提示
showLockHint(locked) {
// 如果已经有提示,先移除
this.hideLockHint();
// 创建提示文本
this.lockHint = this.scene.add.text(this.scene.sys.game.config.width / 2, 50,
locked ? '已锁定相机到选中角色' : '已取消相机锁定', {
fontSize: '16px',
fill: '#ffffff',
fontFamily: 'Arial',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
padding: {
x: 10,
y: 5
}
});
this.lockHint.setOrigin(0.5, 0.5);
this.lockHint.setScrollFactor(0, 0); // 固定在屏幕上
// 3秒后自动隐藏
this.scene.time.delayedCall(3000, () => {
this.hideLockHint();
}, [], this);
}
// 移除锁定提示
hideLockHint() {
if (this.lockHint) {
this.lockHint.destroy();
this.lockHint = null;
}
}
update() {
// 更新锁定按钮状态
this.updateLockButton();
// 如果锁定状态且只有一个选中角色,将相机中心绑定到该角色
if (cameraLocked && selectedUnits.length === 1) {
const selectedUnit = selectedUnits[0];
this.scene.cameras.main.centerOn(selectedUnit.x, selectedUnit.y);
}
// 更新视口指示器位置和大小
this.updateViewport();
// 更新单位标记
this.updateUnitMarkers();
}
updateViewport() {
const camera = this.scene.cameras.main;
// 计算相机视口在世界中的位置和大小
const viewportLeft = camera.scrollX;
const viewportTop = camera.scrollY;
const viewportWidth = camera.width * camera.zoom;
const viewportHeight = camera.height * camera.zoom;
// 将世界坐标转换为小地图坐标
const mapLeft = (viewportLeft + this.worldSize) * this.scale;
const mapTop = (viewportTop + this.worldSize) * this.scale;
const mapWidth = viewportWidth * this.scale;
const mapHeight = viewportHeight * this.scale;
// 更新视口指示器
this.viewport.setPosition(mapLeft, mapTop);
this.viewport.setSize(mapWidth, mapHeight);
}
updateUnitMarkers() {
// 清除现有标记
this.unitMarkers.forEach(marker => {
marker.destroy();
});
this.unitMarkers = [];
// 获取所有单位
if (this.scene.unitGroup) {
const units = this.scene.unitGroup.getChildren();
units.forEach(unit => {
// 将单位世界坐标转换为小地图坐标
const mapX = (unit.x + this.worldSize) * this.scale;
const mapY = (unit.y + this.worldSize) * this.scale;
// 检查单位是否被选中
const isSelected = selectedUnits.includes(unit);
// 根据选中状态设置不同的颜色和大小
const color = isSelected ? 0x00ff00 : 0xff0000;
const size = isSelected ? 3 : 2;
// 创建单位标记
const marker = this.scene.add.circle(mapX, mapY, size, color, 1);
marker.setOrigin(0.5, 0.5);
// 将标记添加到容器和数组中
this.container.add(marker);
this.unitMarkers.push(marker);
});
}
}
}