Files
CINC/objects/Unit.js
T
2025-12-31 00:30:38 +08:00

124 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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();
}
/**
* 创建选中状态指示器
*/
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);
}
/**
* 设置单位选中状态
* @param {boolean} isSelected
*/
setSelected(isSelected) {
this.isSelected = isSelected;
if (this.selectedIndicator) {
this.selectedIndicator.setVisible(isSelected);
}
}
/**
* 设置移动目标点
* @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 };
}
/**
* 清除目标并停止移动
*/
clearTarget() {
this.target = null;
this.setVelocity(0, 0);
}
/**
* 相对移动控制(用于键盘/虚拟摇杆)
* @param {number} x - 水平方向 (-1 到 1)
* @param {number} y - 垂直方向 (-1 到 1)
*/
moveRelative(x, y) {
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);
}
}
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);
}
}
}