mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-30 00:41:29 +08:00
feat(SS) 添加地图
This commit is contained in:
1 parent
2616dc21f1
commit
d3669bd44e
13 files changed
+1359
-99
No files matched your search
@@ -0,0 +1,196 @@
|
||||
# InputPlugin 架构设计说明
|
||||
|
||||
## 问题分析
|
||||
|
||||
### 原始设计的问题
|
||||
1. **紧耦合**:直接依赖 Phaser 的 Key 对象和事件系统
|
||||
2. **无法跨引擎**:切换引擎需要重写整个插件
|
||||
3. **违反开闭原则**:修改输入方式需要修改插件内部代码
|
||||
4. **测试困难**:难以进行单元测试(依赖具体引擎)
|
||||
|
||||
## 解决方案:适配器模式
|
||||
|
||||
### 架构层次
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 业务逻辑层 (GameScene) │
|
||||
│ - 不关心底层实现 │
|
||||
│ - 只调用统一接口 │
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ InputPlugin (核心插件) │
|
||||
│ - 提供统一接口 │
|
||||
│ - 管理适配器生命周期 │
|
||||
│ - registerKey(), isDown(), isUp() │
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ IInputAdapter (接口定义) │
|
||||
│ - 定义适配器必须实现的方法 │
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ 具体适配器实现 │
|
||||
│ - PhaserInputAdapter │
|
||||
│ - PixiInputAdapter │
|
||||
│ - CocosInputAdapter │
|
||||
│ - GodotInputAdapter (可扩展) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心优势
|
||||
|
||||
#### 1. **跨引擎复用**
|
||||
```javascript
|
||||
// Phaser 中使用
|
||||
const phaserPlugin = new InputPlugin(scene);
|
||||
phaserPlugin.registerKey('W', ['ArrowUp']);
|
||||
if (phaserPlugin.isDown('W')) { /* 移动 */ }
|
||||
|
||||
// PixiJS 中使用(代码完全相同)
|
||||
const pixiPlugin = new PixiInputPlugin(app);
|
||||
pixiPlugin.registerKey('W', ['ArrowUp']);
|
||||
if (pixiPlugin.isDown('W')) { /* 移动 */ }
|
||||
```
|
||||
|
||||
#### 2. **易于扩展**
|
||||
添加新引擎支持只需实现适配器接口:
|
||||
```javascript
|
||||
class GodotInputAdapter extends IInputAdapter {
|
||||
initialize() { /* Godot 特定实现 */ }
|
||||
registerKey(key, aliases) { /* ... */ }
|
||||
isDown(key) { /* ... */ }
|
||||
isUp(key) { /* ... */ }
|
||||
destroy() { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. **易于测试**
|
||||
```javascript
|
||||
class MockInputAdapter extends IInputAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
this.mockKeys = new Map();
|
||||
}
|
||||
|
||||
initialize() {}
|
||||
|
||||
registerKey(key, aliases) {
|
||||
this.mockKeys.set(key, false);
|
||||
}
|
||||
|
||||
isDown(key) {
|
||||
return this.mockKeys.get(key) || false;
|
||||
}
|
||||
|
||||
isUp(key) {
|
||||
return !this.isDown(key);
|
||||
}
|
||||
|
||||
destroy() {}
|
||||
|
||||
// 测试辅助方法
|
||||
setKeyDown(key) {
|
||||
this.mockKeys.set(key, true);
|
||||
}
|
||||
|
||||
setKeyUp(key) {
|
||||
this.mockKeys.set(key, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 单元测试示例
|
||||
const mockAdapter = new MockInputAdapter();
|
||||
const plugin = new InputPlugin(null, null);
|
||||
plugin.inputAdapter = mockAdapter;
|
||||
|
||||
plugin.registerKey('W');
|
||||
mockAdapter.setKeyDown('W');
|
||||
assert(plugin.isDown('W') === true);
|
||||
```
|
||||
|
||||
#### 4. **符合设计原则**
|
||||
- **单一职责原则**:每个适配器只负责一个引擎的输入处理
|
||||
- **开闭原则**:对扩展开放,对修改关闭
|
||||
- **依赖倒置原则**:依赖抽象接口,不依赖具体实现
|
||||
- **里氏替换原则**:所有适配器可以互相替换
|
||||
|
||||
## 使用示例
|
||||
|
||||
### Phaser 项目
|
||||
```javascript
|
||||
// main.js
|
||||
import { InputPlugin } from './plugins/InputPlugin.js';
|
||||
|
||||
const config = {
|
||||
scene: [GameScene],
|
||||
plugins: {
|
||||
scene: [
|
||||
{
|
||||
key: 'InputPlugin',
|
||||
plugin: InputPlugin,
|
||||
mapping: 'inputPlugin'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// GameScene.js
|
||||
create() {
|
||||
// 注册按键
|
||||
this.inputPlugin.registerKey('W', ['ArrowUp']);
|
||||
this.inputPlugin.registerKey('S', ['ArrowDown']);
|
||||
this.inputPlugin.registerKey('A', ['ArrowLeft']);
|
||||
this.inputPlugin.registerKey('D', ['ArrowRight']);
|
||||
}
|
||||
|
||||
update() {
|
||||
// 使用统一接口
|
||||
if (this.inputPlugin.isDown('W')) {
|
||||
this.player.setVelocityY(-200);
|
||||
}
|
||||
if (this.inputPlugin.isDown('S')) {
|
||||
this.player.setVelocityY(200);
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### PixiJS 项目
|
||||
```javascript
|
||||
// main.js
|
||||
import { PixiInputPlugin } from './plugins/PixiInputPlugin.js';
|
||||
|
||||
const app = new PIXI.Application({ width: 800, height: 600 });
|
||||
const inputPlugin = new PixiInputPlugin(app);
|
||||
|
||||
inputPlugin.registerKey('W', ['ArrowUp']);
|
||||
inputPlugin.registerKey('S', ['ArrowDown']);
|
||||
|
||||
// 游戏循环
|
||||
app.ticker.add(() => {
|
||||
if (inputPlugin.isDown('W')) {
|
||||
player.y -= 2;
|
||||
}
|
||||
if (inputPlugin.isDown('S')) {
|
||||
player.y += 2;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
**适配器模式的优势:**
|
||||
- ✅ 解耦:业务逻辑与具体引擎实现分离
|
||||
- ✅ 复用:同一套业务逻辑可在不同引擎中使用
|
||||
- ✅ 扩展:添加新引擎支持无需修改现有代码
|
||||
- ✅ 测试:可以轻松创建 Mock 对象进行单元测试
|
||||
- ✅ 维护:每个适配器独立维护,降低复杂度
|
||||
|
||||
**何时使用适配器模式:**
|
||||
- 需要集成第三方库或框架
|
||||
- 需要支持多种实现方式
|
||||
- 需要在不修改现有代码的情况下扩展功能
|
||||
- 需要提高代码的可测试性
|
||||
Reference in new issue
Block a user