Sprites & Rendering
Pyxen rendert dein Spiel mit einem Metal-gestützten 2D-Renderer. Alles, was auf dem Bildschirm sichtbar ist, ist eine Entität mit einer Sprite-Komponente.
Sprites
Ein Sprite sagt der Engine, was sie für eine Entität zeichnen soll. Du erstellst eins, indem du ein Bild aus deinem Projekt referenzierst:
player = world.spawn(sprite=Sprite("hero"))
Die Zeichenkette "hero" bezieht sich auf ein Bild namens hero in den Assets deines Projekts.
Kachel-Sheets
Die meisten Spiele verwenden Kachel-Sheets — ein einzelnes Bild mit vielen Frames oder Kacheln, die in einem Raster angeordnet sind. Du wählst einen Bereich des Bildes mit dem tile-Parameter:
Sprite("characters", tile=(0, 0, 16, 16)) # erste Kachel
Sprite("characters", tile=(16, 0, 16, 16)) # zweite Kachel
Sprite("characters", tile=(0, 16, 16, 16)) # Kachel in zweiter Reihe
Die vier Werte sind (x, y, Breite, Höhe) in Pixeln, gemessen von der oberen linken Ecke des Bildes.
Sprite-Animationen
Wenn du benannte Animationen im Sprite-Editor erstellst, kannst du sie direkt abspielen:
player = world.spawn(
sprite=Sprite("hero", animation="walk"),
x=100, y=50
)
Die Engine liest die Frame-Sequenz und FPS aus den Metadaten des Sprites und wechselt die Frames automatisch. Um Animationen zu wechseln, weise ein neues Sprite zu:
player.sprite = Sprite("hero", animation="jump")
Für einmalige Animationen (wie ein Angriff oder Tod) setze loop=False und prüfe, wann sie fertig ist:
player.sprite = Sprite("hero", animation="attack", loop=False)
def update():
if player.animation and player.animation.finished:
player.sprite = Sprite("hero", animation="idle")
Die e.animation-Komponente gibt dir schreibgeschützten Zugriff auf den aktuellen Zustand: .name, .frame, .playing, .finished. Siehe die Entity-Referenz für Details.
Du kannst auch manuell animieren, indem du die Kachel in jedem Frame änderst:
def update():
frame = time.frame % 4
player.sprite = Sprite("hero", tile=(frame * 16, 0, 16, 16))
Pivot-Punkt
Standardmäßig wird ein Sprite von seiner oberen linken Ecke gezeichnet. Du kannst den Pivot-Punkt ändern, um zu steuern, wo das Sprite verankert ist:
Sprite("hero", tile=(0, 0, 16, 16), pivot=(8, 8))
Dies zentriert das Sprite auf der Position der Entität. Der Pivot ist in Pixelkoordinaten relativ zur Kachel. Den Pivot auf die Mitte der Kachel zu setzen ist die häufigste Wahl — es lässt Rotation und Skalierung intuitiv funktionieren.
Farbtönung
Du kannst das Sprite jeder Entität tönen, indem du ihre Farbe setzt:
player.color = (1.0, 0.5, 0.5, 1.0) # rötliche Tönung
Farbe ist ein RGBA-Tupel mit Werten von 0.0 bis 1.0. Weiß (1, 1, 1, 1) bedeutet keine Tönung. Du kannst den Alpha-Kanal für Transparenz verwenden:
ghost.color = (1, 1, 1, 0.5) # 50% transparent
Du kannst Farbe und Alpha mit Tweens flüssig animieren:
ghost.tween("alpha", to=0, duration=0.5, ease="out_quad") # ausblenden
Für kontinuierliche Effekte wie Pulsieren oder Flackern verwende Animationen:
ghost.animate("alpha", by=0.3, center=0.7, speed=4.0) # flackern
Kamera
Die Kamera steuert, welcher Teil der Welt sichtbar ist. Erstelle eine, indem du eine Entität mit einer Camera-Komponente erzeugst:
cam = world.spawn(camera=Camera(), x=160, y=90)
Bewege die Kamera, um dem Spieler zu folgen:
def update():
cam.x = player.x
cam.y = player.y
Die Kamera unterstützt Zoom:
cam.camera.zoom = 2.0 # 2-fach hineinzoomen
Du kannst den Zoom mit einem Tween flüssig animieren:
cam.tween("zoom", to=2.0, duration=0.5, ease="out_quad")
Auflösung
Pyxen-Spiele laufen mit einer Standardauflösung von 320x180 Pixeln. Das ist eine bewusste Wahl — niedrige Auflösung lässt Pixel Art scharf aussehen und hält das Rendering schnell. Die Engine skaliert die Ausgabe, um den Bildschirm zu füllen.
Text
Die Text-Komponente rendert Bitmap-Text. Erstelle ein Text-Entity so:
label = world.spawn(text=Text("Hello, world!"))
Standardmäßig verwendet Text die eingebaute Pixel-Schriftart. Um eine eigene Schriftart zu verwenden, die mit dem Schriftart-Editor erstellt wurde:
title = world.spawn(text=Text("Game Over", font="myfont"))
Aktualisiere den Text zur Laufzeit, indem du die text-Eigenschaft änderst:
def update():
score_label.text = Text(f"Score: {score}")
Siehe die Text-Referenz für die vollständige API.
Zeichenreihenfolge
Entitäten werden in dieser Reihenfolge gezeichnet:
- Ebene — niedrigere Ebenen werden zuerst gezeichnet (Ebene 0 hinter Ebene 1)
- Tiefe — innerhalb einer Ebene, bestimmt durch die Position im Szenengraph
- Entitäten ohne Sprites werden nicht gezeichnet, existieren aber trotzdem in der Welt
Siehe Szenengraph für mehr über Ebenen und Tiefe.