In diesem Kapitel lernst du, wie du Pixelgrafiken programmieren kannst. Dazu installieren wir das Paket »Pixelflow Canvas« und erstellen ein erstes Bild mit einer hügeligen Wiese aus Bézierkurven und einem Regenbogen aus konzentrischen Kreisen.
Stelle zuerst sicher, dass du keinen Ordner geöffnet hast. Um sicherzugehen, drücke einfach den Shortcut für »Ordner schließen«: StrgK und dann F. Dein Workspace sollte jetzt ungefähr so aussehen:
Falls du es noch nicht getan hast, musst du zuerst eine Erweiterung für Visual Studio Code installieren. Anschließend installieren wir ein Rubygem, das uns das Programmieren von Pixelgrafiken ermöglicht.
Um Pixelgrafiken im Workspace programmieren zu können, benötigen wir die Erweiterung »Pixelflow Canvas«. Klicke dazu auf das Extensions-Symbol in der Seitenleiste und suche nach »Pixelflow Canvas«. Klicke auf »Install«, um die Erweiterung zu installieren.
Um bequem von Ruby Befehle an das Canvas schicken zu können, benötigen wir das Rubygem »pixelflow_canvas«. Öffne das Terminal, indem du den Shortcut StrgJ drückst. Dein Workspace sollte jetzt ungefähr so aussehen:
Installiere es, indem du folgenden Befehl in das Terminal eingibst:
gem install pixelflow_canvas
Wähle im Menü links oben »File« / »New Text File« (oder drücke StrgAltN), um eine neue Datei anzulegen:
Schreibe den folgenden Code in die Datei:
require 'pixelflow_canvas' Pixelflow::Canvas.new(320, 180, :palette) do set_pixel(160, 90, 10) end
Da Visual Studio Code noch nicht weiß, dass es sich um Ruby-Code handelt, sieht dein Code noch etwas farblos aus:
Speichere die Datei unter dem Dateinamen rainbow.rb
, indem du StrgS drückst und den Dateinamen eingibst.
Dein Programm sollte jetzt ungefähr so aussehen:
Bevor wir das Programm ausführen können, müssen wir das Pixelflow Canvas öffnen. Drücke dazu StrgShiftP oder F1 und gib dann »Show Pixelflow Canvas« ein.
Du solltest jetzt ein neues Panel sehen, in dem das Pixelflow Canvas angezeigt wird:
Führe das Programm aus, indem du im Terminal ruby rainbow.rb
eingibst. Du solltest nun einen einzelnen, grünen Pixel in der Mitte der Zeichenfläche sehen:
Schauen wir uns den Code genauer an:
require 'pixelflow_canvas' Pixelflow::Canvas.new(320, 180, :palette) do set_pixel(160, 90, 10) end
require 'pixelflow_canvas'
lädt das Rubygem »pixelflow_canvas«.Pixelflow::Canvas.new(320, 180, :palette)
erstellt ein neues Canvas mit einer Breite von 320 Pixeln und einer Höhe von 180 Pixeln. Der dritte Parameter :palette
gibt an, dass wir eine Palette verwenden wollen.do
/ end
-Block enthält die Befehle, die auf das Canvas angewendet werden sollen.set_pixel(160, 90, 10)
setzt den Pixel an der Position (160, 90) auf die Farbe 10.Der Ursprung der Zeichenfläche ist oben links, der x-Wert nimmt nach rechts zu und der y-Wert nach unten. Da wir eine Palette verwenden, geben wir Farben einfach als Zahl von 0 bis 255 an. Welche Farbe sich hinter welcher Zahl verbirgt, ist in der Palette definiert.
Da standardmäßig die VGA-Palette verwendet wird, entspricht die Farbe 10 einem hellen Grün.
Hier findest du eine Übersicht über alle Farben der Standard-VGA-Palette.
:palette
durch :rgb
.
Anschließend musst du alle Farben als Tripel von rot, grün und blau im Bereich von 0 bis 255 angeben. Der historische
Hintergrund für die Verwendung von Paletten rührt daher, dass man so mit weniger Speicherplatz auskam (während ein RGB-Pixel
3 Bytes benötigt, benötigt ein Pixel mit Palette nur 1 Byte, da die Farbe nur als Index in der Palette gespeichert wird).
Heute ist das eigentlich nicht mehr nötig, aber es kann trotzdem von Vorteil sein, eine Palette zu verwenden, da du so eine
einheitliche Farbgebung hast und nicht jedes Mal die passenden RGB-Werte heraussuchen musst.
Die Standard-VGA-Palette ist nicht die einzige Palette, die du verwenden kannst. Du kannst auch eine andere Palette wählen oder sogar deine eigene Palette definieren. Eine Übersicht über alle verfügbaren Paletten findest du hier. Da wir eine Wiese mit Regenbogen zeichnen möchten, wählen wir die »zughy_32«-Palette:
Verändere den Code wie folgt und führe ihn erneut aus:
require 'pixelflow_canvas' Pixelflow::Canvas.new(320, 180, :palette) do set_predefined_palette(:zughy_32) set_pixel(160, 90, 10) end
Führe das Programm aus, indem du im Terminal ruby rainbow.rb
eingibst (du kannst auch einfach den letzten Befehl wiederholen, indem du ↑ und Enter drückst).
Du solltest jetzt sehen, dass sich die Farben geändert haben – der Hintergrund ist nicht mehr schwarz, weil die Farbe 0 nun ein dunkles Lila ist und die Farbe 10 ist nun ein dunkles Türkis.
Lösche den set_pixel
-Befehl und füge stattdessen den folgenden Code ein:
set_color(16) fill_rect(0, 0, 319, 179)
Wir füllen die gesamte Zeichenfläche mit der Farbe 16 (hellblau), indem wir den Befehl fill_rect
verwenden. Dieser Befehlt benötigt vier Parameter: die x- und y-Koordinaten der oberen linken Ecke des Rechtecks und die x- und y-Koordinaten der unteren rechten Ecke des Rechtecks.
Dein Bild sollte jetzt so aussehen:
Um eine hügelige Wiese zu zeichnen, werden wir keine geraden Linien, sondern Bézierkurven verwenden. Eine Bézierkurve wird durch eine Reihe von Punkten definiert, die die Kurve beeinflussen. Wir können hier zwei Arten von Bézierkurven verwenden: eine quadratische Bézierkurve (mit drei Punkten) und eine kubische Bézierkurve (mit vier Punkten).
Du kannst hier interaktiv die Punkte der Bézierkurven verschieben, um zu verstehen, wie Bézierkurven funktionieren:
Wir können also z. B. eine kubische Bézierkurve verwenden, um eine hügelige Wiese zu zeichnen. Dabei sind der erste und der letzte Punkt die Endpunkte der Kurve, während die beiden mittleren Punkte die Kontrollpunkte sind, die die Form der Kurve beeinflussen. Wir zeichnen drei Kurven mit verschiedenen Grüntönen, um eine hügelige Wiese darzustellen. Füge den folgenden Code hinzu:
set_color(7) draw_cubic_bezier(0, 120, 100, 140, 200, 100, 320, 120) set_color(8) draw_cubic_bezier(0, 140, 100, 150, 200, 110, 320, 140) set_color(9) draw_cubic_bezier(0, 170, 110, 140, 220, 140, 320, 170)
Dein Bild sollte jetzt so aussehen:
Um den Hügel mit Farbe zu füllen, können wir den Befehl flood_fill
verwenden. Dieser Befehl füllt eine Fläche mit einer bestimmten Farbe, beginnend von einem bestimmten Punkt. Füge den folgenden Code hinzu:
set_color(7) flood_fill(0, 130)
Der Punkt an der Stelle (0, 130) liegt zwischen den oberen beiden Kurven, und nun wird der Bereich zwischen diesen beiden Kurven mit der Farbe 7 (hellgrün) gefüllt. Dein Bild sollte danach so aussehen:
Füge anschließend die folgenden Zeilen hinzu, um die restlichen Flächen zu füllen:
set_color(8) flood_fill(0, 150) set_color(9) flood_fill(0, 179)
Dein Bild sollte jetzt so aussehen:
Wir wollen nun einen Regenbogen zeichnen, der aus ineinander gelegten Kreisen besteht. Würden wir die Kreise einfach so zeichnen, würden sie den Rasen überdecken. Um das zu verhindern, können wir eine Maske verwenden. Eine Maske ist ein Bereich, in dem wir zeichnen können, ohne den Rest des Bildes zu beeinflussen. Wir definieren uns eine Maske, die nur die Hintergrundfarbe 16 (hellblau) umfasst, und zeichnen dann die Kreise.
Mit dem Befehl set_mask
können wir eine Maske definieren. Innerhalb des do
/ end
-Blocks können wir dann definieren, was alles zur Maske gehört. Mit dem Befehl add_color(16)
geben wir an, dass alle Pixel, die momentan die Farbe 16 haben, zur Maske gehören. Alle anderen Pixel werden durch die nachfolgenden Zeichenbefehle nicht beeinflusst. Füge den folgenden Code hinzu:
set_mask do add_color(16) end
Nun können wir die Kreise zeichnen. Wir verwenden gefüllte Kreise und zeichnen sie von außen nach innen. Wir beginnen mit einem Radius von 125 Pixeln und verringern ihn dann um 5 Pixel für jeden Kreis, während wir die Farben rot (28), orange (27), gelb (26), grün (8), indigo (19), violett (23) und himmelblau (16) durchlaufen. Füge den folgenden Code hinzu:
r = 125 [28, 27, 26, 8, 19, 23, 16].each do |color| set_color(color) fill_circle(160, 180, r) r -= 5 end
Dein Bild sollte anschließend so aussehen:
Für den Himmel müssen wir die Maske erneuern, da sie nach wie vor gilt und somit folgende Zeichenbefehle auch den Regenbogen überdecken würden. Füge den folgenden Code ein:
set_mask do add_color(16) end
Im Bereich von 16 bis 20 gibt es ein paar schöne Blautöne, die wir für den Himmel verwenden können. Wir gehen zeilenweise von oben nach unten durch das Bild und wählen eine Farbe aus diesem Spektrum (mit etwas zufälliger Variation) und zeichnen damit eine horizontale Linie von links nach rechts. Füge den folgenden Code hinzu:
(0...180).each do |y| set_color(20 - 3.5 * (y / 179.0) - rand() * 1.5) draw_line(0, y, 319, y) end
Anschließend entfernen wir die Maske wieder:
remove_mask()
Das fertige Bild sollte nun so aussehen:
Um das Bild zu speichern, füge den folgenden Code hinzu:
save_as_png('rainbow.png')
Hier siehst du noch einmal den gesamten Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
require 'pixelflow_canvas.rb' # Wir erstellen ein neues Pixelflow-Canvas mit einer # Größe von 320x180 Pixeln und wir möchten eine # Palette verwenden. canvas = Pixelflow::Canvas.new(320, 180, :palette) do # Wir wählen die Zughy-32-Palette set_predefined_palette(:zughy_32) # Hintergrund set_color(16) fill_rect(0, 0, 319, 179) # drei grüne Graskurven set_color(7) draw_cubic_bezier(0, 120, 100, 140, 200, 100, 320, 120) set_color(8) draw_cubic_bezier(0, 140, 100, 150, 200, 110, 320, 140) set_color(9) draw_cubic_bezier(0, 170, 110, 140, 220, 140, 320, 170) # Grasflächen füllen set_color(7) flood_fill(0, 130) set_color(8) flood_fill(0, 150) set_color(9) flood_fill(0, 179) # Maske setzen: nur noch Pixel setzen, # die die Farbe 16 (Hintergrund) haben set_mask do add_color(16) end # Regenbogen zeichnen r = 125 [28, 27, 26, 8, 19, 23, 16].each do |color| set_color(color) fill_circle(160, 180, r) r -= 5 end # Maske erneuern: nur noch Pixel setzen, # die jetzt die Farbe 16 (Hintergrund) haben set_mask do add_color(16) end # Himmel zeichnen: Verlauf von dunkelblau # nach hellblau (0...180).each do |y| set_color(20 - 3.5 * (y / 179.0) - rand() * 1.5) draw_line(0, y, 319, y) end # Maske aufheben remove_mask() # Bild speichern save_as_png("rainbow.png") end |
In diesem Kapitel hast du gesehen, wie du Pixelgrafiken mit dem Pixelflow Canvas programmieren kannst. Du hast gesehen, wie man komplexe Szenen aus einfachen Formen zusammensetzen kann und anschließend das Bild speichern kann. Eine Übersicht über alle Befehle findest du in der Dokumentation des Pixelflow Canvas.