Geometrische Muster in p5.js
Zufällige geometrische Mustergenerierung
Ziel der Übung
In dieser Übung programmierst du ein zufällig generiertes Muster in einem 800x800px Canvas. Verschiedene geometrische Formen werden dabei in Segmente unterteilt und miteinander kombiniert. Durch das Drücken der Leertaste wird ein neues Muster erzeugt und mit den Pfeiltasten kann die Farbpalette gewechselt werden.
p5.js
Wir verwenden für diese Übung die JavaScript Bibliothek p5.js. Du kannst den online Editor verwenden, um damit Programme zu bauen. Alternativ kann die Bibliothek auch in deine eigene Webseite integriert oder mit einem beliebigen Quellcode-Editor bearbeitet werden.
Öffne zum Starten den p5.js Editor.
Dort wird dir folgender Code angezeigt:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
}
Diese beiden Funktionen sind das Skelett deines p5.js-Programms:
Die setup()
-Funktion wird einmalig ausgeführt, wenn das Programm zum ersten Mal geladen wird. Hier kannst du die Zeichenfläche erstellen, die p5.js zum Anzeigen von Grafiken verwendet. Textformatierung und die Farben für das Zeichnen können hier ebenfalls festgelegt werden.
Die draw()
-Funktion wiederholt sich, solange das Programm läuft. Es steuert, wie sich das Programm im Laufe der Zeit entwickeln soll, einschließlich Animationen und anderer dynamischer Elemente.
Falls du das erste Mal mit p5.js arbeitest, wirf ebenfalls einen Blick auf die get started Anleitung von p5.js.
Setup()-Funktion
Zunächst definieren wir die Größe des Canvas auf 800x800px. Die Funktion noLoop()
stoppt die draw()
-Funktion nach erstmaligem Durchlauf. Somit wird gewährleistet, dass das generierte Muster nicht sofort von einem Neuen überschrieben wird. noStroke()
deaktiviert das Zeichnen der Kontur.
function setup() {
createCanvas(800, 800);
noLoop();
noStroke();
}
Farbpaletten
Nun geht es um die Auswahl der Farbwerte bzw. -paletten, die im weiteren Verlauf auf die Formen angewandt werden. Hierzu wird ein zweidimensionales array
über der setup()
-Funktion definiert, welches mit Hexadezimalwerten gefüllt wird. Dabei ist die Anzahl der Farben und Paletten variabel. Du kannst die vorgegeben Werte benutzen oder selbst eigene Farbpaletten entwerfen.
//Definition der Farbpaletten
let paletten = [
["#0B090A", "#161A1D", "#660708", "#A4161A", "#BA181B", "#E5383B", "#B1A7A6", "D3D3D3", "#F5F3F4", "#FFFFFF"],
["#800016", "#a0001c", "#c00021", "#ff002b", "#ffffff", "#407ba7", "#004e89", "002962", "#00043a"],
["#03071e", "#370617", "#6a040f", "#9d0208", "#d00000", "#dc2f02", "#e85d04", "f48c06", "#faa307", "#ffba08"],
["#132a13", "#31572c", "#4f772d", "#90a955", "#ecf39e", "#edf0c6", "#f7f8ec"]
];
Darunter wird die Anzahl der Segmente einer Reihe bzw. Spalte definiert sowie eine Zählvariable, die zum Wechseln der Farbpaletten benötigt wird.
let segmentAnz = 5; //Anzahl der Segmente in x und y Richtung
let counter = 0; //Zählvariable für die Palettenauswahl
makeTile()-Funktion
Als Nächstes legen wir eine neue Funktion an, die in den Segmenten zufällige geometrische Formen erstellt. Mit Hilfe der shuffel()
-Funktion werden die Farben in einer Palette willkürlich angeordnet, sodass der darauffolgenden fill()
-Funktion ein zufälliger Farbwert aus der Palette übergeben wird. Mit dieser Farbe wird ein Quadrat erzeugt, welches das erste Segment ausfüllt.
Nun werden diese Quadrate mit weiteren geometrischen Formen gefüllt. Durch die push()
-Funktion können die momentanen Zeichenstileinstellungen gespeichert werden, während die pop()
-Funktion diese wiederherstellt. Dadurch lassen sich zwischen diesen Funktionen neue temporäre Zeichenstile definieren. Das gewährleistet, dass die erzeugten geometrischen Formen nicht die gleiche Farbe annehmen wie das Segment.
Die neu erstellten Formen werden mit der translate()
-Funktion um die Hälfte des Segments s
verschoben und dann mittels der rotate()
-Funktion um einen zufälligen Wert gedreht. Damit der Rotationswert nicht immer derselbe ist, wird die random()
-Funktion verwendet.
In der Variable r
wird eine Zufallszahl von 0 bis einschließlich 3 definiert, diese wird in der darauf folgenden if()
-Abfrage verwendet, um die geometrische Form zu bestimmen. Dabei werden die Funktionen arc()
, rect()
und triangle()
verwendet, um Kurven, Rechtecke oder Dreiecke zu generieren.
//Generierung zufälliger geometrischer Formen
function makeTile(x, y, s) {
shuffle(paletten[counter], true);
fill(paletten[counter][0]);
square(x, y, s);
push();
translate(x + s / 2, y + s / 2);
rotate(random([0, PI / 2, PI, 3 * PI / 2]));
fill(paletten[counter][1]);
let r = floor(random(4));
if (r == 0) {
arc(-s / 2, 0, s, s, -PI / 2, PI / 2);
} else if (r == 1) {
rect(-s / 2, -s / 2, s / 2, s);
} else if (r == 2) {
triangle(-s / 2, -s / 2, s / 2, -s / 2, -s / 2, s / 2);
}
pop();
}
draw()-Funktion
Nun wird neben der setup()
-Funktion ebenfalls die draw()
-Funktion angepasst. Dabei wird als Erstes die Variable s
definiert, welche die Breite der Segmente angibt. In einer verschachtelten for
-Schleife werden spaltenweise einzelne Segmente generiert. Die random()
-Funktion in der if
-Abfrage entscheidet dabei, ob das Segment weiter untergliedert wird. Hierzu werden die Variablen x
, y
und s
an die makeTile()
-Funktion übergeben.
function draw() {
let s = width / segmentAnz; //s ist die Laenge der einzelnen Segmente
//Generierung der einzelnen Segmente
for (let x = 0; x < width; x += s) {
for (let y = 0; y < height; y += s) {
//Segmentunterteilung
if (random() < 1 / 2) {
makeTile(x, y, s / 2);
makeTile(x + s / 2, y, s / 2);
makeTile(x, y + s / 2, s / 2);
makeTile(x + s / 2, y + s / 2, s / 2);
} else {
makeTile(x, y, s);
}
}
}
}
keyPressed()-Funktion
Um per Tastatur ein neues Muster zu generieren oder die Farbpalette zu wechseln, wird die keyPressed()
-Funktion erstellt. In einer verschachtelten if
-Abfrage wird überprüft, ob die Leertaste, linke Pfeiltaste oder rechte Pfeiltaste gedrückt ist. Sobald das der Fall ist, wird am Ende der Abfrage die redraw()
-Funktion aufgerufen, welche ein neues Muster generiert. Die Pfeiltasten wechseln zusätzlich noch die Farbpalette mithilfe der zuvor definierten Zählvariable counter
.
//Ermöglicht das Wechseln der Farbpalette und die Neugenerierung mit der Tastatur
function keyPressed() {
if (key == (" ") || keyIsDown(LEFT_ARROW) || keyIsDown(RIGHT_ARROW)) {
if (keyIsDown(LEFT_ARROW) && counter > 0) {
counter--;
} else if (keyIsDown(LEFT_ARROW) && counter == 0) {
counter = paletten.length - 1;
} else if (keyIsDown(RIGHT_ARROW) && counter < paletten.length - 1) {
counter++;
} else if (keyIsDown(RIGHT_ARROW) && counter == paletten.length - 1) {
counter = 0;
}
redraw();
}
Variationen
Die generierten Muster können ganz leicht durch das Anpassen der Variablen abgeändert werden (z.B. seqmentAnz = 80
). Durch das Arbeiten mit dem Code lernt man am besten. Probiere es einfach selbst aus!
Quellcode
Hier findest du den gesamten Quellcode.
Das Tutorial wurde inspiriert von den Werken Roni Kaufmans.