feat(control) 小地图

This commit is contained in:
chicrobot committed 2025-12-31 00:30:38 +08:00
1 parent f86e5f3a79
commit e2bc630d6d
8 files changed
+339 -24

No files matched your search

+112 -4
View File
@@ -1,16 +1,124 @@
// 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();
}
moveTo(targetX, targetY) {
this.scene.physics.moveToObject(this, {x: targetX, y: targetY}, 200);
/**
* 创建选中状态指示器
*/
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);
}
moveRelative(dirX, dirY, speed = 100) {
this.setVelocity(dirX * speed, dirY * speed);
/**
* 设置单位选中状态
* @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);
}
}
}