đź Comprendre lâECS : la brique invisible derriĂšre les jeux modernes
le 13 octobre 2025
Quand on conçoit un jeu, surtout un jeu tactique ou systémique comme Darkwaar, on se retrouve vite à jongler entre :
- des entités (joueurs, ennemis, objets, cases),
- des comportements (mouvement, attaque, effet),
- et des systĂšmes (rendu, IA, collisions, effets de statut...).
Les approches orientĂ©es objet classiques finissent vite par crĂ©er des hiĂ©rarchies trop profondes : Player extends Character extends Entity extends Drawable extends ObjectâŠ
Résultat : une usine à gaz.
Câest lĂ quâintervient lâECS â Entity Component System.
âïž LâidĂ©e de base
LâECS part dâun principe simple :
sĂ©parer les donnĂ©es, le comportement, et lâexĂ©cution.
| ĂlĂ©ment | RĂŽle | Exemple |
|---|---|---|
| Entity | Identifiant unique | #23 = Guerrier sur la case (3,2) |
| Component | Données brutes (pas de logique) | Position(3,2), Vie(10), Attaque(3) |
| System | Comportement (agit sur certains composants) | SystemeDeMouvement, SystemeDeCombat, SystemeDeRendu |
LâECS ne remplace pas la programmation orientĂ©e objet â il la dĂ©structure pour la rendre Ă©volutive. Au lieu dâĂ©crire ce que fait chaque classe, on dĂ©finit comment les donnĂ©es interagissent.
đ§© Exemple concret
Prenons un exemple simplifié en GDScript (Godot) :
# Composant Position
class_name CPosition
extends Resource
@export var q:int
@export var r:int
# Composant Vie
class_name CVie
extends Resource
@export var hp:int = 10
# SystĂšme de rendu
extends Node
const CPosition = preload("res://components/CPosition.gd")
func process_system(dt):
for entity in get_entities_with([CPosition]):
var pos = entity.get_component(CPosition)
draw_unit(pos.q, pos.r)
Ici :
- lâentitĂ© ne âfaitâ rien â elle contient des composants ;
- les systÚmes se déclenchent sur les entités qui possÚdent un certain ensemble de composants.
Câest une approche data-driven : tout est pilotĂ© par les donnĂ©es.
đ§ź Pourquoi câest puissant
LâECS nâest pas juste un design pattern Ă la mode. Câest une approche structurante qui rĂ©sout trois problĂšmes majeurs :
1. ĂvolutivitĂ©
Tu peux ajouter de nouveaux comportements sans casser les anciens :
Ajouter un composant
CInvisiblesuffit pour quâun systĂšme âRenduâ ignore ton entitĂ©.
2. Rejeu et simulation
Tu peux rejouer une partie en appliquant la mĂȘme sĂ©quence dâĂ©vĂ©nements, car tout lâĂ©tat du jeu est pur data, sĂ©rialisable, diffable et testable.
3. Performance
Les ECS modernes (comme Flecs, EnTT ou Unity DOTS) stockent les données en mémoire contiguë. Le CPU adore ça :
moins dâappels, moins de cache-miss, plus de vitesse.
đ§± Dans Darkwaar 5
Darkwaar 5 repose sur un ECS lĂ©ger en GDScript, sans moteur externe. Lâobjectif est dâavoir :
- un monde (
World) central, - des entités simples (un Node par personnage ou objet),
- des composants (
Resource) pour les données, - des systÚmes (
Node) pour la logique.
Exemple simplifié :
# GameRoot.gd
@onready var world := $World
func _ready():
var unit = world.create_entity()
unit.add_component(CPosition.new())
unit.add_component(CVie.new())
Chaque frame :
- le
Worldpasse sur les systÚmes actifs ; - les systÚmes parcourent les entités qui les concernent ;
- et la logique sâexĂ©cute sur les donnĂ©es brutes.
Cette sĂ©paration permet dâajouter facilement :
- un systĂšme de buffs (effets temporaires),
- un systÚme de résolution de combat,
- ou un systĂšme de puzzle pour les niveaux.
đ§© ECS â magie
LâECS ne fait pas âmieuxâ quâune approche orientĂ©e objet : il fait plus simple Ă maintenir.
Mais il y a un coĂ»t : il faut penser en flux de donnĂ©es, pas en hiĂ©rarchie dâobjets.
- Pas de âPlayer.move()â, mais un
SystemMouvementqui lit lesCPositionetCVitesse. - Pas de âEnemy.attack()â, mais un
SystemCombatqui lit lesCCombatetCVie.
Câest un changement de paradigme â mais une fois compris, tout devient plus clair.
đ§ Ce que Darkwood en retient
Chez Darkwood, lâECS nâest pas quâune architecture de jeu. Câest une façon de penser la modularitĂ© :
- Dans Darkwaar, il structure le gameplay et les puzzles.
- Dans Uniflow, il inspire la logique des âflowsâ de donnĂ©es.
- Dans Flow, il sert de base pour la composition visuelle dâautomatisations.
MĂȘme combat : sĂ©parer les donnĂ©es, les comportements et la logique dâexĂ©cution.
đź Et aprĂšs ?
La prochaine étape pour Darkwaar 5 :
- intĂ©grer lâECS au systĂšme de carte isomĂ©trique ;
- lier chaque case à une entité ;
- et synchroniser les composants entre la vue (haut) et le HUD (bas).
Cela posera les fondations dâun moteur tactique isomĂ©trique open-source, pensĂ© pour la gĂ©nĂ©ration procĂ©durale, les puzzles et les systĂšmes Ă©mergents.