Entity Component System
Brine2D uses a hybrid Entity–Component–Behavior–System (ECBS) model. Each concept has a specific role:
| Concept | Purpose | DI support |
|---|---|---|
| Component | Pure data, no logic | — |
| Behavior | Entity-specific logic | ✅ Full injection |
| System | Batch processing across many entities | ✅ Constructor injection |
Quick Start
public class GameScene : Scene
{
protected override void OnEnter()
{
World.CreateEntity("Player")
.AddComponent<TransformComponent>(t => t.Position = new Vector2(400, 300))
.AddComponent<SpriteComponent>(s => s.TexturePath = "assets/player.png")
.AddBehavior<PlayerMovementBehavior>();
}
}
World is a framework property available in every scene — no constructor injection needed.
Topics
Core
| Guide | Description |
|---|---|
| Getting Started | End-to-end walkthrough of the ECBS API |
| Entities | Create, tag, activate, and destroy entities |
| Components | Pure-data components and their lifecycle hooks |
Logic and Processing
| Guide | Description |
|---|---|
| Systems | Batch-process entities each frame |
| Queries | Find entities with fluent and cached queries |
Advanced
| Guide | Description |
|---|---|
| Multi-Threading | Automatic parallel query iteration |
The Four Concepts
Component — pure data
public class HealthComponent : Component
{
public int HP { get; set; } = 100;
public int MaxHP { get; set; } = 100;
}
Components inherit from Component and hold state only. Logic belongs in Behaviors or Systems.
Behavior — entity-specific logic with DI
public class PlayerMovementBehavior : Behavior
{
private readonly IInputContext _input;
private TransformComponent _transform = null!;
public PlayerMovementBehavior(IInputContext input) => _input = input;
protected override void OnAdded()
=> _transform = Entity!.GetRequiredComponent<TransformComponent>();
public override void Update(GameTime gameTime)
{
if (_input.IsKeyDown(Key.D))
_transform.Position += new Vector2(200f * (float)gameTime.DeltaTime, 0);
}
}
Behaviors are created via DI, attached to one entity, and participate in the Update/FixedUpdate/Render pipelines.
Behaviors are covered in the Getting Started guide
System — batch processing
public class GravitySystem : UpdateSystemBase
{
public override int UpdateOrder => SystemUpdateOrder.Physics;
public override void Update(IEntityWorld world, GameTime gameTime)
{
world.Query()
.With<TransformComponent>()
.With<PhysicsBodyComponent>()
.ForEach<TransformComponent, PhysicsBodyComponent>((entity, t, body) =>
{
body.Velocity += new Vector2(0, 980f) * (float)gameTime.DeltaTime;
t.Position += body.Velocity * (float)gameTime.DeltaTime;
});
}
}
Systems extend UpdateSystemBase, RenderSystemBase, or FixedUpdateSystemBase.
Queries — find entities
// One-shot fluent query
World.Query()
.With<TransformComponent>()
.WithTag("Enemy")
.WithinRadius(playerPos, 200f)
.ForEach<TransformComponent>((entity, t) => { /* ... */ });
// Cached query — built once, rebuilds only when components change
private CachedEntityQuery<TransformComponent, EnemyComponent>? _enemyQuery;
protected override void OnEnter()
{
_enemyQuery = World.CreateCachedQuery<TransformComponent, EnemyComponent>()
.WithTag("active")
.Build();
}
Default Systems
These systems are added to every scene automatically:
| System | Pipeline | Order | Purpose |
|---|---|---|---|
SpriteRenderingSystem |
Render | 0 | Sprite batching and culling |
AudioSystem |
Update | 0 | Spatial audio processing |
ParticleSystem |
Both | 250 / 100 | GPU-instanced particles |
AnimationSystem |
Update | 400 | Sprite animation and state machines |
CameraSystem |
Update | 500 | Camera follow and zoom |
DebugRenderer |
Render | 1000 | Debug visualization (disabled by default) |
Enable/disable or remove them from OnEnter:
protected override void OnEnter()
{
World.GetSystem<ParticleSystem>()!.IsEnabled = false;
World.GetSystem<DebugRenderer>()!.IsEnabled = true;
}
Physics systems are opt-in. Call
builder.Services.AddPhysics()thenWorld.AddSystem<Box2DPhysicsSystem>().
When to Use What
| Situation | Use |
|---|---|
| Per-entity input, AI, or effects | Behavior |
| Batch physics, rendering, collision | System |
| Pure state (position, health, flags) | Component |
| Finding groups of entities per frame | Cached EntityQuery |
Related Topics
- Getting Started — end-to-end walkthrough
- Entities — entity management
- Components — component lifecycle
- Systems — system base classes and ordering
- Queries — fluent and cached queries
- Multi-Threading — automatic parallel iteration
- Fundamentals: ECBS Architecture — design rationale
Ready to build with ECS? Start with Getting Started!