mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-29 17:37:35 +08:00
feat(control) 小地图
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# CINC 游戏项目
|
||||
|
||||
## 项目介绍
|
||||
CINC是一个基于Phaser.js开发的2D策略/模拟游戏项目。该项目采用模块化架构设计,实现了单位管理、选择控制、移动命令等核心游戏功能,支持键盘和鼠标操作,以及虚拟摇杆控制。
|
||||
|
||||
## 功能特性
|
||||
- **单位系统**:创建和管理游戏单位,支持单位移动和碰撞检测
|
||||
- **选择系统**:支持单选和框选多个单位
|
||||
- **命令系统**:处理单位移动命令,支持相对移动和目标点移动
|
||||
- **输入系统**:统一处理键盘和鼠标输入
|
||||
- **响应式设计**:适配不同屏幕尺寸
|
||||
- **虚拟摇杆**:支持触摸设备操作
|
||||
|
||||
## 技术栈
|
||||
- **游戏引擎**:Phaser.js
|
||||
- **开发语言**:ES6+ JavaScript (模块化)
|
||||
- **渲染技术**:HTML5 Canvas
|
||||
- **物理系统**:Phaser Arcade Physics
|
||||
|
||||
## 项目结构
|
||||
```
|
||||
├── config/ # 游戏配置文件
|
||||
│ └── gameConfig.js
|
||||
├── index.html # 入口HTML文件
|
||||
├── main.js # 游戏初始化入口
|
||||
├── objects/ # 游戏对象定义
|
||||
│ └── Unit.js # 单位类
|
||||
├── phaser.min.js # Phaser.js库
|
||||
├── scenes/ # 游戏场景
|
||||
│ └── GameScene.js
|
||||
├── systems/ # 游戏系统
|
||||
│ ├── CommandSystem.js # 命令处理系统
|
||||
│ ├── ControlMode.js # 控制模式管理
|
||||
│ ├── InputSystem.js # 输入处理系统
|
||||
│ └── SelectionSystem.js # 单位选择系统
|
||||
├── ui/ # 用户界面组件
|
||||
│ └── VirtualJoystick.js # 虚拟摇杆
|
||||
└── utils/ # 工具文件
|
||||
```
|
||||
|
||||
## 运行方法
|
||||
1. 使用Python启动本地HTTP服务器:
|
||||
```bash
|
||||
python -m http.server 8000
|
||||
```
|
||||
|
||||
2. 在浏览器中访问:
|
||||
```
|
||||
http://localhost:8000
|
||||
```
|
||||
|
||||
## 游戏操作
|
||||
- **单选单位**:鼠标左键点击单位
|
||||
- **框选单位**:按住鼠标左键拖动框选多个单位
|
||||
- **移动命令**:点击空地指定移动目标点
|
||||
- **键盘控制**:使用WASD或方向键进行相对移动(需先选中单位)
|
||||
|
||||
## 开发说明
|
||||
项目采用模块化设计,各系统之间通过事件系统通信,便于扩展和维护。主要系统职责:
|
||||
|
||||
- **InputSystem**:处理所有输入事件,转换为游戏命令
|
||||
- **SelectionSystem**:管理单位选择状态
|
||||
- **CommandSystem**:执行具体游戏命令
|
||||
- **Unit**:单位对象,处理自身逻辑和渲染
|
||||
|
||||
## 扩展建议
|
||||
- 添加单位属性系统(生命值、攻击力等)
|
||||
- 实现战斗系统
|
||||
- 添加地图和关卡系统
|
||||
- 实现资源管理系统
|
||||
- 添加UI界面(控制面板、状态栏等)
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 758 B |
+129
@@ -0,0 +1,129 @@
|
||||
// ui/MiniMap.js
|
||||
|
||||
export class MiniMap {
|
||||
constructor(scene, options = {}) {
|
||||
this.scene = scene;
|
||||
this.worldSize = options.worldSize || 2000;
|
||||
this.mapSize = options.mapSize || 200;
|
||||
this.x = options.x || 10;
|
||||
this.y = options.y || 10;
|
||||
|
||||
// 计算缩放比例(将世界坐标转换为小地图坐标)
|
||||
this.scale = this.mapSize / (this.worldSize * 2);
|
||||
|
||||
// 创建小地图容器
|
||||
this.container = scene.add.container(this.x, this.y);
|
||||
this.container.setScrollFactor(0, 0); // 小地图固定在屏幕上
|
||||
|
||||
// 创建小地图背景
|
||||
this.background = scene.add.rectangle(0, 0, this.mapSize, this.mapSize, 0x000000, 0.5);
|
||||
this.background.setOrigin(0, 0);
|
||||
this.background.setStrokeStyle(1, 0xffffff, 0.8);
|
||||
this.container.add(this.background);
|
||||
|
||||
// 创建视口指示器
|
||||
this.viewport = scene.add.rectangle(0, 0, 0, 0, 0xffffff, 0.3);
|
||||
this.viewport.setOrigin(0, 0);
|
||||
this.viewport.setStrokeStyle(1, 0xffffff, 1);
|
||||
this.container.add(this.viewport);
|
||||
|
||||
// 创建单位标记数组
|
||||
this.unitMarkers = [];
|
||||
|
||||
// 设置交互
|
||||
this.setupInteractions();
|
||||
|
||||
// 更新小地图(初始调用)
|
||||
this.update();
|
||||
}
|
||||
|
||||
setupInteractions() {
|
||||
// 启用容器交互
|
||||
this.container.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.mapSize, this.mapSize), Phaser.Geom.Rectangle.Contains);
|
||||
|
||||
// 点击小地图移动相机
|
||||
this.container.on('pointerdown', (pointer) => {
|
||||
this.handleMapClick(pointer);
|
||||
});
|
||||
|
||||
// 拖动小地图移动相机
|
||||
this.container.on('pointermove', (pointer) => {
|
||||
if (pointer.isDown) {
|
||||
this.handleMapDrag(pointer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleMapClick(pointer) {
|
||||
// 将小地图坐标转换为世界坐标
|
||||
const worldX = (pointer.x - this.x) / this.scale - this.worldSize;
|
||||
const worldY = (pointer.y - this.y) / this.scale - this.worldSize;
|
||||
|
||||
// 移动相机到点击位置
|
||||
this.scene.cameras.main.centerOn(worldX, worldY);
|
||||
}
|
||||
|
||||
handleMapDrag(pointer) {
|
||||
// 将小地图坐标转换为世界坐标
|
||||
const worldX = (pointer.x - this.x) / this.scale - this.worldSize;
|
||||
const worldY = (pointer.y - this.y) / this.scale - this.worldSize;
|
||||
|
||||
// 移动相机到拖动位置
|
||||
this.scene.cameras.main.centerOn(worldX, worldY);
|
||||
}
|
||||
|
||||
update() {
|
||||
// 更新视口指示器位置和大小
|
||||
this.updateViewport();
|
||||
|
||||
// 更新单位标记
|
||||
this.updateUnitMarkers();
|
||||
}
|
||||
|
||||
updateViewport() {
|
||||
const camera = this.scene.cameras.main;
|
||||
|
||||
// 计算相机视口在世界中的位置和大小
|
||||
const viewportLeft = camera.scrollX;
|
||||
const viewportTop = camera.scrollY;
|
||||
const viewportWidth = camera.width * camera.zoom;
|
||||
const viewportHeight = camera.height * camera.zoom;
|
||||
|
||||
// 将世界坐标转换为小地图坐标
|
||||
const mapLeft = (viewportLeft + this.worldSize) * this.scale;
|
||||
const mapTop = (viewportTop + this.worldSize) * this.scale;
|
||||
const mapWidth = viewportWidth * this.scale;
|
||||
const mapHeight = viewportHeight * this.scale;
|
||||
|
||||
// 更新视口指示器
|
||||
this.viewport.setPosition(mapLeft, mapTop);
|
||||
this.viewport.setSize(mapWidth, mapHeight);
|
||||
}
|
||||
|
||||
updateUnitMarkers() {
|
||||
// 清除现有标记
|
||||
this.unitMarkers.forEach(marker => {
|
||||
marker.destroy();
|
||||
});
|
||||
this.unitMarkers = [];
|
||||
|
||||
// 获取所有单位
|
||||
if (this.scene.unitGroup) {
|
||||
const units = this.scene.unitGroup.getChildren();
|
||||
|
||||
units.forEach(unit => {
|
||||
// 将单位世界坐标转换为小地图坐标
|
||||
const mapX = (unit.x + this.worldSize) * this.scale;
|
||||
const mapY = (unit.y + this.worldSize) * this.scale;
|
||||
|
||||
// 创建单位标记
|
||||
const marker = this.scene.add.circle(mapX, mapY, 2, 0xff0000, 1);
|
||||
marker.setOrigin(0.5, 0.5);
|
||||
|
||||
// 将标记添加到容器和数组中
|
||||
this.container.add(marker);
|
||||
this.unitMarkers.push(marker);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user