pyxen.Entity
Une Entity est un handle léger — un conteneur pour des composants.
Pour une introduction au système entité-composant, consultez Entités et Composants.
Composants intégrés
| Composant | Accès |
|---|---|
| Transform | e.x, e.y, e.rotation, e.scale |
| Sprite | e.sprite, e.color |
| Animation | e.animation |
| Sound | e.sound |
| Music | e.music |
| GridBody | e.body |
| GridMap | e.map |
| Node | e.parent, e.children |
| Layer | e.layer |
| Name | e.name |
| Camera | e.camera |
Transform
e.x = 100
e.y = 50
e.rotation = 45
e.scale = (2, 2)
La lecture de scale renvoie un Vector2 :
s = e.scale
print(s.x, s.y)
Sprite
e.sprite = sprite
e.color = (1.0, 0.5, 0.5, 1.0)
La lecture de color renvoie un objet Color :
c = e.color
print(c.r, c.g, c.b, c.a)
Animation de sprite
Lorsqu’un sprite est créé avec le paramètre animation, le moteur joue l’animation automatiquement. Vous pouvez lire l’état de l’animation via e.animation :
player.sprite = Sprite("hero", animation="walk")
Propriétés
| Propriété | Type | Description |
|---|---|---|
name | str | Nom du clip d’animation courant |
frame | int | Index de la frame courante dans le clip |
playing | bool | True si l’animation est en cours de lecture |
finished | bool | True si une animation à lecture unique est terminée |
anim = player.animation
if anim:
print(anim.name) # "walk"
print(anim.frame) # 2
print(anim.playing) # True
print(anim.finished) # False
Si aucune animation n’est active, e.animation renvoie None :
player.sprite = Sprite("hero", tile=(0, 0, 16, 16))
print(player.animation) # None
Annulation
Assignez None à e.animation pour arrêter la lecture :
player.animation = None
Assigner un nouveau sprite annule automatiquement toute animation existante.
Animations à lecture unique
Utilisez loop=False pour les animations qui ne jouent qu’une fois :
player.sprite = Sprite("hero", animation="attack", loop=False)
def update():
if player.animation and player.animation.finished:
player.sprite = Sprite("hero", animation="idle")
Tweens
Les tweens animent les propriétés d’une entité au fil du temps. Le moteur gère l’interpolation automatiquement — pas de code par frame nécessaire.
entity.tween()
# Forme avec nom de propriété
entity.tween("x", to=200, duration=1.0)
entity.tween("alpha", to=0, duration=0.5, ease="out_quad")
# Forme abrégée — animer plusieurs propriétés en même temps
entity.tween(x=200, y=100, duration=1.0, ease="out_quad")
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
property | str | — | Nom de la propriété (positionnel ou forme abrégée) |
to | float | — | Valeur cible |
by | float | — | Décalage relatif (alternative à to) |
start | float | actuel | Valeur de départ (par défaut la valeur actuelle) |
duration | float | 1.0 | Durée en secondes |
ease | str | "linear" | Nom de la fonction d’easing |
Utilisez to pour une cible absolue, ou by pour un décalage relatif :
entity.tween("x", to=200, duration=1.0) # déplacer vers x=200
entity.tween("x", by=50, duration=0.5) # déplacer de 50 pixels vers la droite
Utilisez start pour forcer la valeur de départ :
entity.tween("x", to=200, start=0, duration=1.0) # toujours partir de 0
Propriétés animables
| Composant | Propriétés |
|---|---|
| Transform | x, y, rotation, sx, sy |
| Sprite | r, g, b, alpha |
| Camera | zoom |
Fonctions d’easing
| Nom | Courbe |
|---|---|
linear | Vitesse constante (par défaut) |
in_quad | Départ lent, accélération |
out_quad | Départ rapide, décélération |
in_out_quad | Départ et fin lents |
in_cubic | Départ plus lent que quad |
out_cubic | Départ plus rapide que quad |
in_out_cubic | Départ et fin doux |
in_expo | Départ très lent, accélération explosive |
in_out_expo | Milieu explosif |
out_expo | Départ très rapide, arrêt doux |
in_back | Recule avant d’avancer |
out_back | Dépasse la cible puis se stabilise |
in_out_back | Recul et dépassement |
in_elastic | Ressort en tension |
out_elastic | Dépassement et rebond élastique |
in_out_elastic | Élastique aux deux extrémités |
entity.tweens.cancel()
Annule les tweens d’une entité. Passez un nom de propriété pour annuler un seul tween, ou appelez sans argument pour annuler tous les tweens. La valeur se fige à sa position actuelle.
entity.tweens.cancel("x") # annuler une propriété
entity.tweens.cancel() # annuler tous
Résolution des conflits
Lancer un nouveau tween sur la même entité et propriété remplace le précédent. Les tweens sur des propriétés différentes s’exécutent indépendamment.
entity.tween("x", to=100, duration=1.0)
entity.tween("x", to=200, duration=0.5) # remplace le premier tween
entity.tween("y", to=50, duration=1.0) # s'exécute en parallèle du tween x
Les tweens sur les entités détruites sont nettoyés automatiquement.
Lancer un animate() sur une propriété annule tout tween() actif sur cette propriété, et vice versa.
Animations
Animations continues qui s’exécutent indéfiniment — oscillation sinusoïdale (pulsation, respiration, balancement) et rotation à vitesse constante.
entity.animate() — Oscillation
Fait osciller une propriété autour d’une valeur centrale avec une onde sinusoïdale.
entity.animate("sx", "sy", by=0.15, speed=6.0) # coin pulse
entity.animate("alpha", by=0.3, center=0.7, speed=4.0) # flicker 0.4–1.0
La valeur suit : center + sin(elapsed * speed) * by
entity.animate() — Rotation
Accumule une valeur à un rythme constant. Omettez by= pour utiliser le mode rotation.
entity.animate("rotation", speed=180) # 180°/sec clockwise
Paramètres
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
*props | str | — | Un ou plusieurs noms de propriété (positionnels) |
by | float | — | Amplitude (mode oscillation). Omettre pour la rotation. |
center | float | actuel | Valeur centrale pour l’oscillation |
speed | float | 1.0 | Fréquence angulaire (oscillation) ou unités/sec (rotation) |
Mêmes 10 propriétés que les tweens : x, y, rotation, sx, sy, r, g, b, alpha, zoom.
entity.animations.cancel()
Annule les animations d’une entité. Passez un nom de propriété pour annuler une seule animation, ou appelez sans argument pour annuler toutes les animations.
entity.animations.cancel("rotation") # annuler une propriété
entity.animations.cancel() # annuler toutes
Parent / Enfants
child.parent = parent
Accéder aux enfants :
for c in parent.children:
print(c.name)
Obtenir le nombre d’enfants :
parent.children.count
Composants personnalisés
Les composants sont créés par assignation :
- Un dictionnaire — composant structuré
- Un booléen — composant marqueur
e.cell = {
'row': 0,
'col': 0
}
La première assignation crée le schéma. Les types des champs sont inférés et le schéma devient fixe — vous ne pouvez pas ajouter de nouveaux champs par la suite.
Utilisation des composants dans les systèmes
for cell in world.all("cell"):
...
Voir : pyxen.world.all()
Composants marqueurs
e.alive = True
Les marqueurs ne stockent aucune donnée — ils indiquent uniquement une présence. Vous pouvez les requêter comme des composants normaux :
for e in world.all("alive"):
...
Accès aux champs des composants
e.cell.row
e.cell.col
e.cell.row = 5
Types de champs supportés
| Type Python | Stocké comme |
|---|---|
int | Entier 32 bits |
float | Flottant 32 bits |
bool | Booléen |
str | Chaîne fixe (max 31 chars) |
Entity | Référence d’entité |
Les types invalides lèvent une erreur :
TypeError: invalid value type in dict
Règles du schéma
- Taille maximale d’un composant : 256 octets
- Chaînes : 31 caractères maximum
- Les clés du dictionnaire doivent être des chaînes
- Impossible d’ajouter de nouveaux champs après la création du schéma
e.cell = {'row': 0}
e.cell = {'row': 0, 'new_field': 5}
ValueError: cannot create new fields after schema is complete
Il est valide d’omettre des champs lors des assignations suivantes — ils prennent les valeurs par défaut 0, 0.0, False, "", etc.
Vérifier la présence d’un composant
e.has("cell")
Renvoie True si l’entité possède le composant, False sinon.
Cela fonctionne pour les noms de composants personnalisés et intégrés :
e.has("sprite") # True si l'entité a un sprite
e.has("body") # True si l'entité a un grid body
Requêter les descendants
entity.all(*components, without=(), include_self=False)
Renvoie un itérateur sur tous les descendants de l’entité (parcours en profondeur dans la hiérarchie du scene graph) correspondant au filtre de composants donné.
Fonctionne exactement comme world.all(), mais limité à un sous-arbre au lieu du monde entier.
# Tous les descendants avec le composant "enemy"
for e in parent.all("enemy"):
...
# Avec exclusion
for e in parent.all("enemy", without=("boss",)):
...
# Inclure l'entité parente elle-même
for e in parent.all("tag", include_self=True):
...
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
*components | str | — | Noms des composants requis |
without | tuple | () | Noms des composants à exclure |
include_self | bool | False | Inclure ou non l’entité elle-même |
Les noms de composants intégrés et personnalisés sont supportés.
Suppression de composants
Supprimez un composant d’une entité en utilisant del ou en assignant None :
# Les deux sont équivalents :
del entity.health
entity.health = None
Après la suppression, entity.has("health") retourne False et l’entité ne correspond plus aux requêtes pour ce composant.
e = world.spawn()
e.health = {'hp': 100}
del e.health
e.has("health") # False
# world.all("health") n'inclura pas e
Vous pouvez réajouter un composant après l’avoir supprimé :
del e.health
e.health = {'hp': 50} # fonctionne normalement
Composants intégrés
Tous les composants intégrés peuvent être supprimés :
del e.sprite # efface les données du sprite
del e.body # efface le corps physique
del e.camera # supprime la caméra
del e.text # supprime le texte
del e.sound # supprime le son
del e.music # supprime la musique
del e.map # supprime la grille de carte
Sprite et body sont réinitialisés à zéro (l’entité conserve le stockage, mais les données sont vides). Camera, text, sound, music et map sont entièrement effacés.
Marqueurs
e.enemy = True
del e.enemy # ou : e.enemy = None
e.has("enemy") # False
Cycle de vie d’une entité
- Créée avec
world.spawn() - Modifiée via l’assignation de composants
- Composants supprimés avec
delou= None - Détruite avec
world.destroy()
Voir : pyxen.world.spawn() | pyxen.world.destroy()