Entités et components
Pyxen utilise un Entity-Component System (ECS). Si vous avez déjà utilisé des moteurs de jeu avec des hiérarchies de classes — où un Player hérite de Character qui hérite de GameObject — c’est différent. Dans Pyxen, il n’y a pas d’héritage. Tout repose sur la composition.
Entités
Une entity est un objet de jeu. Ce peut être un joueur, un mur, un projectile, une particule — n’importe quoi. Sous le capot, une entity est simplement un identifiant. Elle ne contient aucune donnée par elle-même. À la place, vous lui attachez des components.
player = world.spawn(name="player", x=100, y=50)
Cela crée une entity à la position (100, 50) avec un nom. L’entity existe dans le monde et sera affichée si elle possède un sprite.
Components
Les components sont des données attachées à une entity. Pyxen en propose deux types :
Components intégrés
Ceux-ci sont fournis par le moteur :
| Component | Fonction |
|---|---|
| Transform | Position (x, y), rotation, échelle |
| Sprite | Apparence visuelle — image, tile, pivot, couleur |
| Camera | Viewport avec zoom |
| GridBody | Corps de collision sur la grille |
| GridMap | Tilemap avec lignes, colonnes et données de tiles |
| Sound | Lecture d’effets sonores |
| Music | Lecture de flux musical |
| Name | Identifiant textuel pour la recherche |
| Layer | Couche de rendu (0–255) |
| Parent / Children | Hiérarchie de scène |
Vous définissez les components intégrés via les propriétés de l’entity ou au moment de la création :
e = world.spawn(
x=50, y=80,
sprite=Sprite("hero"),
name="player"
)
# plus tard
e.x = 100
e.sprite = Sprite("hero", tile=(16, 0, 16, 16))
Components personnalisés
Vous pouvez attacher vos propres components à n’importe quelle entity. Un component personnalisé est un dictionnaire avec des champs typés :
player.health = {"value": 100, "max": 100}
player.speed = {"value": 2.5}
Une fois attaché, vous accédez directement aux champs :
player.health.value -= 10
Vous pouvez aussi utiliser des components marqueurs — des components sans données qui servent d’étiquettes :
player.alive = True
enemy.boss = True
C’est utile pour les requêtes : vous pouvez trouver toutes les entités possédant un marqueur donné.
Types de champs
Les champs de components peuvent être :
| Type | Exemple | Notes |
|---|---|---|
int | 42 | Entier 32 bits |
float | 3.14 | Flottant 32 bits |
bool | True | Booléen |
str | "hello" | 31 caractères maximum |
| Entity | player | Référence vers une autre entity |
Ces contraintes existent car les components sont stockés dans un format compact et optimisé pour le cache à l’intérieur du moteur C++. C’est ce qui rend les requêtes rapides.
Rechercher des entités
Le monde vous permet de trouver des entités par leurs components :
# toutes les entités avec un component "health"
for e in world.all("health"):
if e.health.value <= 0:
world.destroy(e)
# combiner : possède "enemy", ne possède pas "dead"
for e in world.all("enemy", without=("dead",)):
e.x += e.speed.value
Vous pouvez aussi effectuer des requêtes sur les components intégrés comme "sprite", "body", "camera", "sound", "music" et "map" :
# toutes les entités avec un sprite
for e in world.all("sprite"):
e.color = (1, 1, 1, 1)
# entités ayant à la fois un sprite et le component personnalisé "enemy"
for e in world.all("sprite", "enemy"):
e.color = (1, 0, 0, 1)
Les requêtes sont la principale façon d’écrire la logique de jeu dans Pyxen. Au lieu que chaque objet se mette à jour lui-même, vous écrivez des systèmes qui parcourent les entités possédant des components spécifiques.
Consultez l’API complète : world.all(), Entity
Pourquoi l’ECS ?
Si vous êtes habitué à la programmation orientée objet pour les jeux, l’ECS peut sembler inhabituel au début. Ses avantages :
- Pas de hiérarchies de classes — vous n’avez pas besoin de décider à l’avance si un PowerUp est-un Collectible est-un Entity. Attachez simplement les components dont vous avez besoin.
- Combinaison facile des comportements — une entity peut avoir les components
health,enemy,flyingetbossen même temps, sans héritage multiple. - Requêtes rapides — le moteur stocke les components en mémoire contiguë, donc parcourir toutes les entités possédant un component donné est très efficace.
- Débogage facile — chaque entity est simplement un ensemble de données. L’inspecteur de frames vous montre exactement ce qui est attaché à chacune d’elles.