Variablen und Animationen

Erstelle deine erste animierte Landschaft mit p5.js

Tutorial für Einsteiger in die Animation

In diesem Tutorial lernst du, wie du mit Variablen Animationen erstellst. Du wirst eine animierte Landschaft bauen mit bewegten Wolken, wachsenden Bäumen und zufälligen Sternschnuppen!

Bisher hatten alle Objekte meistens feste Werte:

function setup() { createCanvas(600, 400); } function draw() { //gelber Hintergrund background(255,255,0); // circle(x, y, radius) circle(300, 200, 100); }

Im Folgenden wollen wir vier veränderliche Größen kennenlernen, sogenannte Variablen, mit denen man auch die Position, die Farbe oder die Größe von Objekten ändern kann:

Lassen wir uns diese Werte einmal ausgeben:

function setup() { createCanvas(600, 400); } function draw() { background(220); // hellgrauer Hintergrund textSize(20); // Schriftgröße 20 text("mouseX: " + mouseX, 10, 20); // Text mit dem mouseX-Wert text("mouseY: " + mouseY, 10, 40); // Text mit dem mouseY-Wert text("key: " + key, 10, 60); // Text mit dem key-Wert text("keyIsPressed: " + keyIsPressed, 10, 80); // Text mit dem keyIsPressed-Wert text("frameCount: " + frameCount, 10, 100); // Text mit dem frameCount-Wert }

1. Interaktivität durch mouseX und mouseY

In dem folgenden Beispiel kann man mit dem Mauszeiger zeichnen:

function setup() { createCanvas(600, 400); //einmalig den Hintergrund schwarz setzen background(0); // Kurzform für background(0,0,0) } function draw() { //einen kleinen weißen Punkt an der Mausposition zeichnen fill("white"); noStroke(); // kein Rand zeichnen // ACHTUNG: Jetzt nutzen wir die Variablen mouseX und mouseY, // um einen Punkt an der Mausposition zu zeichnen. circle(mouseX, mouseY, 10); }
  • Modifiziere den obigen Kreis so, dass er sich mit der Maus bewegt (vielleicht sogar entgegengesetzt) und dabei seine Größe ändert.
  • Wie kann man die Bewegung des Kreises verlangsamen oder beschleunigen?

2. Interaktivität durch frameCount

Alles was in draw() steht, wird 60 mal pro Sekunde wiederholt, um Animationen zu ermöglichen: Wie in einem Daumenkino werden Bilder nacheinander gezeigt, um ein Gefühl von Bewegung zu erzeugen:

Die Seitenzahlen in diesem Daumenkino entspricht der Variable frameCount.

Möchte man die Animation beschleunigen oder verlangsamen, kann man die Variable frameRate() verwenden, z.B. ist frameRate(30) die halbe Geschwindigkeit von frameRate(60), denn hier werden nur noch 30 Bilder pro Sekunde gezeigt.

Es hindert uns nichts daran, die Variable frameCount als x-Koordinate ellipse(x,y,breite,höhe) zu verwenden, um eine bewegte Wolke zu zeichnen:

function setup() { createCanvas(600, 400); } function draw() { //hellblauer Hintergrund background("skyblue"); frameRate(30); // die Animation auf 30 Bilder pro Sekunde setzen //bewegte Wolke fill(255); // weiße Füllung, Kurzform für fill(255,255,255) noStroke(); // kein Rand zeichnen ellipse(frameCount, 100,70, 40); // ellipse(x, y, breite, höhe) // Text, der den frameCount-Wert anzeigt fill("black"); text("frameCount: " + frameCount, 10, 20); }

Die Wolke sein nun ein Ufo. Schaffst Du es, dass es:

  • nach unten fliegt,
  • von rechts nach links fliegt,
  • von unten nach oben fliegt,
  • von links unten nach rechts oben fliegt?
Verändere auch die Variable frameRate() um die Geschwindigkeit der Animation zu ändern.

Man kann auch eigene Variablen erstellen, die ihre Werte über die Zeit ändern können. Dazu gibt es in p5.js den Befehl let.

// Eigene Variable für die x-Position der Wolke festlegen (deklarieren) let wolkeX; // die Variable wolkeX festlegen (deklarieren) function setup() { createCanvas(600, 400); // den Wert der Variable wolkeX auf 100 setzen wolkeX = 100; } function draw() { // himmelblauer Hintergrund background("skyblue"); // weiße Wolke an der Position wolkeX zeichnen fill("white"); noStroke(); // kein Rand zeichnen ellipse(wolkeX,100,70,40); // ellipse(x, y, breite, höhe) }

Man unterscheidet zwischen dem Erstellen einer Variablen (Deklaration) und dem erstmaligen Zuweisen eines Wertes (Initialisierung):

  • let wolkeX; - Deklaration der Variablen wolkeX
  • wolkeX = 100; - Initialisierung der Variablen wolkeX mit dem Wert 100 (meistens in setup())
  • let wolkeX = 100; - gleichzeitige Deklaration und Initialisierung der Variablen wolkeX mit dem Wert 100
  • Verändere den Wert von wolkeX und beobachte die Veränderung.
  • Erstelle eine weitere Variable für die y-Position der Wolke und verwende sie um die Wolke an einer anderen Position zu zeichnen.
  • Erstelle eine Variable für die Farbe der Wolke und verwende sie um die Wolke in einer anderen Farbe zu zeichnen.

Variablen verändern

Der Hauptvorteil von Variablen ist, dass man ihre Werte über die Zeit ändern kann.

// Eigene Variable für die x-Position der Wolke festlegen (deklarieren) let wolkeX; function setup() { createCanvas(600, 400); wolkeX = 100; // den Wert der Variable wolkeX auf 100 setzen (initialisieren) } function draw() { // himmelblauer Hintergrund background("skyblue"); // neue wolkeX ist gleich alte wolkeX plus 1 wolkeX = wolkeX + 1; // weiße Wolke an der Position wolkeX zeichnen fill("white"); noStroke(); // kein Rand zeichnen ellipse(wolkeX, 100, 70, 40); // ellipse(x, y, breite, höhe) // Text, der den wolkeX-Wert anzeigt fill("black"); text("wolkeX: " + wolkeX, 10, 20); }

Welchen Wert hat die Variable Ergebnis am Ende?

let Ergebnis; let x = 10; let y = 20; y = x+y; x = y+x; Ergebnis = x+y;

Bisher hatten wir das Problem, dass manchmal die Werte einer Variable unmögliche Werte annehmen. Dies kann man durch sogenannte bedingte Anweisungen vermeiden. Dazu gibt es in p5.js den Befehl if.

if (wolkeX > 600) { // wenn wolkeX größer als 600 ist, wolkeX = 0; // dann setze wolkeX (wieder) auf 0 }

Alle Anweisungen in den geschweiften Klammern werden nur ausgeführt, wenn die Bedingung erfüllt ist.

In unserem Beispiel hat dies die folgende Wirkung:

// Eigene Variable für die x-Position der Wolke festlegen (deklarieren) let wolkeX; // die Variable wolkeX festlegen (deklarieren) function setup() { createCanvas(600, 400); wolkeX = 100;// den Wert der Variable wolkeX auf 100 setzen (initialisieren) } function draw() { // himmelblauer Hintergrund background("skyblue"); // neue wolkeX ist gleich alte wolkeX plus 1 wolkeX = wolkeX + 1; // eine bedingte Anweisung setzen: if (wolkeX > 600) { // wenn wolkeX größer als 600 ist, wolkeX = 0; // dann setze wolkeX (wieder) auf 0 } // weiße Wolke an der Position wolkeX zeichnen fill("white"); noStroke(); // kein Rand zeichnen ellipse(wolkeX,100,70,40); // ellipse(x, y, breite, höhe) // Text, der den wolkeX-Wert anzeigt fill("black"); text("wolkeX: " + wolkeX, 10, 20); }

Wenn man eine Bedingung überprüft, muss man meist zwei Werte miteinander vergleichen. Dazu gibt es in p5.js die folgenden Möglichkeiten:

Operatoren zum Vergleichen von Werten:

  • < - kleiner als
  • > - größer als
  • <= - kleiner oder gleich
  • >= - größer oder gleich
  • == - gleich
  • != - ungleich
Verwechsele nicht den Vergleichsoperator == mit dem Zuweisungsoperator =: let x; // Variable x deklarieren x = 10; // setzt den Wert der Variable x auf 10 x == 11; // prüft, ob x gleich 11 ist -> dies ist falsch

Den Vergleichsoperator == kann man auch gut bei Tastatureingaben verwenden:

function setup() { createCanvas(600, 400); background("gray") } function draw() { // Farbe des Hintergrunds ändern if (key == 'r') { background("red"); } if (key == 'g') { background("green"); } // Text, der den Tastenamen anzeigt fill("black"); text("key: " + key, 10, 20); }
  • Füge noch weitere Farbmöglichkeiten hinzu.
  • Lasse auf Tastendruck "k" einen Kreis zeichnen.
  • Steuere mit der Tasteneingabe (z.B. "w", "a", "s", "d") eine Emoji-Figur in einem Quadrat.

Man kann auch Zufallswerte erstellen, die sich über die Zeit ändern. Dazu gibt es in p5.js den Befehl random().

WolkeX = random(0, 600); // setzt die x-Position der Wolke auf einen zufälligen Wert zwischen 0 und 600

Aber auch die Farbe des Hintergrunds kann zufällig sein:

let farbe; // deklariere die Variable farbe let kreisX; // deklariere die Variable kreisX let kreisY; // deklariere die Variable kreisY function setup() { createCanvas(600, 400); background(0); // Hintergrund schwarz setzen (nur einmalig) } function draw() { // Zufällige Werte (bei jedem Durchlauf der draw()-Funktion) kreisX = random(0, 600); // Zahl zwischen 0 und 600 kreisY = random(0, 400); // Zahl zwischen 0 und 400 farbe = color(random(0, 255), random(0, 255), random(0, 255)); // Zufällige Farbe // Kreis zeichnen fill(farbe); // Farbe des Kreises setzen noStroke(); // kein Rand zeichnen circle(kreisX, kreisY, 10); // Kreis zeichnen (x, y, radius) }

Um alle Themen zusammenzuführen und Ideen für eigene Projekte zu bekommen, folgen nun verschiedene Beispiele.

Beispiel 1 - Animierte Landschaft

// Variable für die x-Position der Wolke let wolkeX = 0; // Variablen für die Sternschnuppe let sternschnuppeX = 0; let sternschnuppeY = 0; // Variablen für das Wachstum der Bäume let baumLinksWachstum = 0; let baumRechtsWachstum = 0; function setup() { createCanvas(400, 400); } function draw() { background('navy'); frameRate(15); // Sternschnuppe zeichnen stroke("yellow"); line(sternschnuppeX, sternschnuppeY, sternschnuppeX + 30, sternschnuppeY - 30); // Mond zeichnen fill(255); stroke(0); circle(350, 50, 100); stroke("navy"); fill("navy"); circle(320, 50, 100); // Große graue Berge stroke(0); fill(80); triangle(-40, 300, 75, 100, 250, 300); triangle(100, 300, 300, 100, 500, 300); // Gras fill('rgb(50,76,50)'); rect(0, 300, 400, 100); // Wolken zeichnen fill(255); ellipse(wolkeX, 50, 80, 40); ellipse(wolkeX - 40, 100, 60, 20); ellipse(wolkeX + 20, 150, 40, 10); // Baumstamm links fill("rgb(118,80,72)"); rect(40, 270, 15, 50); // Blätter links fill("green"); triangle(25, 270, 45, 240 - baumLinksWachstum, 70, 270); // Baumstamm rechts fill("rgb(118,80,72)"); rect(340, 330, 15, 50); // Blätter rechts fill("green"); triangle(325, 330, 345, 240 - baumRechtsWachstum, 370, 330); // Wolke bewegen: erhöhen und bei Erreichen der Breite zurücksetzen wolkeX = wolkeX + 1; if (wolkeX > 400) { wolkeX = 0; } // Baumwachstum links: erhöhen und bei 2900 zurücksetzen baumLinksWachstum = baumLinksWachstum + 1; if (baumLinksWachstum >= 2900) { baumLinksWachstum = 0; } // Baumwachstum rechts: erhöhen und bei 290 zurücksetzen baumRechtsWachstum = baumRechtsWachstum + 1; if (baumRechtsWachstum >= 290) { baumRechtsWachstum = 0; } // Sternschnuppe an zufällige Position setzen sternschnuppeX = random(0, 400); sternschnuppeY = random(0, 400 / 2); }

Beispiel 2 - Interaktives Zeichenprogramm

let pinselFarbe; function setup() { createCanvas(600, 400); background("lightgray"); pinselFarbe = "black"; } function draw() { // pinselFarben if (key == 'c') { background("lightgray"); // Canvas löschen } if (key == 'r') { pinselFarbe = "red"; } if (key == 'g') { pinselFarbe = "green"; } if (key == 'b') { pinselFarbe = "blue"; } if (key == 's') { pinselFarbe = "black"; } // Nur zeichnen wenn Maus gedrückt ist if (mouseIsPressed) { fill(pinselFarbe); noStroke(); circle(mouseX, mouseY, 20); } // Farbpalette anzeigen fill(0); text("Aktuelle Farbe:", 10, 20); fill(pinselFarbe); rect(110, 8, 20, 15); fill(0); text("Tasten: c=löschen, r=rot, g=grün, b=blau, s=schwarz", 10, 390); }

Beispiel 3 - Einfaches Fangspiel

let spielerX, spielerY; let zielX, zielY; let punkte = 0; let geschwindigkeit = 5; let zielGroesseZuwachs = 0; function setup() { createCanvas(600, 400); spielerX = 300; spielerY = 200; // neues Ziel setzen zielX = random(50, 550); zielY = random(50, 350); } function draw() { background("darkgray"); // Tastatursteuerung if (keyIsPressed) { if (key == 'w') { spielerY = spielerY - geschwindigkeit; } if (key == 's') { spielerY = spielerY + geschwindigkeit; } if (key == 'a') { spielerX = spielerX - geschwindigkeit; } if (key == 'd') { spielerX = spielerX + geschwindigkeit; } } // Spieler im Canvas halten if (spielerX < 25) spielerX = 25; if (spielerX > 575) spielerX = 575; if (spielerY < 25) spielerY = 25; if (spielerY > 375) spielerY = 375; // Ziel zeichnen (grün, pulsierend) fill("lightgreen"); noStroke(); let zielGroesse = 20; zielGroesseZuwachs = zielGroesseZuwachs + 1; if (zielGroesseZuwachs > 20) { zielGroesseZuwachs = 0; } circle(zielX, zielY, zielGroesse+zielGroesseZuwachs); // Spieler zeichnen fill(100, 150, 255); circle(spielerX, spielerY, 50); // Kollision prüfen let abstand = dist(spielerX, spielerY, zielX, zielY); if (abstand < 35) { punkte = punkte + 1; // neues Ziel setzen zielX = random(50, 550); zielY = random(50, 350); } // Punktestand anzeigen fill(255); textSize(20); text("Punkte: " + punkte, 10, 30); textSize(12); text("Steuerung: W/A/S/D", 10, 390); }

p5.js ist eine freie und quelloffene JavaScript-Bibliothek für kreative Programmierung