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

ComposantAccès
Transforme.x, e.y, e.rotation, e.scale
Spritee.sprite, e.color
Animatione.animation
Sounde.sound
Musice.music
GridBodye.body
GridMape.map
Nodee.parent, e.children
Layere.layer
Namee.name
Camerae.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éTypeDescription
namestrNom du clip d’animation courant
frameintIndex de la frame courante dans le clip
playingboolTrue si l’animation est en cours de lecture
finishedboolTrue 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ètreTypeDéfautDescription
propertystrNom de la propriété (positionnel ou forme abrégée)
tofloatValeur cible
byfloatDécalage relatif (alternative à to)
startfloatactuelValeur de départ (par défaut la valeur actuelle)
durationfloat1.0Durée en secondes
easestr"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

ComposantPropriétés
Transformx, y, rotation, sx, sy
Spriter, g, b, alpha
Camerazoom

Fonctions d’easing

NomCourbe
linearVitesse constante (par défaut)
in_quadDépart lent, accélération
out_quadDépart rapide, décélération
in_out_quadDépart et fin lents
in_cubicDépart plus lent que quad
out_cubicDépart plus rapide que quad
in_out_cubicDépart et fin doux
in_expoDépart très lent, accélération explosive
in_out_expoMilieu explosif
out_expoDépart très rapide, arrêt doux
in_backRecule avant d’avancer
out_backDépasse la cible puis se stabilise
in_out_backRecul et dépassement
in_elasticRessort en tension
out_elasticDé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ètreTypeDéfautDescription
*propsstrUn ou plusieurs noms de propriété (positionnels)
byfloatAmplitude (mode oscillation). Omettre pour la rotation.
centerfloatactuelValeur centrale pour l’oscillation
speedfloat1.0Fré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 PythonStocké comme
intEntier 32 bits
floatFlottant 32 bits
boolBooléen
strChaîne fixe (max 31 chars)
EntityRé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ètreTypeDéfautDescription
*componentsstrNoms des composants requis
withouttuple()Noms des composants à exclure
include_selfboolFalseInclure 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 del ou = None
  • Détruite avec world.destroy()

Voir : pyxen.world.spawn() | pyxen.world.destroy()