pyxen.draw
Das Modul draw zeichnet Formen Frame für Frame direkt auf den Bildschirm. Rufe es aus
update() auf: Was du zeichnest, gehört zu diesem Frame, und der nächste beginnt leer — du
zeichnest es also in jedem Frame erneut, solange es zu sehen sein soll.
from pyxen import *
def update():
draw.circle(64, 64, 20, fill=(1, 0.2, 0.3, 1))
draw.line(0, 0, 128, 128, color=(1, 1, 1, 1))
Es entsteht nichts: keine Entität, die du behalten, und nichts, das du zerstören müsstest. Der Zeitreise-Debugger behält, was jeder Frame gezeichnet hat: Wenn du pausierst und durch die Frames zurückgehst, zeigt jeder Frame seine Formen so wie im laufenden Spiel.
draw oder eine Shape-Komponente?
Pyxen bietet dieselben Primitive zweimal an. Auf dem Bildschirm sind sie identisch und unterscheiden sich nur in ihrer Lebensdauer.
| Shape-Komponente | draw | |
|---|---|---|
| Lebensdauer | Lebt, bis du die Entität zerstörst | Jeder Frame zeichnet es neu |
| Position | Position, Rotation und Skalierung der Entität | Weltkoordinaten, die du übergibst |
| Kosten | Eine vollständige Entität: Transform, Ebene, Komponentenspeicher | Ein paar Quads im Frame-Puffer |
| Debugger | Als Entität aufgelistet und inspiziert | In jedem Frame zu sehen, zu dem du zurückgehst |
| Gut für | Spielobjekte — Schiffe, Wände, feste Oberfläche | Bilder vom Zustand deines Spiels: Spuren, Overlays, Balken |
Nimm Shape, wenn das Ding etwas in deinem Spiel ist. Nimm draw, wenn du ein Bild von
einem Zustand malst, den deine Entitäten schon halten: Behalte diesen Zustand in Entitäten und
Komponenten, wo der Debugger und der Inspektor ihn sehen, und zeichne ihn in jedem Frame.
Farben
Jedes Farbargument nimmt ein (r, g, b, a)-Tupel mit Komponenten von 0.0 bis 1.0 oder
ein Color.
draw.rect(10, 10, 40, 20, fill=(1, 0, 0, 1)) # deckendes Rot
draw.rect(10, 40, 40, 20, fill=(1, 0, 0, 0.35)) # Rot mit 35 %
Die gefüllten Formen zeichnen standardmäßig nichts. draw.rect, draw.triangle und
draw.circle starten mit vollständig transparentem fill und stroke, ein Aufruf ohne
beides ist also unsichtbar — das ist die häufigste Überraschung bei diesem Modul.
draw.line und draw.polyline verwenden dagegen deckendes Weiß und sind immer zu sehen.
Funktionen
draw.line(x1, y1, x2, y2, color=(1,1,1,1), width=1)
Eine gerade Linie zwischen zwei Punkten.
| Argument | Typ | Beschreibung |
|---|---|---|
x1, y1 | float | Startpunkt, in Weltkoordinaten. |
x2, y2 | float | Endpunkt. |
color | Tupel | Linienfarbe. Standard ist deckendes Weiß. |
width | float | Linienstärke in Pixeln. Standard ist 1. |
def update():
draw.line(0, 64, 128, 64, color=(0.3, 1, 0.5, 1), width=2)
draw.polyline(points, color=(1,1,1,1), width=1, closed=False)
Eine Folge verbundener Liniensegmente.
| Argument | Typ | Beschreibung |
|---|---|---|
points | Tupel oder FloatBuffer | Flache Folge (x1, y1, x2, y2, …) — keine Liste von Paaren. |
color | Tupel | Linienfarbe. Standard ist deckendes Weiß. |
width | float | Linienstärke in Pixeln. |
closed | bool | Bei True wird der letzte Punkt mit dem ersten verbunden. |
def update():
draw.polyline((10, 10, 40, 60, 80, 20, 110, 70),
color=(1, 0.8, 0.2, 1), width=2)
Die Punkte liegen bewusst flach: genau diese Form hat ein FloatBuffer bereits, sodass ein
einmal berechneter Pfad in jedem Frame unverändert an draw.polyline übergeben werden kann,
ohne ihn neu aufzubauen.
draw.rect(x, y, width, height, fill=None, stroke=None, stroke_width=1)
Ein achsenparalleles Rechteck. x, y ist seine Ecke, nicht sein Mittelpunkt.
| Argument | Typ | Beschreibung |
|---|---|---|
x, y | float | Position der Ecke. |
width, height | float | Größe in Pixeln. |
fill | Tupel | Innenfarbe. Weglassen für keine Füllung. |
stroke | Tupel | Umrissfarbe. Weglassen für keinen Umriss. |
stroke_width | float | Stärke des Umrisses. Standard ist 1. |
def update():
# Eine Lebensleiste: dunkler Hintergrund, kräftige Füllung, dünner Umriss.
draw.rect(4, 4, 60, 6, fill=(0.1, 0.1, 0.1, 1))
draw.rect(4, 4, 60 * health / max_health, 6, fill=(0.2, 1, 0.4, 1))
draw.rect(4, 4, 60, 6, stroke=(1, 1, 1, 0.5))
draw.triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)
Ein Dreieck durch drei Punkte.
| Argument | Typ | Beschreibung |
|---|---|---|
x1, y1, x2, y2, x3, y3 | float | Die drei Ecken. |
fill | Tupel | Innenfarbe. Weglassen für keine Füllung. |
stroke | Tupel | Umrissfarbe. Weglassen für keinen Umriss. |
stroke_width | float | Stärke des Umrisses. |
def update():
draw.triangle(64, 20, 84, 60, 44, 60, fill=(1, 1, 0.3, 1))
draw.circle(x, y, radius, fill=None, stroke=None, stroke_width=1, segments=12)
Ein Kreis um einen Mittelpunkt.
| Argument | Typ | Beschreibung |
|---|---|---|
x, y | float | Position des Mittelpunkts. |
radius | float | Radius in Pixeln. |
fill | Tupel | Innenfarbe. Weglassen für keine Füllung. |
stroke | Tupel | Umrissfarbe. Weglassen für keinen Umriss. |
stroke_width | float | Stärke des Umrisses. |
segments | int | Gerade Segmente, die die Kurve annähern. Standard ist 12. |
Ein Kreis ist in Wahrheit ein Vieleck. Zwölf Segmente wirken bei kleinen Größen rund; erhöhe den Wert für große Kreise und senke ihn, wenn du ein sichtbares Vieleck willst.
def update():
draw.circle(64, 64, 24, fill=(0.2, 0.4, 1, 1), segments=32)
draw.circle(64, 64, 30, stroke=(1, 1, 1, 0.4), segments=32)
Hinweise
draw-Aufrufe gehören inupdate(). Ausstart()zeichnen sie ein einziges Frame und sind dann weg.- Gezeichnet wird in Weltkoordinaten, die Kamera bewegt das Gezeichnete also mit. Für eine
Oberfläche, die stehen bleibt, zeichne relativ zu
cameraoder lass sie auf einer unbewegten Kamera. - Alles, was in einem Frame gezeichnet wird, liegt über den Sprites dieses Frames.