pyxen.Entity
Ein Entity ist ein leichtgewichtiger Handle — ein Container für Components.
Eine Einführung in das Entity-Component-System findest du unter Entities und Components.
Eingebaute Components
| Component | Zugriff |
|---|---|
| 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)
Das Lesen von scale gibt einen Vector2 zurück:
s = e.scale
print(s.x, s.y)
Sprite
e.sprite = sprite
e.color = (1.0, 0.5, 0.5, 1.0)
Das Lesen von color gibt ein Color-Objekt zurück:
c = e.color
print(c.r, c.g, c.b, c.a)
Sprite-Animation
Wenn ein Sprite mit dem animation-Parameter erstellt wird, spielt die Engine die Animation automatisch ab. Du kannst den Animationszustand über e.animation auslesen:
player.sprite = Sprite("hero", animation="walk")
Eigenschaften
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
name | str | Name des aktuellen Animationsclips |
frame | int | Aktueller Frame-Index innerhalb des Clips |
playing | bool | True wenn die Animation aktiv abgespielt wird |
finished | bool | True wenn eine einmalige Animation beendet ist |
anim = player.animation
if anim:
print(anim.name) # "walk"
print(anim.frame) # 2
print(anim.playing) # True
print(anim.finished) # False
Wenn keine Animation aktiv ist, gibt e.animation None zurück:
player.sprite = Sprite("hero", tile=(0, 0, 16, 16))
print(player.animation) # None
Abbrechen
Setze e.animation auf None, um die Wiedergabe zu stoppen:
player.animation = None
Das Zuweisen eines neuen Sprites bricht automatisch jede bestehende Animation ab.
Einmalige Animationen
Verwende loop=False für Animationen, die nur einmal abgespielt werden:
player.sprite = Sprite("hero", animation="attack", loop=False)
def update():
if player.animation and player.animation.finished:
player.sprite = Sprite("hero", animation="idle")
Tweens
Tweens animieren die Eigenschaften einer Entität über die Zeit. Die Engine übernimmt die Interpolation automatisch — kein Code pro Frame nötig.
entity.tween()
# Benannte Eigenschaft
entity.tween("x", to=200, duration=1.0)
entity.tween("alpha", to=0, duration=0.5, ease="out_quad")
# Kurzschreibweise — mehrere Eigenschaften gleichzeitig animieren
entity.tween(x=200, y=100, duration=1.0, ease="out_quad")
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
property | str | — | Eigenschaftsname (positional oder Kurzschreibweise) |
to | float | — | Zielwert |
by | float | — | Relativer Offset (Alternative zu to) |
start | float | aktuell | Startwert (standardmäßig der aktuelle Wert) |
duration | float | 1.0 | Dauer in Sekunden |
ease | str | "linear" | Name der Easing-Funktion |
Verwende to für einen absoluten Zielwert oder by für einen relativen Offset:
entity.tween("x", to=200, duration=1.0) # bewege zu x=200
entity.tween("x", by=50, duration=0.5) # bewege 50 Pixel nach rechts
Verwende start, um den Startwert zu überschreiben:
entity.tween("x", to=200, start=0, duration=1.0) # immer von 0 starten
Animierbare Eigenschaften
| Komponente | Eigenschaften |
|---|---|
| Transform | x, y, rotation, sx, sy |
| Sprite | r, g, b, alpha |
| Camera | zoom |
Easing-Funktionen
| Name | Kurve |
|---|---|
linear | Konstante Geschwindigkeit (Standard) |
in_quad | Langsamer Start, beschleunigend |
out_quad | Schneller Start, verlangsamend |
in_out_quad | Langsamer Start und Ende |
in_cubic | Langsamerer Start als Quad |
out_cubic | Schnellerer Start als Quad |
in_out_cubic | Sanfter langsamer Start und Ende |
in_expo | Sehr langsamer Start, explosive Beschleunigung |
in_out_expo | Explosive Mitte |
out_expo | Sehr schneller Start, sanfter Stopp |
in_back | Zieht zurück bevor es vorwärts geht |
out_back | Überschießt das Ziel, pendelt sich ein |
in_out_back | Zurückziehen und Überschießen |
in_elastic | Elastisches Aufziehen |
out_elastic | Elastisches Überschießen und Schwingen |
in_out_elastic | Elastisch an beiden Enden |
entity.tweens.cancel()
Bricht Tweens einer Entität ab. Übergeben Sie einen Eigenschaftsnamen, um einen einzelnen Tween abzubrechen, oder rufen Sie ohne Argument auf, um alle Tweens abzubrechen. Der Wert bleibt an seiner aktuellen Position stehen.
entity.tweens.cancel("x") # einen Tween abbrechen
entity.tweens.cancel() # alle abbrechen
Konfliktlösung
Ein neuer Tween auf derselben Entität und Eigenschaft ersetzt den vorherigen. Tweens auf verschiedenen Eigenschaften laufen unabhängig voneinander.
entity.tween("x", to=100, duration=1.0)
entity.tween("x", to=200, duration=0.5) # ersetzt den ersten Tween
entity.tween("y", to=50, duration=1.0) # läuft neben dem x-Tween
Tweens auf zerstörten Entitäten werden automatisch aufgeräumt.
Ein animate() auf einer Eigenschaft bricht jeden aktiven tween() auf dieser Eigenschaft ab und umgekehrt.
Animationen
Kontinuierliche Animationen, die unbegrenzt laufen — Sinuswellen-Oszillation (Pulsieren, Atmen, Wippen) und konstante Drehung.
entity.animate() — Oszillieren
Lässt eine Eigenschaft mit einer Sinuswelle um einen Mittelwert oszillieren.
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
Der Wert folgt: center + sin(elapsed * speed) * by
entity.animate() — Drehen
Akkumuliert einen Wert mit konstanter Rate. Lassen Sie by= weg, um den Drehmodus zu verwenden.
entity.animate("rotation", speed=180) # 180°/sec clockwise
Parameter
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
*props | str | — | Ein oder mehrere Eigenschaftsnamen (positional) |
by | float | — | Amplitude (Oszillationsmodus). Weglassen für Drehung. |
center | float | aktuell | Mittelwert für die Oszillation |
speed | float | 1.0 | Winkelfrequenz (Oszillation) oder Einheiten/Sek (Drehung) |
Dieselben 10 Eigenschaften wie bei Tweens: x, y, rotation, sx, sy, r, g, b, alpha, zoom.
entity.animations.cancel()
Bricht Animationen einer Entität ab. Übergeben Sie einen Eigenschaftsnamen, um eine einzelne Animation abzubrechen, oder rufen Sie ohne Argument auf, um alle Animationen abzubrechen.
entity.animations.cancel("rotation") # eine Animation abbrechen
entity.animations.cancel() # alle abbrechen
Parent / Children
child.parent = parent
Zugriff auf Kinder:
for c in parent.children:
print(c.name)
Anzahl der Kinder abfragen:
parent.children.count
Eigene Components
Components werden durch Zuweisung erstellt:
- Ein Dictionary — strukturierte Komponente
- Ein Boolean — Marker-Komponente
e.cell = {
'row': 0,
'col': 0
}
Die erste Zuweisung erstellt das Schema. Feldtypen werden abgeleitet und das Schema ist danach fixiert — du kannst später keine neuen Felder hinzufügen.
Components in Systemen verwenden
for cell in world.all("cell"):
...
Siehe: pyxen.world.all()
Marker-Components
e.alive = True
Marker speichern keine Daten — sie zeigen nur Vorhandensein an. Abfragen funktionieren wie bei normalen Components:
for e in world.all("alive"):
...
Auf Component-Felder zugreifen
e.cell.row
e.cell.col
e.cell.row = 5
Unterstützte Feldtypen
| Python-Typ | Gespeichert als |
|---|---|
int | 32-Bit-Ganzzahl |
float | 32-Bit-Gleitkommazahl |
bool | Boolean |
str | Fester String (max. 31 Zeichen) |
Entity | Entity-Referenz |
Ungültige Typen lösen aus:
TypeError: invalid value type in dict
Schema-Regeln
- Maximale Komponentengröße: 256 Bytes
- Strings maximal: 31 Zeichen
- Dict-Schlüssel müssen Strings sein
- Keine neuen Felder nach Schema-Erstellung möglich
e.cell = {'row': 0}
e.cell = {'row': 0, 'new_field': 5}
ValueError: cannot create new fields after schema is complete
Es ist erlaubt, Felder bei nachfolgenden Zuweisungen wegzulassen — sie werden auf 0, 0.0, False, "" usw. gesetzt.
Auf eine Komponente prüfen
e.has("cell")
Gibt True zurück, wenn das Entity die Komponente hat, sonst False.
Das funktioniert sowohl für eigene als auch eingebaute Komponentennamen:
e.has("sprite") # True wenn das Entity ein Sprite hat
e.has("body") # True wenn das Entity einen Grid-Body hat
Nachkommen abfragen
entity.all(*components, without=(), include_self=False)
Gibt einen Iterator über alle Nachkommen des Entity zurück (Tiefensuche durch die Szenengraph-Hierarchie), die dem gegebenen Komponentenfilter entsprechen.
Funktioniert genau wie world.all(), aber beschränkt auf einen Teilbaum statt die gesamte Welt.
# Alle Nachkommen mit "enemy"-Komponente
for e in parent.all("enemy"):
...
# Mit Ausschluss
for e in parent.all("enemy", without=("boss",)):
...
# Das Eltern-Entity selbst einschließen
for e in parent.all("tag", include_self=True):
...
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
*components | str | — | Erforderliche Komponentennamen |
without | tuple | () | Auszuschließende Komponentennamen |
include_self | bool | False | Ob das Entity selbst eingeschlossen wird |
Sowohl eingebaute als auch eigene Komponentennamen werden unterstützt.
Components entfernen
Entferne eine Komponente von einem Entity mit del oder durch Zuweisung von None:
# Beide sind gleichwertig:
del entity.health
entity.health = None
Nach dem Entfernen gibt entity.has("health") False zurück und das Entity wird nicht mehr in Abfragen für diese Komponente gefunden.
e = world.spawn()
e.health = {'hp': 100}
del e.health
e.has("health") # False
# world.all("health") enthält e nicht mehr
Du kannst eine Komponente nach dem Entfernen erneut hinzufügen:
del e.health
e.health = {'hp': 50} # funktioniert problemlos
Eingebaute Components
Alle eingebauten Components können entfernt werden:
del e.sprite # löscht Sprite-Daten
del e.body # löscht Physics-Body
del e.camera # entfernt Kamera
del e.text # entfernt Text
del e.sound # entfernt Sound
del e.music # entfernt Musik
del e.map # entfernt Grid-Map
Sprite und Body werden auf Null initialisiert (das Entity behält den Speicher, aber die Daten sind leer). Camera, Text, Sound, Music und Map werden vollständig gelöscht.
Marker
e.enemy = True
del e.enemy # oder: e.enemy = None
e.has("enemy") # False
Entity-Lebenszyklus
- Erstellt mit
world.spawn() - Geändert durch Komponentenzuweisung
- Components entfernt mit
deloder= None - Zerstört mit
world.destroy()
Siehe: pyxen.world.spawn() | pyxen.world.destroy()