# 系统（System）详解指南

系统是ECS架构中的"S"，负责处理拥有特定组件的实体。本指南详细介绍框架中的各种系统类型及其使用方法。

## 系统基础概念

### 什么是系统？

系统是处理游戏逻辑的地方，它们：
- **专注单一职责** - 每个系统只处理一种类型的逻辑
- **自动执行** - 系统会在每帧自动被调用
- **基于组件过滤** - 只处理包含特定组件的实体
- **高性能** - 利用ECS的数据局部性优势

### 系统的工作原理

```typescript
// 系统的基本工作流程：
// 1. 查询符合条件的实体
// 2. 遍历这些实体
// 3. 读取/修改实体的组件数据
// 4. 执行游戏逻辑

class MovementSystem extends EntitySystem {
    process(entities: Entity[]) {
        for (const entity of entities) {
            const position = entity.getComponent(PositionComponent);
            const velocity = entity.getComponent(VelocityComponent);
            
            // 更新位置 = 当前位置 + 速度 * 时间
            position.x += velocity.x * Time.deltaTime;
            position.y += velocity.y * Time.deltaTime;
        }
    }
}
```

## 系统类型详解

### 1. EntitySystem - 基础系统

最常用的系统类型，每帧处理所有符合条件的实体。

```typescript
import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';

class HealthSystem extends EntitySystem {
    constructor() {
        // 使用Matcher创建查询条件
        super(Matcher.all(HealthComponent));
        // 或者使用链式语法
        // super(Matcher.empty().all(HealthComponent));
    }
    
    // 主要处理逻辑
    protected process(entities: Entity[]) {
        // 直接使用传入的entities参数，已经是匹配的实体
        for (const entity of entities) {
            const health = entity.getComponent(HealthComponent)!;
            
            // 处理生命值逻辑
            if (health.currentHealth <= 0) {
                this.handleDeath(entity);
            } else if (health.currentHealth < health.maxHealth) {
                this.handleRegeneration(health);
            }
        }
    }
    
    private handleDeath(entity: Entity) {
        // 添加死亡标记
        entity.addComponent(new DeadComponent());
        
        // 触发死亡事件
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.emit('entity:died', {
            entityId: entity.id,
            entityName: entity.name
        });
    }
    
    private handleRegeneration(health: HealthComponent) {
        // 缓慢恢复生命值
        health.currentHealth += health.regenRate * Time.deltaTime;
        health.currentHealth = Math.min(health.currentHealth, health.maxHealth);
    }
}
```

**适用场景：**
- 移动系统
- 渲染系统
- 碰撞检测系统
- AI系统

### 2. ProcessingSystem - 简化处理系统

不需要处理具体实体，主要用于执行全局逻辑或不依赖特定实体的系统处理。

```typescript
import { ProcessingSystem, Matcher } from '@esengine/ecs-framework';

class GameLogicSystem extends ProcessingSystem {
    constructor() {
        // ProcessingSystem可以不指定Matcher，或使用空Matcher
        super(Matcher.empty());
    }
    
    // 处理系统逻辑（每帧执行）
    public processSystem() {
        // 执行全局游戏逻辑
        this.updateGameState();
        this.checkWinConditions();
        this.updateUI();
    }
    
    private updateGameState() {
        // 更新游戏状态逻辑
        console.log("更新游戏状态");
    }
    
    private checkWinConditions() {
        // 检查胜利条件
        const players = this.scene.findEntitiesByTag(EntityTags.PLAYER);
        const enemies = this.scene.findEntitiesByTag(EntityTags.ENEMY);
        
        if (enemies.length === 0) {
            this.triggerVictory();
        } else if (players.length === 0) {
            this.triggerGameOver();
        }
    }
    
    private updateUI() {
        // 更新UI显示
        const gameTime = Time.totalTime;
        console.log(`游戏时间: ${gameTime.toFixed(1)}秒`);
    }
    
    private triggerVictory() {
        console.log("游戏胜利！");
        // 处理胜利逻辑
    }
    
    private triggerGameOver() {
        console.log("游戏结束！");
        // 处理游戏结束逻辑
    }
}
```

**适用场景：**
- 全局游戏逻辑系统
- 胜负判断系统
- UI更新系统
- 不依赖特定实体的处理

## AI系统示例

下面是一个完整的AI系统示例，展示EntitySystem的典型用法：

```typescript
import { EntitySystem, Matcher, Entity } from '@esengine/ecs-framework';

enum AIState {
    IDLE,
    PATROL,
    CHASE,
    ATTACK
}

class AISystem extends EntitySystem {
    constructor() {
        // 复杂匹配条件可以使用链式语法
        super(Matcher.empty().all(AIComponent, PositionComponent));
        // 或者使用简洁语法
        // super(Matcher.all(AIComponent, PositionComponent));
    }
    
    // 处理所有匹配的实体
    protected process(entities: Entity[]) {
        for (const entity of entities) {
            this.processEntity(entity);
        }
    }
    
    // 处理单个实体的逻辑（自定义方法）
    private processEntity(entity: Entity) {
        const ai = entity.getComponent(AIComponent);
        const position = entity.getComponent(PositionComponent);
        
        switch (ai.state) {
            case AIState.IDLE:
                this.processIdle(entity, ai);
                break;
            case AIState.PATROL:
                this.processPatrol(entity, ai, position);
                break;
            case AIState.CHASE:
                this.processChase(entity, ai, position);
                break;
            case AIState.ATTACK:
                this.processAttack(entity, ai);
                break;
        }
    }
    
    private processIdle(entity: Entity, ai: AIComponent) {
        ai.idleTimer += Time.deltaTime;
        
        if (ai.idleTimer >= ai.idleTime) {
            ai.state = AIState.PATROL;
            ai.idleTimer = 0;
        }
        
        // 检查附近是否有玩家
        const nearbyPlayer = this.findNearbyPlayer(entity, ai.detectionRange);
        if (nearbyPlayer) {
            ai.state = AIState.CHASE;
            ai.target = nearbyPlayer;
        }
    }
    
    private processPatrol(entity: Entity, ai: AIComponent, position: PositionComponent) {
        // 简单的来回巡逻
        if (!ai.patrolTarget) {
            ai.patrolTarget = this.getNextPatrolPoint(ai);
        }
        
        const direction = ai.patrolTarget.subtract(position);
        const distance = direction.length();
        
        if (distance < 10) {
            ai.patrolTarget = this.getNextPatrolPoint(ai);
        } else {
            const normalized = direction.normalize();
            position.x += normalized.x * ai.moveSpeed * Time.deltaTime;
            position.y += normalized.y * ai.moveSpeed * Time.deltaTime;
        }
    }
}
```

**适用场景：**
- 全局游戏逻辑系统
- 胜负判断系统
- UI更新系统
- 不依赖特定实体的处理

### 3. IntervalSystem - 间隔执行系统

不是每帧都执行，而是按指定间隔执行的系统，适合不需要高频更新的逻辑。

```typescript
import { IntervalSystem, Matcher } from '@esengine/ecs-framework';

class SpawnSystem extends IntervalSystem {
    private spawnPoints: { x: number; y: number }[] = [
        { x: 100, y: 100 },
        { x: 700, y: 100 },
        { x: 400, y: 500 }
    ];
    
    // 每2秒执行一次
    constructor() {
        // IntervalSystem需要指定间隔时间和Matcher
        super(2.0, Matcher.all(SpawnerComponent));
    }
    
    // 间隔执行的逻辑（重写process方法）
    protected process(entities: Entity[]) {
        // entities就是匹配的生成器实体
        
        for (const spawner of entities) {
            const spawnerComp = spawner.getComponent(SpawnerComponent);
            
            if (this.shouldSpawn(spawnerComp)) {
                this.spawnEnemy(spawner, spawnerComp);
            }
        }
    }
    
    private shouldSpawn(spawner: SpawnerComponent): boolean {
        // 检查是否应该生成
        const currentEnemyCount = this.getCurrentEnemyCount();
        return currentEnemyCount < spawner.maxEnemies && 
               Math.random() < spawner.spawnChance;
    }
    
    private spawnEnemy(spawnerEntity: Entity, spawner: SpawnerComponent) {
        // 随机选择生成点
        const spawnPoint = this.spawnPoints[
            Math.floor(Math.random() * this.spawnPoints.length)
        ];
        
        // 创建敌人实体
        const enemy = this.scene.createEntity("Enemy");
        enemy.addComponent(new PositionComponent(spawnPoint.x, spawnPoint.y));
        enemy.addComponent(new HealthComponent(50));
        enemy.addComponent(new AIComponent());
        enemy.addComponent(new VelocityComponent(0, 0));
        enemy.tag = EntityTags.ENEMY;
        
        // 更新生成器统计
        spawner.spawnedCount++;
        spawner.lastSpawnTime = Time.totalTime;
        
        // 发送生成事件
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.emit('enemy:spawned', {
            enemyId: enemy.id,
            spawnPoint: spawnPoint,
            spawnerEntity: spawnerEntity.id
        });
    }
}
```

**适用场景：**
- 敌人生成系统
- 自动保存系统
- 资源回收系统
- 定期数据同步

### 4. PassiveSystem - 被动系统

不处理实体的系统，主要用于事件监听和响应。

```typescript
import { PassiveSystem, Matcher, Core } from '@esengine/ecs-framework';

class ScoreSystem extends PassiveSystem {
    private score: number = 0;
    private multiplier: number = 1;
    private combo: number = 0;
    
    constructor() {
        // PassiveSystem也需要Matcher，即使不使用
        super(Matcher.empty());
    }
    
    initialize() {
        super.initialize();
        
        // 监听游戏事件（使用EntityManager的事件系统）
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.on('enemy:killed', this.onEnemyKilled, { context: this });
        eventBus.on('item:collected', this.onItemCollected, { context: this });
        eventBus.on('combo:broken', this.onComboBroken, { context: this });
    }
    
    // PassiveSystem被移除时清理
    destroy() {
        // 事件监听会在系统销毁时自动清理
        // 如需手动清理，可以保存listenerId并调用eventBus.off()
    }
    
    private onEnemyKilled(data: { enemyType: string; position: { x: number; y: number } }) {
        // 根据敌人类型给分
        let baseScore = this.getScoreForEnemyType(data.enemyType);
        
        // 连击奖励
        this.combo++;
        if (this.combo > 3) {
            this.multiplier = Math.min(this.combo * 0.1, 3.0); // 最多3倍
        }
        
        const finalScore = Math.floor(baseScore * this.multiplier);
        this.addScore(finalScore);
        
        // 显示分数奖励
        this.showScorePopup(data.position, finalScore);
    }
    
    private addScore(points: number) {
        this.score += points;
        
        // 发送分数更新事件
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.emit('score:updated', {
            score: this.score,
            points: points,
            multiplier: this.multiplier,
            combo: this.combo
        });
    }
}
```

**适用场景：**
- 分数统计系统
- 音效播放系统
- UI更新系统
- 成就系统

## 系统生命周期方法

系统提供了多个生命周期方法，可以根据需要重写：

### 重要的生命周期方法

```typescript
class ExampleSystem extends EntitySystem {
    /**
     * 系统初始化回调 - 系统被添加到场景时调用
     * 用于设置事件监听器、初始化资源等
     * 注意：不要重写initialize()方法，而是重写onInitialize()
     */
    protected onInitialize() {
        // 设置事件监听
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.on('someEvent', this.handleEvent, { context: this });
        
        console.log('系统已初始化');
    }
    
    /**
     * 每帧处理开始前调用
     */
    protected onBegin() {
        // 预处理逻辑，如重置计数器
        this.frameCounter++;
    }
    
    /**
     * 主要处理逻辑 - 每帧调用
     * @param entities 符合条件的实体列表
     */
    protected process(entities: Entity[]) {
        for (const entity of entities) {
            // 处理每个实体
            this.processEntity(entity);
        }
    }
    
    /**
     * 后期处理 - 在process之后调用
     * @param entities 符合条件的实体列表
     */
    protected lateProcess(entities: Entity[]) {
        // 后期处理逻辑，如碰撞检测后的响应
        this.handlePostProcessing();
    }
    
    /**
     * 每帧处理结束后调用
     */
    protected onEnd() {
        // 后处理逻辑，如统计数据更新
        this.updateStatistics();
    }
}
```

### 生命周期执行顺序

系统的生命周期方法按以下顺序执行：

1. **initialize()** - 系统被添加到场景时执行一次（框架调用）
   - **onInitialize()** - 用户可重写的初始化回调
2. 每帧循环：
   - **onBegin()** - 帧开始前（用户可重写）
   - **process(entities)** - 主要处理逻辑（用户必须实现）
   - **lateProcess(entities)** - 后期处理（用户可重写）
   - **onEnd()** - 帧结束后（用户可重写）

## 系统管理和注册

### 在场景中添加系统

```typescript
import { Scene, Core } from '@esengine/ecs-framework';

const scene = new Scene();

// 添加各种系统（使用addEntityProcessor方法）
scene.addEntityProcessor(new MovementSystem());
scene.addEntityProcessor(new GameLogicSystem());
scene.addEntityProcessor(new SpawnSystem());
scene.addEntityProcessor(new ScoreSystem());

// 设置系统的执行优先级
const movementSystem = scene.getEntityProcessor(MovementSystem);
if (movementSystem) {
    movementSystem.updateOrder = 10; // 数值越小越先执行
}

const renderSystem = scene.getEntityProcessor(RenderSystem);
if (renderSystem) {
    renderSystem.updateOrder = 100; // 渲染系统最后执行
}

// 设置为当前场景
Core.setScene(scene;
```

### 系统的启用和禁用

```typescript
// 暂时禁用某个系统
const gameLogicSystem = scene.getEntityProcessor(GameLogicSystem);
if (gameLogicSystem) {
    gameLogicSystem.enabled = false;
}

// 重新启用
if (gameLogicSystem) {
    gameLogicSystem.enabled = true;
}

// 移除系统
scene.removeEntityProcessor(gameLogicSystem);
```

## 系统设计最佳实践

### 1. 单一职责原则

```typescript
// 好的设计：每个系统只负责一件事
class MovementSystem extends EntitySystem {
    // 只负责移动
}

class CollisionSystem extends EntitySystem {
    // 只负责碰撞检测
}

class RenderSystem extends EntitySystem {
    // 只负责渲染
}

// 不好的设计：一个系统做太多事情
class GameplaySystem extends EntitySystem {
    // 既处理移动，又处理碰撞，还处理渲染...
}
```

### 2. 合理的系统执行顺序

```typescript
// 设置合理的执行顺序
scene.addEntityProcessor(new InputSystem()).updateOrder = 0;    // 输入最先
scene.addEntityProcessor(new GameLogicSystem()).updateOrder = 10;     // 游戏逻辑
scene.addEntityProcessor(new MovementSystem()).updateOrder = 20; // 移动计算
scene.addEntityProcessor(new CollisionSystem()).updateOrder = 30; // 碰撞检测
scene.addEntityProcessor(new HealthSystem()).updateOrder = 40;  // 生命值处理
scene.addEntityProcessor(new RenderSystem()).updateOrder = 100; // 渲染最后
```

### 3. 系统间通信

```typescript
// 使用事件进行系统间通信
class CollisionSystem extends EntitySystem {
    process(entities: Entity[]) {
        // ... 碰撞检测逻辑
        
        if (collision) {
            // 发送碰撞事件，让其他系统响应
            const eventBus = this.scene.entityManager.eventBus;
            eventBus.emit('collision:detected', {
                entity1: collider1,
                entity2: collider2,
                collisionPoint: point
            });
        }
    }
}

class HealthSystem extends PassiveSystem {
    initialize() {
        super.initialize();
        
        // 监听碰撞事件
        const eventBus = this.scene.entityManager.eventBus;
        eventBus.on('collision:detected', this.onCollision, { context: this });
    }
    
    private onCollision(data: CollisionEventData) {
        // 处理碰撞伤害
        if (data.entity1.hasComponent(HealthComponent)) {
            const health = data.entity1.getComponent(HealthComponent);
            health.takeDamage(10);
        }
    }
}
```

### 4. 性能优化

```typescript
class OptimizedMovementSystem extends EntitySystem {
    private lastUpdateTime: number = 0;
    private readonly UPDATE_INTERVAL = 16; // 60FPS
    
    process(entities: Entity[]) {
        const currentTime = Time.totalTime;
        
        // 限制更新频率
        if (currentTime - this.lastUpdateTime < this.UPDATE_INTERVAL) {
            return;
        }
        
        // 批量处理
        this.processBatch(entities);
        
        this.lastUpdateTime = currentTime;
    }
    
    private processBatch(entities: Entity[]) {
        // 使用for循环而不是forEach，性能更好
        for (let i = 0; i < entities.length; i++) {
            const entity = entities[i];
            // 处理逻辑...
        }
    }
}
```

## 常见问题

### Q: 系统的执行顺序重要吗？

A: 非常重要！合理的执行顺序可以避免逻辑错误：

```typescript
// 正确顺序：
// 1. 输入系统（收集玩家输入）
// 2. AI系统（敌人决策）
// 3. 移动系统（更新位置）
// 4. 碰撞系统（检测碰撞）
// 5. 渲染系统（显示画面）
```

### Q: 什么时候使用哪种系统类型？

A: 
- **EntitySystem** - 大部分游戏逻辑（移动、AI、碰撞等）
- **ProcessingSystem** - 不依赖特定实体的全局处理（游戏状态管理、全局逻辑）
- **IntervalSystem** - 不需要每帧执行的逻辑（生成器、自动保存）
- **PassiveSystem** - 事件响应系统（分数、音效、UI更新）

### Q: 系统可以访问其他系统吗？

A: 不建议直接访问。推荐使用事件系统进行系统间通信，保持松耦合。

### Q: 如何调试系统性能？

A: 使用框架内置的性能监控：

```typescript
const monitor = PerformanceMonitor.instance;
monitor.startFrame('MovementSystem');
// 系统逻辑...
monitor.endFrame('MovementSystem');

// 查看性能报告
console.log(monitor.getReport());
```

通过合理使用这些系统类型，你可以构建出高性能、易维护的游戏逻辑！ 