Files
CINC/objects/Unit.js
T

212 lines
5.7 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();
// 目标地点显示
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) {
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);
}
}
}