mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-29 19:51:29 +08:00
docs(all) 添加注释
This commit is contained in:
1 parent
3863cfe1f6
commit
3c9b15eef7
13 files changed
+317
-74
No files matched your search
Generated
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.13" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/CINC.iml" filepath="$PROJECT_DIR$/.idea/CINC.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -1,20 +1,36 @@
|
|||||||
|
// 导出游戏配置对象,供main.js文件使用
|
||||||
export default {
|
export default {
|
||||||
|
// 游戏渲染类型:Phaser.AUTO表示自动选择最佳渲染方式(WebGL或Canvas)
|
||||||
type: Phaser.AUTO,
|
type: Phaser.AUTO,
|
||||||
|
// 游戏窗口宽度:设置为浏览器窗口的宽度
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
|
// 游戏窗口高度:设置为浏览器窗口的高度
|
||||||
height: window.innerHeight,
|
height: window.innerHeight,
|
||||||
|
// 游戏背景颜色:使用十六进制颜色值设置为天蓝色
|
||||||
backgroundColor: '#87ceeb',
|
backgroundColor: '#87ceeb',
|
||||||
|
// 物理引擎配置
|
||||||
physics: {
|
physics: {
|
||||||
|
// 默认使用的物理引擎:'arcade'是Phaser内置的轻量级物理引擎
|
||||||
default: 'arcade',
|
default: 'arcade',
|
||||||
|
// arcade物理引擎的具体配置
|
||||||
arcade: {
|
arcade: {
|
||||||
|
// 重力设置:y轴方向重力为0(适合太空或顶部视图游戏)
|
||||||
gravity: { y: 0 },
|
gravity: { y: 0 },
|
||||||
|
// 调试模式:false表示关闭物理引擎调试信息显示
|
||||||
debug: false
|
debug: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 游戏缩放配置
|
||||||
scale: {
|
scale: {
|
||||||
|
// 缩放模式:Phaser.Scale.RESIZE表示游戏会随着浏览器窗口大小变化而自动调整
|
||||||
mode: Phaser.Scale.RESIZE,
|
mode: Phaser.Scale.RESIZE,
|
||||||
|
// 自动居中:Phaser.Scale.NO_CENTER表示不自动居中游戏窗口
|
||||||
autoCenter: Phaser.Scale.NO_CENTER,
|
autoCenter: Phaser.Scale.NO_CENTER,
|
||||||
|
// 扩展父容器:true表示游戏会扩展到父容器的大小
|
||||||
expandParent: true,
|
expandParent: true,
|
||||||
|
// 缩放后的宽度:设置为浏览器窗口宽度
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
|
// 缩放后的高度:设置为浏览器窗口高度
|
||||||
height: window.innerHeight
|
height: window.innerHeight
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,9 +1,19 @@
|
|||||||
|
// 导入游戏的基础配置文件,该文件包含游戏的宽度、高度、渲染模式等基本设置
|
||||||
import gameConfig from './config/gameConfig.js';
|
import gameConfig from './config/gameConfig.js';
|
||||||
|
|
||||||
|
// 导入游戏场景类,游戏的主要逻辑和玩法都在这个场景中实现
|
||||||
import GameScene from './scenes/GameScene.js';
|
import GameScene from './scenes/GameScene.js';
|
||||||
|
|
||||||
|
// 创建游戏的最终配置对象
|
||||||
const config = {
|
const config = {
|
||||||
|
// 使用扩展运算符(...)将gameConfig中的所有配置项复制到当前对象中
|
||||||
|
// 这相当于把gameConfig的内容合并到这个新的config对象里
|
||||||
...gameConfig,
|
...gameConfig,
|
||||||
|
// 指定游戏使用的场景列表,这里只使用了一个GameScene场景
|
||||||
|
// 游戏可以有多个场景,比如开始菜单、游戏主界面、结束界面等
|
||||||
scene: [GameScene]
|
scene: [GameScene]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 创建一个新的Phaser游戏实例,并将配置对象传入
|
||||||
|
// 同时将游戏实例赋值给window.game,这样在浏览器的开发者工具中可以直接访问游戏实例
|
||||||
window.game = new Phaser.Game(config);
|
window.game = new Phaser.Game(config);
|
||||||
+69
-24
@@ -1,83 +1,126 @@
|
|||||||
// scenes/GameScene.js
|
// 游戏场景文件:这是游戏的主要场景,包含了游戏的核心逻辑和玩法实现
|
||||||
|
|
||||||
|
// 导入单位类:用于创建游戏中的角色/单位
|
||||||
import Unit from '../objects/Unit.js';
|
import Unit from '../objects/Unit.js';
|
||||||
|
|
||||||
|
// 导入输入系统:处理玩家的键盘和鼠标输入
|
||||||
import { InputSystem } from '../systems/InputSystem.js';
|
import { InputSystem } from '../systems/InputSystem.js';
|
||||||
|
|
||||||
|
// 导入选择系统:处理单位的选择逻辑
|
||||||
import { SelectionSystem } from '../systems/SelectionSystem.js';
|
import { SelectionSystem } from '../systems/SelectionSystem.js';
|
||||||
|
|
||||||
|
// 导入命令系统:处理玩家对单位的命令(如移动、攻击等)
|
||||||
import { CommandSystem } from '../systems/CommandSystem.js';
|
import { CommandSystem } from '../systems/CommandSystem.js';
|
||||||
|
|
||||||
|
// 导入虚拟摇杆:用于移动设备上的操作控制
|
||||||
import { VirtualJoystick } from '../ui/VirtualJoystick.js';
|
import { VirtualJoystick } from '../ui/VirtualJoystick.js';
|
||||||
|
|
||||||
|
// 导入小地图:显示游戏世界的缩略图
|
||||||
import { MiniMap } from '../ui/MiniMap.js';
|
import { MiniMap } from '../ui/MiniMap.js';
|
||||||
|
|
||||||
|
// 定义GameScene类,继承自Phaser.Scene(Phaser框架的场景类)
|
||||||
export default class GameScene extends Phaser.Scene {
|
export default class GameScene extends Phaser.Scene {
|
||||||
|
// create方法:当场景创建时自动调用,用于初始化游戏元素
|
||||||
create() {
|
create() {
|
||||||
// === 0. 添加窗口大小变化监听 ===
|
// === 0. 添加窗口大小变化监听 ===
|
||||||
|
// 监听浏览器窗口大小变化事件,当窗口大小改变时调用resizeGame方法
|
||||||
window.addEventListener('resize', this.resizeGame.bind(this));
|
window.addEventListener('resize', this.resizeGame.bind(this));
|
||||||
|
|
||||||
// === 1. 创建玩家纹理(红圈)===
|
// === 1. 创建玩家纹理===
|
||||||
|
// 检查是否已经存在名为'player'的纹理,如果不存在则创建
|
||||||
if (!this.textures.exists('player')) {
|
if (!this.textures.exists('player')) {
|
||||||
|
// 创建一个32x32像素的HTML5 Canvas元素
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 32;
|
canvas.width = 32; // 设置Canvas宽度
|
||||||
canvas.height = 32;
|
canvas.height = 32; // 设置Canvas高度
|
||||||
|
|
||||||
|
// 获取Canvas的2D绘图上下文
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
ctx.fillStyle = '#ff0000';
|
ctx.fillStyle = '#000000ff'; // 设置填充颜色为完全不透明的黑色
|
||||||
ctx.beginPath();
|
ctx.beginPath(); // 开始绘制路径
|
||||||
|
// 绘制一个圆形:圆心(16,16),半径14,从0到2π(完整圆形)
|
||||||
ctx.arc(16, 16, 14, 0, Math.PI * 2);
|
ctx.arc(16, 16, 14, 0, Math.PI * 2);
|
||||||
ctx.fill();
|
ctx.fill(); // 填充圆形
|
||||||
|
|
||||||
|
// 将创建的Canvas添加到Phaser的纹理管理器中,命名为'player'
|
||||||
this.textures.addCanvas('player', canvas);
|
this.textures.addCanvas('player', canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 2. 扩大物理世界和相机边界(关键!)===
|
// === 2. 物理世界和相机边界===
|
||||||
|
// 定义游戏世界的大小
|
||||||
const worldSize = 2000;
|
const worldSize = 2000;
|
||||||
|
|
||||||
|
// 设置物理世界的边界:从(-worldSize,-worldSize)到(worldSize*2, worldSize*2)
|
||||||
|
// 这样游戏世界的中心就是(0,0),范围是从-2000到2000,总共4000x4000大小
|
||||||
this.physics.world.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
this.physics.world.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
||||||
|
|
||||||
|
// 设置相机的边界,与物理世界边界相同
|
||||||
this.cameras.main.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
this.cameras.main.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
||||||
|
|
||||||
// 设置相机起始位置在地图中心
|
// 设置相机起始位置在地图中心
|
||||||
// 使用centerOn方法将相机中心定位在地图坐标(0, 0)
|
// 使用centerOn方法将相机中心定位在地图坐标(0, 0)
|
||||||
this.cameras.main.centerOn(0, 0); // 地图中心坐标是(0, 0)
|
this.cameras.main.centerOn(0, 0); // 地图中心坐标是(0, 0)
|
||||||
|
|
||||||
// === 3. 创建单位组 ===
|
// === 3. 初始化系统 ===
|
||||||
|
// 创建输入系统实例
|
||||||
|
this.inputSystem = new InputSystem(this);
|
||||||
|
// 创建选择系统实例
|
||||||
|
this.selectionSystem = new SelectionSystem(this);
|
||||||
|
// 创建命令系统实例
|
||||||
|
this.commandSystem = new CommandSystem(this);
|
||||||
|
// 创建虚拟摇杆实例
|
||||||
|
this.virtualJoystick = new VirtualJoystick(this);
|
||||||
|
|
||||||
|
// === 4. 创建单位组 ===
|
||||||
|
// 创建一个单位组,用于管理游戏中的所有单位
|
||||||
this.unitGroup = this.add.group();
|
this.unitGroup = this.add.group();
|
||||||
|
|
||||||
|
// 创建5个玩家单位
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
const worldSizePersent = worldSize/100
|
// 计算单位的初始位置
|
||||||
|
const worldSizePersent = worldSize/100; // 世界大小的1%
|
||||||
|
// 每个单位的x坐标递增2%世界大小,y坐标固定为2%世界大小
|
||||||
const unit = new Unit(this, worldSizePersent + 2*i * worldSizePersent, 2 * worldSizePersent, 'player');
|
const unit = new Unit(this, worldSizePersent + 2*i * worldSizePersent, 2 * worldSizePersent, 'player');
|
||||||
|
// 将创建的单位添加到单位组中
|
||||||
this.unitGroup.add(unit);
|
this.unitGroup.add(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 4. 初始化系统 ===
|
|
||||||
this.inputSystem = new InputSystem(this);
|
|
||||||
this.selectionSystem = new SelectionSystem(this);
|
|
||||||
this.commandSystem = new CommandSystem(this);
|
|
||||||
this.virtualJoystick = new VirtualJoystick(this);
|
|
||||||
|
|
||||||
// === 5. 添加角色之间的碰撞检测 ===
|
// === 5. 添加角色之间的碰撞检测 ===
|
||||||
|
// 为单位组添加碰撞检测,使得单位之间可以相互碰撞
|
||||||
this.physics.add.collider(this.unitGroup, this.unitGroup);
|
this.physics.add.collider(this.unitGroup, this.unitGroup);
|
||||||
|
|
||||||
// === 6. 创建小地图 ===
|
// === 6. 创建小地图 ===
|
||||||
|
// 创建小地图实例,设置其位置和大小
|
||||||
this.miniMap = new MiniMap(this, {
|
this.miniMap = new MiniMap(this, {
|
||||||
worldSize: worldSize,
|
worldSize: worldSize, // 游戏世界大小
|
||||||
mapSize: 200,
|
mapSize: 200, // 小地图显示大小
|
||||||
x: 10,
|
x: this.sys.game.config.width - mapSize - 10, // 小地图在屏幕上的x坐标
|
||||||
y: 10
|
y: 10 // 小地图在屏幕上的y坐标
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update方法:每帧自动调用(约60次/秒),用于更新游戏状态
|
||||||
update() {
|
update() {
|
||||||
// 更新输入(键盘、鼠标)
|
// 更新输入系统,处理玩家的键盘和鼠标输入
|
||||||
this.inputSystem.update();
|
this.inputSystem.update();
|
||||||
|
|
||||||
// 更新所有单位的移动逻辑和选中状态(关键!)
|
// 更新所有单位的移动逻辑和选中状态
|
||||||
|
// 获取单位组中的所有子元素(即所有单位)
|
||||||
this.unitGroup.getChildren().forEach(unit => {
|
this.unitGroup.getChildren().forEach(unit => {
|
||||||
|
// 如果单位有自己的update方法,则调用它
|
||||||
if (unit.update) {
|
if (unit.update) {
|
||||||
unit.update();
|
unit.update();
|
||||||
}
|
}
|
||||||
|
// 调用单位的updateMovement方法,更新单位的移动状态
|
||||||
unit.updateMovement();
|
unit.updateMovement();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新小地图
|
// 更新小地图显示
|
||||||
if (this.miniMap) {
|
if (this.miniMap) {
|
||||||
this.miniMap.update();
|
this.miniMap.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新虚拟摇杆
|
// 更新虚拟摇杆状态
|
||||||
if (this.virtualJoystick) {
|
if (this.virtualJoystick) {
|
||||||
this.virtualJoystick.update();
|
this.virtualJoystick.update();
|
||||||
}
|
}
|
||||||
@@ -85,8 +128,10 @@ export default class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 窗口大小变化时的处理函数
|
* 窗口大小变化时的处理函数
|
||||||
|
* 当浏览器窗口大小改变时,调整游戏画布的大小以适应新窗口
|
||||||
*/
|
*/
|
||||||
resizeGame() {
|
resizeGame() {
|
||||||
|
// 调用Phaser的scale.resize方法,将游戏画布大小调整为当前窗口大小
|
||||||
this.scale.resize(window.innerWidth, window.innerHeight);
|
this.scale.resize(window.innerWidth, window.innerHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,53 @@
|
|||||||
// systems/CommandSystem.js
|
// 命令系统:处理玩家对游戏单位的各种命令(如移动、选择等)
|
||||||
|
|
||||||
|
// 从ControlMode.js导入当前激活的单位和选中的单位列表
|
||||||
import { activeUnit, selectedUnits } from './ControlMode.js';
|
import { activeUnit, selectedUnits } from './ControlMode.js';
|
||||||
|
|
||||||
|
// 导出CommandSystem类,用于创建命令系统实例
|
||||||
export class CommandSystem {
|
export class CommandSystem {
|
||||||
|
// 构造函数:初始化命令系统
|
||||||
constructor(scene) {
|
constructor(scene) {
|
||||||
|
// 保存场景引用,用于访问游戏世界和发送事件
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
|
||||||
|
// 监听场景中的移动相关事件
|
||||||
|
// 当'move-relative'事件触发时,调用onMoveRelative方法
|
||||||
scene.events.on('move-relative', this.onMoveRelative, this);
|
scene.events.on('move-relative', this.onMoveRelative, this);
|
||||||
|
// 当'move-to-point'事件触发时,调用onMoveToPoint方法
|
||||||
scene.events.on('move-to-point', this.onMoveToPoint, this);
|
scene.events.on('move-to-point', this.onMoveToPoint, this);
|
||||||
|
// 当'select-unit'事件触发时,调用onSelectUnit方法
|
||||||
scene.events.on('select-unit', this.onSelectUnit, this);
|
scene.events.on('select-unit', this.onSelectUnit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理相对移动命令:根据方向向量移动单位
|
||||||
onMoveRelative(dir) {
|
onMoveRelative(dir) {
|
||||||
|
// 确定移动目标单位:优先使用选中的单位列表,如果没有选中单位则使用当前激活的单位
|
||||||
const targets = selectedUnits.length > 0 ? selectedUnits : (activeUnit ? [activeUnit] : []);
|
const targets = selectedUnits.length > 0 ? selectedUnits : (activeUnit ? [activeUnit] : []);
|
||||||
|
|
||||||
|
// 遍历所有目标单位,调用它们的moveRelative方法进行相对移动
|
||||||
targets.forEach(unit => {
|
targets.forEach(unit => {
|
||||||
unit.moveRelative(dir.x, dir.y);
|
unit.moveRelative(dir.x, dir.y);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理移动到指定点的命令
|
||||||
onMoveToPoint(x, y) {
|
onMoveToPoint(x, y) {
|
||||||
|
// 确定移动目标单位:优先使用选中的单位列表,如果没有选中单位则使用当前激活的单位
|
||||||
const targets = selectedUnits.length > 0 ? selectedUnits : (activeUnit ? [activeUnit] : []);
|
const targets = selectedUnits.length > 0 ? selectedUnits : (activeUnit ? [activeUnit] : []);
|
||||||
|
|
||||||
|
// 遍历所有目标单位,调用它们的setTarget方法设置移动目标点
|
||||||
targets.forEach(unit => {
|
targets.forEach(unit => {
|
||||||
unit.setTarget(x, y); // ← 使用新接口
|
unit.setTarget(x, y); // ← 使用单位的新接口方法
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理选择单位的命令
|
||||||
onSelectUnit(unit) {
|
onSelectUnit(unit) {
|
||||||
// 切换单位
|
// 动态导入ControlMode.js模块,确保能够访问最新的模块内容
|
||||||
import('./ControlMode.js').then(mod => {
|
import('./ControlMode.js').then(mod => {
|
||||||
|
// 调用ControlMode模块的setActiveUnit方法设置当前激活的单位
|
||||||
mod.setActiveUnit(unit);
|
mod.setActiveUnit(unit);
|
||||||
|
// 触发'unit-activated'事件,通知其他系统当前单位已激活
|
||||||
this.scene.events.emit('unit-activated', unit);
|
this.scene.events.emit('unit-activated', unit);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-4
@@ -1,24 +1,44 @@
|
|||||||
|
// 游戏控制模式常量定义
|
||||||
|
// 这些常量用于指定游戏当前使用的控制方式
|
||||||
export const CONTROL_MODE = {
|
export const CONTROL_MODE = {
|
||||||
SINGLE: 'single',
|
SINGLE: 'single', // 单单位控制模式:只控制当前激活的单个单位
|
||||||
GROUP: 'group',
|
GROUP: 'group', // 组控制模式:同时控制多个选中的单位
|
||||||
JOYSTICK: 'joystick'
|
JOYSTICK: 'joystick' // 摇杆控制模式:使用虚拟摇杆控制单位
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 当前激活的单位变量
|
||||||
|
// 用于存储当前玩家正在直接控制的单个单位
|
||||||
|
// 初始值为null,表示没有激活的单位
|
||||||
export let activeUnit = null;
|
export let activeUnit = null;
|
||||||
|
|
||||||
|
// 选中的单位列表
|
||||||
|
// 用于存储玩家当前选中的所有单位
|
||||||
|
// 初始值为空数组,表示没有选中任何单位
|
||||||
export let selectedUnits = [];
|
export let selectedUnits = [];
|
||||||
|
|
||||||
|
// 设置当前激活单位的函数
|
||||||
|
// @param {Object} unit - 要设置为激活状态的单位对象
|
||||||
export function setActiveUnit(unit) {
|
export function setActiveUnit(unit) {
|
||||||
|
// 将传入的单位设置为当前激活单位
|
||||||
activeUnit = unit;
|
activeUnit = unit;
|
||||||
// 不再重置selectedUnits数组,这样可以同时选中多个单位
|
// 注意:这里不再重置selectedUnits数组,这样可以同时选中多个单位
|
||||||
|
// 而只激活其中一个作为当前操作的单位
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将单位添加到选择列表的函数
|
||||||
|
// @param {Object} unit - 要添加到选择列表的单位对象
|
||||||
export function addToSelection(unit) {
|
export function addToSelection(unit) {
|
||||||
|
// 检查单位是否已经在选择列表中,如果不在则添加
|
||||||
if (!selectedUnits.includes(unit)) {
|
if (!selectedUnits.includes(unit)) {
|
||||||
|
// 将单位添加到选择列表的末尾
|
||||||
selectedUnits.push(unit);
|
selectedUnits.push(unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清除选择列表的函数
|
||||||
export function clearSelection() {
|
export function clearSelection() {
|
||||||
|
// 将当前激活单位设置为null(取消激活)
|
||||||
activeUnit = null;
|
activeUnit = null;
|
||||||
|
// 将选中的单位列表重置为空数组(取消所有选择)
|
||||||
selectedUnits = [];
|
selectedUnits = [];
|
||||||
}
|
}
|
||||||
+88
-31
@@ -1,39 +1,68 @@
|
|||||||
// systems/InputSystem.js
|
// 输入系统:处理玩家的键盘、鼠标和触摸输入,将输入转换为游戏事件
|
||||||
|
|
||||||
|
// 从ControlMode.js导入清除选择和设置激活单位的函数
|
||||||
import { clearSelection, setActiveUnit } from './ControlMode.js';
|
import { clearSelection, setActiveUnit } from './ControlMode.js';
|
||||||
|
|
||||||
|
// 导出InputSystem类,用于创建输入系统实例
|
||||||
export class InputSystem {
|
export class InputSystem {
|
||||||
|
// 构造函数:初始化输入系统
|
||||||
|
// @param {Object} scene - 游戏场景实例
|
||||||
constructor(scene) {
|
constructor(scene) {
|
||||||
|
// 保存场景引用,用于访问游戏世界和发送事件
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
|
||||||
|
// 用于存储框选开始时的鼠标世界坐标
|
||||||
|
// 初始值为null,表示当前没有进行框选操作
|
||||||
this.selectionStart = null;
|
this.selectionStart = null;
|
||||||
|
|
||||||
// 初始化键盘
|
// 初始化键盘输入
|
||||||
|
// 获取Phaser的键盘输入管理器
|
||||||
const kb = scene.input.keyboard;
|
const kb = scene.input.keyboard;
|
||||||
|
|
||||||
|
// 创建按键映射对象,将游戏功能与键盘按键关联
|
||||||
this.keys = {
|
this.keys = {
|
||||||
|
// 上移键:同时支持W键和方向上键
|
||||||
up: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.W), kb.addKey(Phaser.Input.Keyboard.KeyCodes.UP)],
|
up: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.W), kb.addKey(Phaser.Input.Keyboard.KeyCodes.UP)],
|
||||||
|
// 下移键:同时支持S键和方向下键
|
||||||
down: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.S), kb.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN)],
|
down: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.S), kb.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN)],
|
||||||
|
// 左移键:同时支持A键和方向左键
|
||||||
left: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.A), kb.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT)],
|
left: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.A), kb.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT)],
|
||||||
|
// 右移键:同时支持D键和方向右键
|
||||||
right: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.D), kb.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT)]
|
right: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.D), kb.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT)]
|
||||||
};
|
};
|
||||||
|
|
||||||
// 禁用浏览器右键菜单
|
// 禁用浏览器右键菜单,避免影响游戏操作
|
||||||
scene.input.mouse.disableContextMenu();
|
scene.input.mouse.disableContextMenu();
|
||||||
|
|
||||||
// 鼠标/触摸事件
|
// 注册鼠标/触摸事件监听器
|
||||||
|
// 当鼠标/触摸按下时,调用onPointerDown方法
|
||||||
scene.input.on('pointerdown', this.onPointerDown, this);
|
scene.input.on('pointerdown', this.onPointerDown, this);
|
||||||
|
// 当鼠标/触摸移动时,调用onPointerMove方法
|
||||||
scene.input.on('pointermove', this.onPointerMove, this);
|
scene.input.on('pointermove', this.onPointerMove, this);
|
||||||
|
// 当鼠标/触摸释放时,调用onPointerUp方法
|
||||||
scene.input.on('pointerup', this.onPointerUp, this);
|
scene.input.on('pointerup', this.onPointerUp, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查按键组中是否有任何按键被按下
|
||||||
|
// @param {Array} keyGroup - 按键对象数组
|
||||||
|
// @returns {boolean} - 如果有任何按键被按下则返回true,否则返回false
|
||||||
isKeyDown(keyGroup) {
|
isKeyDown(keyGroup) {
|
||||||
|
// 使用some方法检查数组中是否有任何一个按键处于按下状态
|
||||||
return keyGroup.some(key => key.isDown);
|
return keyGroup.some(key => key.isDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update方法:每帧自动调用(约60次/秒),用于处理持续的输入
|
||||||
update() {
|
update() {
|
||||||
// 键盘相对移动(仅当有激活单位)
|
// 创建一个方向对象,用于存储移动方向
|
||||||
const dir = { x: 0, y: 0 };
|
const dir = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
// 检查左移键是否被按下,如果是则x方向减1(向左移动)
|
||||||
if (this.isKeyDown(this.keys.left)) dir.x -= 1;
|
if (this.isKeyDown(this.keys.left)) dir.x -= 1;
|
||||||
|
// 检查右移键是否被按下,如果是则x方向加1(向右移动)
|
||||||
if (this.isKeyDown(this.keys.right)) dir.x += 1;
|
if (this.isKeyDown(this.keys.right)) dir.x += 1;
|
||||||
|
// 检查上移键是否被按下,如果是则y方向减1(向上移动)
|
||||||
if (this.isKeyDown(this.keys.up)) dir.y -= 1;
|
if (this.isKeyDown(this.keys.up)) dir.y -= 1;
|
||||||
|
// 检查下移键是否被按下,如果是则y方向加1(向下移动)
|
||||||
if (this.isKeyDown(this.keys.down)) dir.y += 1;
|
if (this.isKeyDown(this.keys.down)) dir.y += 1;
|
||||||
|
|
||||||
// 无论是否有按键按下,都发送移动事件
|
// 无论是否有按键按下,都发送移动事件
|
||||||
@@ -41,79 +70,101 @@ export class InputSystem {
|
|||||||
this.scene.events.emit('move-relative', dir);
|
this.scene.events.emit('move-relative', dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理鼠标/触摸按下事件
|
||||||
|
// @param {Object} pointer - 指针事件对象,包含鼠标/触摸的位置等信息
|
||||||
onPointerDown(pointer) {
|
onPointerDown(pointer) {
|
||||||
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
||||||
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果是左键按下
|
||||||
if (pointer.leftButtonDown()) {
|
if (pointer.leftButtonDown()) {
|
||||||
|
// 获取鼠标在游戏世界中的坐标(不是屏幕坐标)
|
||||||
const worldX = pointer.worldX;
|
const worldX = pointer.worldX;
|
||||||
const worldY = pointer.worldY;
|
const worldY = pointer.worldY;
|
||||||
|
|
||||||
// 检查是否点中某个单位
|
// 检查是否点中了某个单位
|
||||||
let clickedUnit = null;
|
let clickedUnit = null;
|
||||||
|
// 遍历场景中的所有单位
|
||||||
this.scene.unitGroup.getChildren().forEach(unit => {
|
this.scene.unitGroup.getChildren().forEach(unit => {
|
||||||
|
// 获取单位的边界矩形
|
||||||
const bounds = unit.getBounds();
|
const bounds = unit.getBounds();
|
||||||
|
// 检查鼠标世界坐标是否在单位的边界内
|
||||||
if (worldX >= bounds.x && worldX <= bounds.right &&
|
if (worldX >= bounds.x && worldX <= bounds.right &&
|
||||||
worldY >= bounds.y && worldY <= bounds.bottom) {
|
worldY >= bounds.y && worldY <= bounds.bottom) {
|
||||||
|
// 如果点中了单位,存储该单位
|
||||||
clickedUnit = unit;
|
clickedUnit = unit;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (clickedUnit) {
|
if (clickedUnit) {
|
||||||
// 切换控制目标
|
// 如果点中了单位,发送选择单位事件
|
||||||
this.scene.events.emit('select-unit', clickedUnit);
|
this.scene.events.emit('select-unit', clickedUnit);
|
||||||
} else {
|
} else {
|
||||||
// 开始框选或移动指令
|
// 如果没有点中单位,开始框选或移动指令
|
||||||
// 存储世界坐标用于框选
|
// 存储框选开始时的世界坐标
|
||||||
this.selectionStart = { x: worldX, y: worldY };
|
this.selectionStart = { x: worldX, y: worldY };
|
||||||
|
// 发送选择开始事件
|
||||||
this.scene.events.emit('selection-start', this.selectionStart);
|
this.scene.events.emit('selection-start', this.selectionStart);
|
||||||
}
|
}
|
||||||
} else if (pointer.rightButtonDown()) {
|
} else if (pointer.rightButtonDown()) {
|
||||||
// 右键点击:移动选中的单位
|
// 如果是右键按下,发送移动到指定点的事件
|
||||||
const worldX = pointer.worldX;
|
const worldX = pointer.worldX;
|
||||||
const worldY = pointer.worldY;
|
const worldY = pointer.worldY;
|
||||||
this.scene.events.emit('move-to-point', worldX, worldY);
|
this.scene.events.emit('move-to-point', worldX, worldY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理鼠标/触摸移动事件
|
||||||
|
// @param {Object} pointer - 指针事件对象
|
||||||
onPointerMove(pointer) {
|
onPointerMove(pointer) {
|
||||||
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
||||||
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果当前正在进行框选操作
|
||||||
if (this.selectionStart) {
|
if (this.selectionStart) {
|
||||||
// 使用世界坐标计算框选区域
|
// 获取当前鼠标在游戏世界中的坐标
|
||||||
const currentWorldX = pointer.worldX;
|
const currentWorldX = pointer.worldX;
|
||||||
const currentWorldY = pointer.worldY;
|
const currentWorldY = pointer.worldY;
|
||||||
|
|
||||||
// 计算当前选择框的位置和大小
|
// 计算框选区域的矩形
|
||||||
|
// 确保矩形的x和y是左上角坐标
|
||||||
const rect = new Phaser.Geom.Rectangle(
|
const rect = new Phaser.Geom.Rectangle(
|
||||||
|
// 使用Math.min确保x是较小的值(左上角)
|
||||||
Math.min(this.selectionStart.x, currentWorldX),
|
Math.min(this.selectionStart.x, currentWorldX),
|
||||||
|
// 使用Math.min确保y是较小的值(左上角)
|
||||||
Math.min(this.selectionStart.y, currentWorldY),
|
Math.min(this.selectionStart.y, currentWorldY),
|
||||||
|
// 计算矩形宽度
|
||||||
Math.abs(currentWorldX - this.selectionStart.x),
|
Math.abs(currentWorldX - this.selectionStart.x),
|
||||||
|
// 计算矩形高度
|
||||||
Math.abs(currentWorldY - this.selectionStart.y)
|
Math.abs(currentWorldY - this.selectionStart.y)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新选择框的位置和大小
|
// 发送选择更新事件,更新框选区域的显示
|
||||||
this.scene.events.emit('selection-update', rect);
|
this.scene.events.emit('selection-update', rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理鼠标/触摸释放事件
|
||||||
|
// @param {Object} pointer - 指针事件对象
|
||||||
onPointerUp(pointer) {
|
onPointerUp(pointer) {
|
||||||
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
|
||||||
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
|
||||||
|
// 重置框选起始点
|
||||||
this.selectionStart = null;
|
this.selectionStart = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果当前正在进行框选操作
|
||||||
if (this.selectionStart) {
|
if (this.selectionStart) {
|
||||||
// 使用世界坐标计算最终框选区域
|
// 获取当前鼠标在游戏世界中的坐标
|
||||||
const currentWorldX = pointer.worldX;
|
const currentWorldX = pointer.worldX;
|
||||||
const currentWorldY = pointer.worldY;
|
const currentWorldY = pointer.worldY;
|
||||||
|
|
||||||
|
// 计算最终的框选区域
|
||||||
const rect = new Phaser.Geom.Rectangle(
|
const rect = new Phaser.Geom.Rectangle(
|
||||||
Math.min(this.selectionStart.x, currentWorldX),
|
Math.min(this.selectionStart.x, currentWorldX),
|
||||||
Math.min(this.selectionStart.y, currentWorldY),
|
Math.min(this.selectionStart.y, currentWorldY),
|
||||||
@@ -121,22 +172,24 @@ export class InputSystem {
|
|||||||
Math.abs(currentWorldY - this.selectionStart.y)
|
Math.abs(currentWorldY - this.selectionStart.y)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 如果框太小,视为“点击地面移动”
|
// 如果框选区域太小(宽度和高度都小于10像素),视为点击地面移动
|
||||||
if (rect.width < 10 && rect.height < 10) {
|
if (rect.width < 10 && rect.height < 10) {
|
||||||
|
// 发送移动到指定点的事件
|
||||||
this.scene.events.emit('move-to-point', pointer.worldX, pointer.worldY);
|
this.scene.events.emit('move-to-point', pointer.worldX, pointer.worldY);
|
||||||
} else {
|
} else {
|
||||||
// 否则执行框选
|
// 否则执行框选操作
|
||||||
this.scene.events.emit('selection-end', rect);
|
this.scene.events.emit('selection-end', rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置框选起始点,结束框选操作
|
||||||
this.selectionStart = null;
|
this.selectionStart = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查鼠标是否在小地图上
|
* 检查鼠标是否在小地图上
|
||||||
* @param {Phaser.Input.Pointer} pointer
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
||||||
* @returns {boolean}
|
* @returns {boolean} - 如果鼠标在小地图上返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
isMouseOnMiniMap(pointer) {
|
isMouseOnMiniMap(pointer) {
|
||||||
// 检查场景中是否有小地图
|
// 检查场景中是否有小地图
|
||||||
@@ -144,25 +197,27 @@ export class InputSystem {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取小地图实例
|
||||||
const miniMap = this.scene.miniMap;
|
const miniMap = this.scene.miniMap;
|
||||||
|
// 获取鼠标在屏幕上的坐标
|
||||||
const mouseX = pointer.x;
|
const mouseX = pointer.x;
|
||||||
const mouseY = pointer.y;
|
const mouseY = pointer.y;
|
||||||
|
|
||||||
// 计算小地图的边界
|
// 计算小地图的边界
|
||||||
const mapLeft = miniMap.x;
|
const mapLeft = miniMap.x; // 小地图左边界
|
||||||
const mapRight = miniMap.x + miniMap.mapSize;
|
const mapRight = miniMap.x + miniMap.mapSize; // 小地图右边界
|
||||||
const mapTop = miniMap.y;
|
const mapTop = miniMap.y; // 小地图上边界
|
||||||
const mapBottom = miniMap.y + miniMap.mapSize;
|
const mapBottom = miniMap.y + miniMap.mapSize; // 小地图下边界
|
||||||
|
|
||||||
// 检查鼠标是否在小地图边界内
|
// 检查鼠标坐标是否在小地图边界内
|
||||||
return mouseX >= mapLeft && mouseX <= mapRight &&
|
return mouseX >= mapLeft && mouseX <= mapRight &&
|
||||||
mouseY >= mapTop && mouseY <= mapBottom;
|
mouseY >= mapTop && mouseY <= mapBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查鼠标是否在摇杆上
|
* 检查鼠标是否在虚拟摇杆上
|
||||||
* @param {Phaser.Input.Pointer} pointer
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
||||||
* @returns {boolean}
|
* @returns {boolean} - 如果鼠标在摇杆上返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
isMouseOnJoystick(pointer) {
|
isMouseOnJoystick(pointer) {
|
||||||
// 检查场景中是否有虚拟摇杆
|
// 检查场景中是否有虚拟摇杆
|
||||||
@@ -170,18 +225,20 @@ export class InputSystem {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取虚拟摇杆实例
|
||||||
const joystick = this.scene.virtualJoystick;
|
const joystick = this.scene.virtualJoystick;
|
||||||
|
// 获取鼠标在屏幕上的坐标
|
||||||
const mouseX = pointer.x;
|
const mouseX = pointer.x;
|
||||||
const mouseY = pointer.y;
|
const mouseY = pointer.y;
|
||||||
|
|
||||||
// 计算摇杆的边界(包括摇杆和操作区域)
|
// 计算摇杆的边界(包括摇杆和操作区域)
|
||||||
const joystickRadius = joystick.radius * 2; // 操作区域是摇杆半径的两倍
|
const joystickRadius = joystick.radius * 2; // 操作区域是摇杆半径的两倍
|
||||||
const joystickLeft = joystick.centerX - joystickRadius;
|
const joystickLeft = joystick.centerX - joystickRadius; // 摇杆左边界
|
||||||
const joystickRight = joystick.centerX + joystickRadius;
|
const joystickRight = joystick.centerX + joystickRadius; // 摇杆右边界
|
||||||
const joystickTop = joystick.centerY - joystickRadius;
|
const joystickTop = joystick.centerY - joystickRadius; // 摇杆上边界
|
||||||
const joystickBottom = joystick.centerY + joystickRadius;
|
const joystickBottom = joystick.centerY + joystickRadius; // 摇杆下边界
|
||||||
|
|
||||||
// 检查鼠标是否在摇杆边界内
|
// 检查鼠标坐标是否在摇杆边界内
|
||||||
return mouseX >= joystickLeft && mouseX <= joystickRight &&
|
return mouseX >= joystickLeft && mouseX <= joystickRight &&
|
||||||
mouseY >= joystickTop && mouseY <= joystickBottom;
|
mouseY >= joystickTop && mouseY <= joystickBottom;
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-11
@@ -1,70 +1,105 @@
|
|||||||
// systems/SelectionSystem.js
|
// 选择系统:处理游戏中单位的选择逻辑,包括单个单位点击选择和多个单位框选
|
||||||
|
|
||||||
|
// 从ControlMode.js导入选择管理相关的函数
|
||||||
import { clearSelection, addToSelection, setActiveUnit } from './ControlMode.js';
|
import { clearSelection, addToSelection, setActiveUnit } from './ControlMode.js';
|
||||||
|
|
||||||
|
// 导出SelectionSystem类,用于创建选择系统实例
|
||||||
export class SelectionSystem {
|
export class SelectionSystem {
|
||||||
|
// 构造函数:初始化选择系统
|
||||||
|
// @param {Object} scene - 游戏场景实例
|
||||||
constructor(scene) {
|
constructor(scene) {
|
||||||
|
// 保存场景引用,用于访问游戏世界和发送事件
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
|
||||||
|
// 选择框对象,用于显示框选区域
|
||||||
|
// 初始值为null,表示当前没有选择框
|
||||||
this.selectionBox = null;
|
this.selectionBox = null;
|
||||||
|
|
||||||
|
// 注册事件监听器,处理选择相关的事件
|
||||||
|
// 当开始选择时调用onStart方法
|
||||||
scene.events.on('selection-start', this.onStart, this);
|
scene.events.on('selection-start', this.onStart, this);
|
||||||
|
// 当选择区域更新时调用onUpdate方法
|
||||||
scene.events.on('selection-update', this.onUpdate, this);
|
scene.events.on('selection-update', this.onUpdate, this);
|
||||||
|
// 当选择结束时调用onEnd方法
|
||||||
scene.events.on('selection-end', this.onEnd, this);
|
scene.events.on('selection-end', this.onEnd, this);
|
||||||
|
// 当选择单个单位时调用onSelectUnit方法
|
||||||
scene.events.on('select-unit', this.onSelectUnit, this);
|
scene.events.on('select-unit', this.onSelectUnit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理选择开始事件
|
||||||
|
// @param {Object} pos - 选择开始的位置,包含x和y坐标
|
||||||
onStart(pos) {
|
onStart(pos) {
|
||||||
|
// 如果选择框不存在,则创建一个新的选择框
|
||||||
if (!this.selectionBox) {
|
if (!this.selectionBox) {
|
||||||
|
// 在游戏世界中创建一个矩形作为选择框
|
||||||
this.selectionBox = this.scene.add.rectangle(pos.x, pos.y, 1, 1, 0x00ff00, 0.3)
|
this.selectionBox = this.scene.add.rectangle(pos.x, pos.y, 1, 1, 0x00ff00, 0.3)
|
||||||
.setStrokeStyle(1, 0xffffff)
|
.setStrokeStyle(1, 0xffffff) // 设置白色边框,宽度为1像素
|
||||||
.setVisible(true);
|
.setVisible(true); // 设置选择框可见
|
||||||
} else {
|
} else {
|
||||||
|
// 如果选择框已存在,重置其位置和大小并设置可见
|
||||||
this.selectionBox.setPosition(pos.x, pos.y).setSize(1, 1).setVisible(true);
|
this.selectionBox.setPosition(pos.x, pos.y).setSize(1, 1).setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理选择区域更新事件
|
||||||
|
// @param {Object} rect - 更新后的选择区域矩形
|
||||||
onUpdate(rect) {
|
onUpdate(rect) {
|
||||||
|
// 如果选择框存在且可见
|
||||||
if (this.selectionBox && this.selectionBox.visible) {
|
if (this.selectionBox && this.selectionBox.visible) {
|
||||||
// 更新选择框的位置和大小
|
// 更新选择框的位置到矩形中心
|
||||||
this.selectionBox.setPosition(rect.centerX, rect.centerY);
|
this.selectionBox.setPosition(rect.centerX, rect.centerY);
|
||||||
|
// 更新选择框的大小到矩形的宽度和高度
|
||||||
this.selectionBox.setSize(rect.width, rect.height);
|
this.selectionBox.setSize(rect.width, rect.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理选择单个单位事件
|
||||||
|
// @param {Object} unit - 被选择的单位对象
|
||||||
onSelectUnit(unit) {
|
onSelectUnit(unit) {
|
||||||
// 清除所有单位的选中状态
|
// 清除所有单位的选中状态
|
||||||
this.scene.unitGroup.getChildren().forEach(u => {
|
this.scene.unitGroup.getChildren().forEach(u => {
|
||||||
|
// 检查单位是否有setSelected方法
|
||||||
if (u.setSelected) {
|
if (u.setSelected) {
|
||||||
|
// 设置单位为未选中状态
|
||||||
u.setSelected(false);
|
u.setSelected(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 清除当前选择
|
// 清除当前的选择列表和激活单位
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|
||||||
// 选择点击的单位
|
// 设置点击的单位为激活单位
|
||||||
setActiveUnit(unit);
|
setActiveUnit(unit);
|
||||||
|
// 将点击的单位添加到选择列表
|
||||||
addToSelection(unit);
|
addToSelection(unit);
|
||||||
|
|
||||||
// 设置选中状态
|
// 设置点击的单位为选中状态
|
||||||
if (unit.setSelected) {
|
if (unit.setSelected) {
|
||||||
unit.setSelected(true);
|
unit.setSelected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送单位选中事件,通知其他系统
|
||||||
this.scene.events.emit('units-selected', [unit]);
|
this.scene.events.emit('units-selected', [unit]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理选择结束事件
|
||||||
|
// @param {Object} rect - 最终的选择区域矩形
|
||||||
onEnd(rect) {
|
onEnd(rect) {
|
||||||
|
// 如果选择框存在,将其设置为不可见
|
||||||
if (this.selectionBox) {
|
if (this.selectionBox) {
|
||||||
this.selectionBox.setVisible(false);
|
this.selectionBox.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取场景中所有的单位
|
||||||
const units = this.scene.unitGroup.getChildren();
|
const units = this.scene.unitGroup.getChildren();
|
||||||
|
|
||||||
|
// 筛选出在选择区域内的单位
|
||||||
const selected = units.filter(unit => {
|
const selected = units.filter(unit => {
|
||||||
|
// 获取单位的边界矩形
|
||||||
const unitRect = unit.getBounds();
|
const unitRect = unit.getBounds();
|
||||||
|
// 检查单位的边界矩形是否与选择区域重叠
|
||||||
return Phaser.Geom.Rectangle.Overlaps(rect, unitRect);
|
return Phaser.Geom.Rectangle.Overlaps(rect, unitRect);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 先清除所有单位的选中状态
|
// 先清除所有单位的选中状态
|
||||||
units.forEach(unit => {
|
units.forEach(unit => {
|
||||||
@@ -73,18 +108,23 @@ export class SelectionSystem {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 清除当前的选择列表和激活单位
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|
||||||
|
// 如果有单位被选中
|
||||||
if (selected.length > 0) {
|
if (selected.length > 0) {
|
||||||
// 先设置激活单位
|
// 设置选中列表中的第一个单位为激活单位
|
||||||
setActiveUnit(selected[0]);
|
setActiveUnit(selected[0]);
|
||||||
// 然后添加所有选中的单位(包括激活单位)
|
|
||||||
|
// 将所有选中的单位添加到选择列表并设置为选中状态
|
||||||
selected.forEach(unit => {
|
selected.forEach(unit => {
|
||||||
addToSelection(unit);
|
addToSelection(unit);
|
||||||
if (unit.setSelected) {
|
if (unit.setSelected) {
|
||||||
unit.setSelected(true);
|
unit.setSelected(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 发送单位选中事件,通知其他系统
|
||||||
this.scene.events.emit('units-selected', selected);
|
this.scene.events.emit('units-selected', selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user