# Scene Management

In the ECS architecture, a Scene is a container for the game world, responsible for managing the lifecycle of entities, systems, and components. Scenes provide a complete ECS runtime environment.

## Basic Concepts

Scene is the core container of the ECS framework, providing:
- Entity creation, management, and destruction
- System registration and execution scheduling
- Component storage and querying
- Event system support
- Performance monitoring and debugging information

## Scene Management Options

ECS Framework provides two scene management approaches:

1. **[SceneManager](./scene-manager)** - Suitable for 95% of game applications
   - Single-player games, simple multiplayer games, mobile games
   - Lightweight, simple and intuitive API
   - Supports scene transitions

2. **[WorldManager](./world-manager)** - Suitable for advanced multi-world isolation scenarios
   - MMO game servers, game room systems
   - Multi-World management, each World can contain multiple scenes
   - Completely isolated independent environments

This document focuses on the usage of the Scene class itself. For detailed information about scene managers, please refer to the corresponding documentation.

## Creating a Scene

### Inheriting the Scene Class

**Recommended: Inherit the Scene class to create custom scenes**

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

class GameScene extends Scene {
  protected initialize(): void {
    // Set scene name
    this.name = "GameScene";

    // Add systems
    this.addSystem(new MovementSystem());
    this.addSystem(new RenderSystem());
    this.addSystem(new PhysicsSystem());

    // Create initial entities
    this.createInitialEntities();
  }

  private createInitialEntities(): void {
    // Create player
    const player = this.createEntity("Player");
    player.addComponent(new Position(400, 300));
    player.addComponent(new Health(100));
    player.addComponent(new PlayerController());

    // Create enemies
    for (let i = 0; i < 5; i++) {
      const enemy = this.createEntity(`Enemy_${i}`);
      enemy.addComponent(new Position(Math.random() * 800, Math.random() * 600));
      enemy.addComponent(new Health(50));
      enemy.addComponent(new EnemyAI());
    }
  }

  public onStart(): void {
    console.log("Game scene started");
    // Logic when scene starts
  }

  public unload(): void {
    console.log("Game scene unloaded");
    // Cleanup logic when scene unloads
  }
}
```

### Using Scene Configuration

```typescript
import { ISceneConfig } from '@esengine/ecs-framework';

const config: ISceneConfig = {
  name: "MainGame",
  enableEntityDirectUpdate: false
};

class ConfiguredScene extends Scene {
  constructor() {
    super(config);
  }
}
```

## Scene Lifecycle

Scene provides complete lifecycle management:

```typescript
class ExampleScene extends Scene {
  protected initialize(): void {
    // Scene initialization: setup systems and initial entities
    console.log("Scene initializing");
  }

  public onStart(): void {
    // Scene starts running: game logic begins execution
    console.log("Scene starting");
  }

  public unload(): void {
    // Scene unloading: cleanup resources
    console.log("Scene unloading");
  }
}

// Using scenes (lifecycle automatically managed by framework)
const scene = new ExampleScene();
// Scene's initialize(), begin(), update(), end() are automatically called by the framework
```

**Lifecycle Methods**:

1. `initialize()` - Scene initialization, setup systems and initial entities
2. `begin()` / `onStart()` - Scene starts running
3. `update()` - Per-frame update (called by scene manager)
4. `end()` / `unload()` - Scene unloading, cleanup resources

## Entity Management

### Creating Entities

```typescript
class EntityScene extends Scene {
  createGameEntities(): void {
    // Create single entity
    const player = this.createEntity("Player");

    // Batch create entities (high performance)
    const bullets = this.createEntities(100, "Bullet");

    // Add components to batch-created entities
    bullets.forEach((bullet, index) => {
      bullet.addComponent(new Position(index * 10, 100));
      bullet.addComponent(new Velocity(Math.random() * 200 - 100, -300));
    });
  }
}
```

### Finding Entities

```typescript
class SearchScene extends Scene {
  findEntities(): void {
    // Find by name
    const player = this.findEntity("Player");
    const player2 = this.getEntityByName("Player"); // Alias method

    // Find by ID
    const entity = this.findEntityById(123);

    // Find by tag
    const enemies = this.findEntitiesByTag(2);
    const enemies2 = this.getEntitiesByTag(2); // Alias method

    if (player) {
      console.log(`Found player: ${player.name}`);
    }

    console.log(`Found ${enemies.length} enemies`);
  }
}
```

### Destroying Entities

```typescript
class DestroyScene extends Scene {
  cleanupEntities(): void {
    // Destroy all entities
    this.destroyAllEntities();

    // Single entity destruction through the entity itself
    const enemy = this.findEntity("Enemy_1");
    if (enemy) {
      enemy.destroy(); // Entity is automatically removed from the scene
    }
  }
}
```

## System Management

### Adding and Removing Systems

```typescript
class SystemScene extends Scene {
  protected initialize(): void {
    // Add systems
    const movementSystem = new MovementSystem();
    this.addSystem(movementSystem);

    // Set system update order
    movementSystem.updateOrder = 1;

    // Add more systems
    this.addSystem(new PhysicsSystem());
    this.addSystem(new RenderSystem());
  }

  public removeUnnecessarySystems(): void {
    // Get system
    const physicsSystem = this.getEntityProcessor(PhysicsSystem);

    // Remove system
    if (physicsSystem) {
      this.removeSystem(physicsSystem);
    }
  }
}
```

## Event System

Scene has a built-in type-safe event system:

```typescript
class EventScene extends Scene {
  protected initialize(): void {
    // Listen to events
    this.eventSystem.on('player_died', this.onPlayerDied.bind(this));
    this.eventSystem.on('enemy_spawned', this.onEnemySpawned.bind(this));
    this.eventSystem.on('level_complete', this.onLevelComplete.bind(this));
  }

  private onPlayerDied(data: any): void {
    console.log('Player died event');
    // Handle player death
  }

  private onEnemySpawned(data: any): void {
    console.log('Enemy spawned event');
    // Handle enemy spawn
  }

  private onLevelComplete(data: any): void {
    console.log('Level complete event');
    // Handle level completion
  }

  public triggerGameEvent(): void {
    // Send event (synchronous)
    this.eventSystem.emitSync('custom_event', {
      message: "This is a custom event",
      timestamp: Date.now()
    });

    // Send event (asynchronous)
    this.eventSystem.emit('async_event', {
      data: "Async event data"
    });
  }
}
```

## Best Practices

### 1. Scene Responsibility Separation

```typescript
// Good scene design - clear responsibilities
class MenuScene extends Scene {
  // Only handles menu-related logic
}

class GameScene extends Scene {
  // Only handles gameplay logic
}

class InventoryScene extends Scene {
  // Only handles inventory logic
}

// Avoid this design - mixed responsibilities
class MegaScene extends Scene {
  // Contains menu, game, inventory, and all other logic
}
```

### 2. Proper System Organization

```typescript
class OrganizedScene extends Scene {
  protected initialize(): void {
    // Add systems by function and dependencies
    this.addInputSystems();
    this.addLogicSystems();
    this.addRenderSystems();
  }

  private addInputSystems(): void {
    this.addSystem(new InputSystem());
  }

  private addLogicSystems(): void {
    this.addSystem(new MovementSystem());
    this.addSystem(new PhysicsSystem());
    this.addSystem(new CollisionSystem());
  }

  private addRenderSystems(): void {
    this.addSystem(new RenderSystem());
    this.addSystem(new UISystem());
  }
}
```

### 3. Resource Management

```typescript
class ResourceScene extends Scene {
  private textures: Map<string, any> = new Map();
  private sounds: Map<string, any> = new Map();

  protected initialize(): void {
    this.loadResources();
  }

  private loadResources(): void {
    // Load resources needed by the scene
    this.textures.set('player', this.loadTexture('player.png'));
    this.sounds.set('bgm', this.loadSound('bgm.mp3'));
  }

  public unload(): void {
    // Cleanup resources
    this.textures.clear();
    this.sounds.clear();
    console.log('Scene resources cleaned up');
  }

  private loadTexture(path: string): any {
    // Load texture
    return null;
  }

  private loadSound(path: string): any {
    // Load sound
    return null;
  }
}
```

## Next Steps

- Learn about [SceneManager](./scene-manager) - Simple scene management for most games
- Learn about [WorldManager](./world-manager) - For scenarios requiring multi-world isolation
- Learn about [Persistent Entity](./persistent-entity) - Keep entities across scene transitions (v2.3.0+)

Scene is the core container of the ECS framework. Proper scene management makes your game architecture clearer, more modular, and easier to maintain.
