// objects/Unit.js export default class Unit extends Phaser.Physics.Arcade.Sprite { constructor(scene, x, y, texture) { super(scene, x, y, texture); scene.add.existing(this); scene.physics.add.existing(this); // 启用圆形碰撞体(更自然) this.setCircle(14); // 启用与世界边界的碰撞(必须配合 physics.world.setBounds) this.setCollideWorldBounds(true); // 移动目标(x, y) this.target = null; // 选中状态 this.isSelected = false; this.selectedIndicator = null; this.createSelectedIndicator(); // 目标地点显示 this.targetIndicator = null; this.pathGraphics = null; } /** * 创建选中状态指示器 */ createSelectedIndicator() { // 创建一个外圈指示器,默认隐藏 this.selectedIndicator = this.scene.add.circle(this.x, this.y, this.width * 0.7, 0x00ff00, 0.0); this.selectedIndicator.setStrokeStyle(2, 0x00ff00, 1); this.selectedIndicator.setVisible(false); // 确保指示器与单位一起移动 this.selectedIndicator.setOrigin(0.5, 0.5); // 移除固定位置设置,让指示器随单位和相机一起移动 this.selectedIndicator.setScrollFactor(1, 1); } /** * 创建目标地点指示器 */ createTargetIndicator() { if (!this.targetIndicator) { // 创建目标地点指示器(红色圆点) this.targetIndicator = this.scene.add.circle(0, 0, 8, 0xff0000, 1); this.targetIndicator.setOrigin(0.5, 0.5); this.targetIndicator.setScrollFactor(1, 1); this.targetIndicator.setVisible(false); } } /** * 创建寻路路径图形 */ createPathGraphics() { if (!this.pathGraphics) { // 创建图形对象用于绘制路径 this.pathGraphics = this.scene.add.graphics(); this.pathGraphics.setScrollFactor(1, 1); } } /** * 设置单位选中状态 * @param {boolean} isSelected */ setSelected(isSelected) { this.isSelected = isSelected; if (this.selectedIndicator) { this.selectedIndicator.setVisible(isSelected); } // 只有选中时才显示目标地点和路径 this.updateTargetVisibility(); } /** * 更新目标地点和路径的可见性 */ updateTargetVisibility() { if (this.targetIndicator) { this.targetIndicator.setVisible(this.isSelected && this.target !== null); } if (this.pathGraphics) { this.pathGraphics.clear(); // 只有选中且有目标时才绘制路径 if (this.isSelected && this.target !== null) { this.drawPath(); } } } /** * 绘制寻路路径 */ drawPath() { if (!this.pathGraphics || !this.target) { return; } this.pathGraphics.clear(); this.pathGraphics.lineStyle(2, 0x00ff00, 0.8); this.pathGraphics.beginPath(); this.pathGraphics.moveTo(this.x, this.y); this.pathGraphics.lineTo(this.target.x, this.target.y); this.pathGraphics.stroke(); } /** * 设置移动目标点 * @param {number} x * @param {number} y */ setTarget(x, y) { // 获取世界边界 const worldBounds = this.scene.physics.world.bounds; // 限制目标点在世界边界内 const clampedX = Math.max(worldBounds.x, Math.min(worldBounds.right, x)); const clampedY = Math.max(worldBounds.y, Math.min(worldBounds.bottom, y)); this.target = { x: clampedX, y: clampedY }; // 创建目标指示器和路径图形(如果不存在) this.createTargetIndicator(); this.createPathGraphics(); // 更新目标指示器位置 if (this.targetIndicator) { this.targetIndicator.setPosition(this.target.x, this.target.y); } // 更新目标可见性和路径绘制 this.updateTargetVisibility(); } /** * 清除目标并停止移动 */ clearTarget() { this.target = null; this.setVelocity(0, 0); // 隐藏目标指示器和清除路径 if (this.targetIndicator) { this.targetIndicator.setVisible(false); } if (this.pathGraphics) { this.pathGraphics.clear(); } } /** * 相对移动控制(用于键盘/虚拟摇杆) * @param {number} x - 水平方向 (-1 到 1) * @param {number} y - 垂直方向 (-1 到 1) */ moveRelative(x, y) { // 检查是否可以移动 if (this.canMove === false) { this.setVelocity(0, 0); return; } const speed = 150; // 单位:像素/秒 // 归一化方向向量 const magnitude = Math.sqrt(x * x + y * y); if (magnitude > 0) { // 有按键输入时,清除目标点,切换到直接控制模式 this.clearTarget(); const normalizedX = x / magnitude; const normalizedY = y / magnitude; this.setVelocity(normalizedX * speed, normalizedY * speed); } else { // 没有按键输入时,保持当前的目标点(如果有的话) this.setVelocity(0, 0); } } /** * 每帧更新移动逻辑(需在 GameScene.update 中调用) */ update() { // 更新选中指示器位置 if (this.selectedIndicator && this.isSelected) { this.selectedIndicator.setPosition(this.x, this.y); } // 更新路径绘制(单位位置变化时) if (this.isSelected && this.target !== null) { this.drawPath(); } } updateMovement() { if (!this.target) { return; } const dx = this.target.x - this.x; const dy = this.target.y - this.y; const distance = Math.sqrt(dx * dx + dy * dy); // 到达阈值:5 像素内视为“到达” if (distance < 5) { // 精确对齐到目标点(可选) this.setPosition(this.target.x, this.target.y); this.clearTarget(); } else { const speed = 150; // 单位:像素/秒 const angle = Math.atan2(dy, dx); this.setVelocity(Math.cos(angle) * speed, Math.sin(angle) * speed); } } }