Graphic Coding — Bewegung & Transformation — Woche 5

Zurück zur Übersicht, Aufgaben

Bewegung & Kollision

Eine Bewegung ist eine Veränderung der Lage über die Zeit. Mittels Software kontrollieren wir fortlaufend die Position von visuellen Elementen und erzeugen somit den Eindruck einer Bewegung. Kontinuierliche Bewegungen entstehen, da wir die Bilder der Einzelschritte mental zusammen legen, und so Bewegung wahrnehmen.

Bevor wir eine Bewegung durch einen Code umsetzen, müssen wir entscheiden, welcherlei Bewegung entstehen soll. Dazu schauen wir uns beispielhaft einige Bewegungen an, bzw. stellen uns vor, wie

Wir können uns also die Fragen stellen: Wie simulieren wir solche Bewegungen? Wie können wir die Umwelt imitieren und interessante, "natürliche" Bewegungen erzeugen?

Im Folgenden lege ich Schritt für Schritt (und teils wiederholt) dar, wie man einfache Bewegungen programmiert.

Bewegung

Einfache lineare Bewegung für ein visuelles Element erzeugen wir, in dem die Position dieses Elements fortlaufend verändert wird.

	int x = 1;
	int y = 1;
	
	void setup() {
		size(8, 4);
	}
	
	void draw() {
		point(x, y);
		x = x + 1;
	}

Geschwindigkeit

Der Wert, mit der die Variable x verändert wird, kann als die Geschwindigkeit bezeichnet werden. Hierfür können wir wiederum eine Variable einführen. (Im Beispiel v für velocity benannt.)

	int x = 1;
	int y = 1;
	int v = 2;
	
	void setup() {
		size(8, 4);
	}
	
	void draw() {
		point(x, y);
		x = x + v;
	}

Jetzt wird der Punkt pro Schritt um 2 Pixel bewegt; die Geschwindigkeit hat sich somit erhöht.

Kollision + Abprall

Wenn wir eine Kollision in Processing erkennen wollen, d.h. das Aufeinandertreffen zweier visueller Elemente, müssen wir bestimmte Bedingungen prüfen. Und zwar, ob diese beiden Elemente kollidiert sind, also ob sie sich an gleicher Position befinden.

	void draw() {
		point(x, y);
		x = x + v;
		
		if (x >= width) {
			v = -v;
		}
	}

Wenn x größer/gleich der Weite ist, dann bedeutet dies, dass der Punkt den rechten Rand berührt, er also mit dem Rand kollidiert. In diesem Fall soll die Geschwindigkeit umgedreht werden, so dass sich der Punkt danach nach links bewegt.
Dies kann nun analog auch für den linken Rand geprüft werden:

		if (x <= 0) {
			v = -v;
		}

for-Schleife

Wie bereits bei der Einführung von Schleifen erwähnt, gibt es in Processing und anderen Programmiersprachen neben der bereits bekannten while-Schleife noch weitere Möglichkeiten, Wiederholungen auszuführen.
Mit Hilfe von for-Schleifen können wir Zählerschleifen erzeugen, also spezielle Schleifen, die eine Variable als Zähler verwenden und diesen verändern.

	for (int i = 0; i < 10; i = i + 1) {
		fill(i * 20);
		ellipse(mouseX, mouseY, i * 10, i * 10);
	}

Die while-Schleife ist die grundlegendste Schleifenart. Im Folgenden betrachten wir, wie eine while-Schleife als for-Schleife umgesetzt werden kann:

Eine for-Schleife ist also dann sinnvoll und einer while-Schleife vorzuziehen, wenn genau solche Zählerschleifen realisiert werden sollen. Dann unterstützt uns diese kompaktere Schreibweise strukturierten, lesbareren Code zu erstellen.

Interaktion 2

Damit eine computergenerierte Grafik oder ein anderes Programm auf Nutzeraktionen reagieren kann, muss der Computer Informationen aus der realen, physischen Welt aufnehmen können. Hierzu gehören inbesondere die Maus und die Tastatur, natürlich aber auch viele weitere Eingabegeräte wie etwa

Im Folgenden schauen wir uns an, wie wir weitergehend mit Hilfe der Maus und wie wir mit Hilfer der Tastatur mit einem Programm interagieren können.

mouseButton

Mit Hilfe der Processing-Variable mouseButton können wir abfragen, welche Maustaste geklickt wurde. Dazu können wir prüfen, ob der Wert in mouseButton einen der folgenden drei Variablen gleicht:

	void draw() {
		if (mousePressed) {
			if (mouseButton == RIGHT) {
				fill(random(255));
			}
		}
	}

Wichtig ist hierbei, dass für die Prüfung zwei Gleichheitszeichen verwendet werden (und nicht nur eins). Siehe hierzu Relationale Operatoren.

keyPressed

Um mit der Tastatur interaktiv in das Programmgeschehen eingreifen zu können, muss unser Code abfragen, ob eine Taste gedrückt wurde. Dies geschieht mit Hilfe der Variablen keyPressed und ist äquivalent zur Maus-Abfrage mousePressed.

	void draw() {
		if (keyPressed) {
			fill(random(255), 0, 255);
		}
		ellipse(random(width), random(height), 10, 10);
	}

key

Nun können wir — wie die Maustaste — abfragen, welche Taste der User gedrückt hat und auf diese reagieren. Hierzu verwenden wir key und prüfen, ob diese Processing-Variable den Wert eines bestimmten Zeichens hat. Die Zeichen geben wir vom Datentyp char (Character) an, die von einfachen Anführungszeichen umrahmt werden.

	void draw() {
		if (keyPressed) {
			// small
			if (key == 's') {
				s = 10;
			}
			// medium
			if (key == 'm') {
				s = 50;
			}
			// large
			if (key == 'l') {
				s = 100;
			}
		}
		ellipse(random(width), random(height), s, s);
	}

Hinweis

mouseButton wie auch key sollten meist nur abgefragt werden, wenn auch geprüft wurde, dass die Maus, bzw. eine Taste gedrückt wurde. Ansonsten werden die Anweisungen innerhalb des if-Blocks immer wieder ausgeführt, da die Variablen (mouseButton und key) noch den alten Wert besitzen.

Änderungsoperatoren

Häufig verwendete Änderungen von Variablen können wir auch kürzer schreiben. Statt die Zuweisung a = a + 1 zu verwenden, können wir auch a++ benutzen. Neben diesen Incrementer (increment: englisch für Zuwachs) gibt es noch weitere Operatoren, die kürzere Schreibweisen haben, und dadurch den Code lesbarer halten.

	int a = 0;
	a = a + 1;
	int b = 2;
	b = b – 1;
	a = a + 5;
	a = a – 3; 
	int a = 0;
	a++;
	int b = 2;
	b--;
	a+=5;
	a-=3;