Space Invaders

import processing.sound.*;
SoundFile shootSound;
SoundFile overSound;
PImage img_Ship;
PImage img_Alien;
PImage img_Bullet;
PFont scoreFont;
int score;
int round;
int fleetDirection = 1;
boolean started = false;

class Bullet {
    int x = 0;
    int y = height - img_Ship.height;
    boolean active = false;
    
    public void move() {
        y -= 8;
    }
    
    public void Blit() {
        image(img_Bullet, x, y);
    }
}

class Ship {
    int x = width / 2 - 50;
    int state = 0;
    Bullet bullets[] = new Bullet[3];
    
    public void move() {
        if (state == 1 && x >= 0) {
            x -= 5;
        }
        if (state == 2 && x <= width - 100) {
            x += 5;
        }
    }
    
    public void shoot() {
        for (int i = 0; i < bullets.length; i++) {
            if (bullets[i].active == false) {
                bullets[i].active = true;
                bullets[i].x = ship.x + img_Ship.width / 2;
                bullets[i].y = height - img_Ship.height;
                shootSound.play(1, 0.3);
                break;
            }
        }
    }
    
    public void Blit() {
        image(img_Ship, x, height - img_Ship.height);
    }
}

class Alien {
    int x;
    int y;
    boolean dead = false;
    
    Alien (int posx, int posy) {
        x = posx;
        y = posy;
    }
    
    public void move() {
        x += 3 * fleetDirection * pow(1.05, round);
    }
    
    public boolean checkEdges() {
        if (x >= width - img_Alien.width || x <= 0){
            return true;
        } 
        return false;
    }
    
    public void Blit() {
        image(img_Alien, x, y);
    }
}

Ship ship;
Alien aliens[];

void setup () {
    size(1400, 800);
    shootSound = new SoundFile(this, "shoot.mp3");
    overSound = new SoundFile(this, "over.wav");
    img_Ship = loadImage("ship.png");
    img_Ship.resize(100, 100);
    img_Alien = loadImage("alien.png");
    img_Alien.resize(100, 100);
    img_Bullet = loadImage("bullet.png");
    img_Bullet.resize(8, 25);
    scoreFont = createFont("Terminator Two", 32);
    score = 0;
    round = 1;
    ship = new Ship();
    for (int i = 0; i < ship.bullets.length; i++) {
        ship.bullets[i] = new Bullet();
    }
    aliens = new Alien[40];
    for (int i = 0; i < aliens.length; i++) {
        aliens[i] = new Alien((i%10)*120 + 100, 120 * floor(i / 10) + 50);
    }
}

void draw() {
    if (started == true) {
        for (int i = 0; i < ship.bullets.length; i++) {
            if (ship.bullets[i].active == true) {
                ship.bullets[i].move();
                if (ship.bullets[i].y + img_Bullet.height < 0) {
                    ship.bullets[i].active = false;
                }
            }
        }
        ship.move();
        updateAliens();
    }
    updateScreen();
}

void updateScreen() {
    background(255);
    for (int i = 0; i < ship.bullets.length; i++) {
        if (ship.bullets[i].active == true) {
            ship.bullets[i].Blit();
        }
    }
    ship.Blit();
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].dead == false) {
            aliens[i].Blit();
        }
    }
    
    textFont(scoreFont);
    if (started == false) {
        fill(50, 240, 50);
        rect(500, 300, width - 1000, height - 700);
        fill(204, 102, 0);
        text("Press Space", 540, 350);
        if (keyPressed) {
            if (key == 32) {
                started = true;
                aliens = new Alien[40];
                for (int i = 0; i < aliens.length; i++) {
                    aliens[i] = new Alien((i%10)*120 + 100, 120 * floor(i / 10) + 50);
                }
                for (int i = 0; i < ship.bullets.length; i++) {
                    ship.bullets[i] = new Bullet();
                }
            }
        }
        if (mouseX > 500 && mouseX < 900 && mouseY > 300 && mouseY < 400) {
            cursor(HAND);
        }
        
        else {
            cursor(ARROW);
        }
    }
    
    else {
        noCursor();
    }
    
    fill(204, 102, 0);
    text("Score " + score, 20, 40);
    text("Round " + round, width - 300, 40);
}

void keyPressed() {
    if (started == true) {
        if (keyCode == LEFT) {
            ship.state = 1;
        }
    
        if (keyCode == RIGHT) {
            ship.state = 2;
        }
    
        if (keyCode == UP) {
            ship.shoot();
        }
    }
}

void mouseClicked() {
    if (mouseX > 500 && mouseX < 900 && mouseY > 300 && mouseY < 400 && started == false) {
        started = true;
        aliens = new Alien[40];
        for (int i = 0; i < aliens.length; i++) {
            aliens[i] = new Alien((i%10)*120 + 100, 120 * floor(i / 10) + 50);
        }
        for (int i = 0; i < ship.bullets.length; i++) {
            ship.bullets[i] = new Bullet();
        }
    }
}

void updateAliens() {
    // check aliens touching bullets, ship or ground
    for (int i = 0; i < aliens.length; i++) {
        for (int j = 0; j < ship.bullets.length; j++) {
            if (aliens[i].dead == false && ship.bullets[j].active == true) {
                if (checkCollide(img_Alien.height, img_Bullet.height, aliens[i].y, ship.bullets[j].y)) {
                    if (checkCollide(img_Alien.width, img_Bullet.width, aliens[i].x, ship.bullets[j].x)) {
                        aliens[i].dead = true;
                        ship.bullets[j].active = false;
                        score += 1 * round;
                        break;
                    }
                }
            }
        }
    }
    
    // check edges
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].dead == false) {
            if (aliens[i].checkEdges()) {
                fleetDirection *= -1;
                for (int j = 0; j < aliens.length; j++) {
                    aliens[j].y += 20 * pow(1.05, round);
                }
            break;
            }
        }
    }
    
    // ckeck ship
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].dead == false) {
            if (checkCollide(img_Alien.height, img_Ship.height, aliens[i].y, height - img_Ship.height)) {
                if (checkCollide(img_Alien.width, img_Ship.width, aliens[i].x, ship.x)) {
                    started = false;
                    overSound.play(1, 0.2);
                    break;
                }
            }
        }
    }
    
    // check bottom
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].y > height - img_Alien.height && aliens[i].dead == false) {
            started = false;
            overSound.play(1, 0.2);
            break;
        }
    }
    
    // move aliens
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].dead == false) {
            aliens[i].move();
        }
    }
    
    if (newRound()) {
        for (int i = 0; i < aliens.length; i++) {
            aliens[i] = new Alien((i%10)*120 + 100, 120 * floor(i / 10) + 50);
        }
        for (int i = 0; i < ship.bullets.length; i++) {
            ship.bullets[i].active = false;
        }
        round += 1;
    }
}


boolean checkCollide (int big, int small, int bigx, int smallx) {
    if (abs(bigx - smallx) <= big) {
        if (smallx < bigx) {
            if (abs(bigx - smallx) <= small) {
                return true;
            }
        }
        else {
            return true;
        }
    }
    return false;
}

boolean newRound () {
    for (int i = 0; i < aliens.length; i++) {
        if (aliens[i].dead == false) {
            return false;
        }
    }
    return true;
}

Java Processing 📖

Programmieren mit Processing


1. Variablen

Mit Variablen können wir etwas zwischenspeichern, um es später weiterzuverwenden. Sie werden erst deklariert und dann initialisiert. In java muss man bei der Deklarierung auch den Datentyp angeben.
int x;
x = 0;
println(x);
Als Erstes deklarieren wir den integer x, initialisieren ihn auf 0 und drucken in anschließlich in der Konsole. Mit dem Semikolon am Ende einer Zeile können wir unsere Befehle voneinander trennen.
--> 0
Wie der Name schon sagt, sind Variablen variabel, sie lassen sich also verändern.
int x;
x = 0;
println(x);
x = 2;
println(x);
--> 0
--> 2
integer lassen sich adaptiv über +, -, * und / ändern. Durch += wird der alte Wert um einen neuen addiert. Statt x = x + 1 können wir also x+=1 schreiben oder noch kürzer x++. Andersherum wird durch x-- die Variable x um 1 subtrahiert.
Parallel zu integern gibt es noch die primitiven Datentypen floats (Fließkommazahlen), Booleans (Wahrheitswerte) wie true oder false, color und chars (z.B. Buchstaben). Komplexer ist der Datentyp String, mit dem wir Texte speichern können, oder die in Processing vordefinierten Datentypen PImage, PFont und PVector, da diese ebenfalls über zusätzliche Methoden verfügen.
1.1. Systemvariablen
Neben eigenen Datentypen liefert Processing auch eigene Systemvariablen, die uns immer automatisch zur Verfügung stehen. width und height liefern uns die Pixelgröße unseres Fensters, und mouseX und mouseY geben uns die Koordinaten unserer Maus.

2. Bedingungsstatements

Aktuell sind unsere Befehle an den Computer noch sehr stumpf. Im nächsten Schritt wollen wir Logik einbauen. if sagt dem Computer, dass er einen Block von Befehlen ausführen soll, falls eine gewisse Bedingung zutrifft.
int x = 0;
if (x > 0): {
    println(x);
}
x += 1;
if (x > 0): {
    println(x);
}
--> 1
Neben dem if-Statement gibt es auch noch else und else if. else führt einen Block aus, falls eine Bedingung nicht zutrifft. Bei else-if wird eine Bedingung nur überprüft, falls weiter oben definierte Bedingungen nicht zutrafen.
int x = 0;
if (x > 0) {
    println(x);
}
else if (x < 0) {
    println(abs(x), "negative");
}
else {
    println("x must be zero!");
}
--> "x must be zero!"
Wenn wir mehrere Bedingungen haben, können wir diese mit den logischen Operatoren && (und) und || (oder) zu einem Statement kombinieren.
int Puls = 71;
if (Puls < 90 && Puls > 55) {
    println("Sieht gut aus :)");
}
--> "Sieht gut aus :)"

3. Schleifen

Die aktuelle Weise, wie wir Code schreiben, skaliert nicht sehr gut. Deshalb brauchen wir Schleifen, die uns erlauben, einen bestimmten Block mehrmals laufen zu lassen. Die wichtigste Schleife ist die for-Schleife.
for (int i = 0; i < 3; i++){
    println(x);
}
--> 0
--> 1
--> 2
Zusätzlich gibt es noch die while-Schleife, die beim genaueren Hinsehen gar nicht so weit von der for-Schleife entfernt ist.
int i = 0;
while (i < 3){
    println(x);
    i++;
}
--> 0
--> 1
--> 2

4. Funktionen

Ein weiteres Werkzeug zum Programmieren sind Funktionen. Hierbei handelt es sich um längere Blöcke von Code, die wir an anderen Stellen aufrufen können.
int CelsiusToFahrenheit(int c) {
    return c * 9/5 + 32;
}
println(CelsiusToFahrenheit(30));
--> 86
Der Datentyp vor der Funktion gibt den Datentyp von dem an, was die Funktion zurückgeben soll. Wenn wir nichts returnen möchten, können wir vorn void angeben.
Ähnlich wie eigene Datentypen hat Processing auch native Funktionen.
So wird die setup-Funktion direkt beim Start ausgeführt, die draw-Funktion ist wie eine while-Schleife. Sie wird also bei jedem Frame ausgeführt. Andere eingebaute Funktionen sind KeyPressed, MousePressed. Daneben stehen uns auch die Funktionen random, text, background, fill, print und println zur Verfügung.
int x;

void setup() {
    x = 2;
    println("1");
}

void draw() {
    println(x);
    x += 1;
}
void MousePressed() {
    println("click");
}
--> "1"
--> 2
--> 3
--> "click"
--> 4
....

5. Arrays

Arrays sind Listen, die mehrere Werte von einem Datentyp unter einer Variable und mit zusätzlichen Methoden speichern können.
int[] xarray = new int[5];
for (int i = 0; i<xarray.length; i++) {
    xarray[i] = i;
}
println(xarray);
[0] 0
[1] 1
[2] 2
[3] 3
[4] 4
Einzelne Elemente einer Liste können wir einfach überschreiben.
xarray[2] = 5;
println(xarray);
[0] 0
[1] 1
[2] 5
[3] 3
[4] 4
Wenn wir schon vorausgewählte Werte für ein Array haben, können wir diese einfach durch geschweifte Klammern definieren.
int[] zahlen = {8, 42, -3, 200};

6. Klassen

Klassen sind komplizierte Konstrukte, die wir als Blaupause benutzen können, um einzelne Instanzen zu erschaffen. Über die Punktnotation lässt sich auf die einzelnen Attribute einer Instanz zugreifen.
class Ball
{
    int xpos;
    int ypos;
    int d; // Durchmesser
}

Ball ball1 = new Ball(10, 10, 2);
Ball ball2 = new Ball(20, 20, 5);
println("ball1: " + ball1.d + ", ball2: " + ball2.d);
--> "ball1: 2, ball2: 5"
Zusätzlich können Klassen eigene Methoden haben, also Funktionen, die einzelnen Instanzen untergeordnet sind und sich ebenfalls über die Punktnotation nutzen lassen.
class Ball {
    int xpos;
    int ypos;
    int d;
    Ball (int _xpos, int _ypos, int _d) {
        xpos = _xpos;
        ypos = _ypos;
        d = _d; // Durchmesser
    }

    String printBall() {
        return "xpos: " + xpos + ", ypos: " + ypos + ", d: " + d;
    }
}

Ball ball1 = new Ball(10, 10, 2);
println(ball1.printBall());
--> "xpos: 10, ypos: 10, d: 2"
Der erste Code-Block mit demselben Namen wie die Klasse wird Constructor genannt und direkt bei der Instanzierung ausgeführt.

7. Tagebuch

Da mir die oben angerissenen Programmier-Konzepte schon vorher bekannt waren, bestand für mich die größte Lernerfahrung darin, die Syntax von Java und die beschriebenen Eigenheiten von Processing zu lernen. Vorher war es mir z.B. völlig fremd, den Datentypen einer Variablen bei der Deklarierung angeben zu müssen. Ähnliches gilt für die Beschränkung der Elemente eines Arrays auf nur einen Datentyp oder das void vor Funktionen. Auch an kleinere Abweichungen wie die Schreibweise der for-Schleifen und die Semikolons am Ende einer Zeile musste ich mich erst gewöhnen.
Ich habe aus jedem Kapitel des Skripts von Michael Kipp die Aufgabe, die ich am interessantesten fand, bearbeitet und veranschaulicht. Darüber hinaus habe ich an eigenen Projekten gearbeitet wie z.B. Spaceinvaders oder einem Online-Multiplayer-3D-Spiel. Zusätzlich hat es mir Spaß gemacht, mit kleinen spielerischen Programmen mehr über die einzelnen besonderen Features von Processing samt Libraries zu lernen. Neben der Möglichkeit, responsive Anwendungen in Processing zu programmieren, hat mir die Einheit vor allem dabei geholfen, mit der Syntax von Java und Java-ähnlichen Sprachen wie C# vertrauter zu werden.

You did it! :)


3D Online Game

import http.requests.*;
import processing.sound.*;

int id = 1;
String name = "Robert";

boolean started = false;
int x = 0;
int load = 0;
PFont scoreFont;
int n;
int round;
String wallCords;
String alivePlayers = "";
PImage bg;
PImage groundImage;
PShape[] model = new PShape[5];
PShape rocket;
SoundFile music;

class Player {
    float eyeX, eyeY, eyeZ; // Position Kamera
    float centerX, centerY, centerZ; // Zielpunkt der Kamera
    float SPEED = 5; // Fortbewegung pro Schritt
    int charRotate = 0;
    float animation = 0;
    boolean dead;

    // Konstruktor
    Player() {
        eyeX = 0.01;
        eyeY = -100;
        eyeZ = -0.01;
        centerX = 0;
        centerY = -20;
        centerZ = -240;
    }

    void drawPlayer(boolean cam) {
        if (cam) {
            camera(eyeX, eyeY, eyeZ, 
            centerX, centerY, centerZ, 
            0, 1, 0);
        }
        if (dead == false) {
            pushMatrix();
            translate(eyeX, 0, eyeZ - 100);
            rotateX(radians(180));
            rotateY(radians(charRotate));
            scale(750);
            shape(model[floor(animation) % model.length]);
            popMatrix();
        }
    }
}

class Wall {
    float x;
    float z;
    int h;
    int w;
    float speed;
    float r = random(255);
    float g = random(255);
    float b = random(255);
    boolean active = true;

    Wall(float posx, float posz, int posw, int posh, float nspeed) {
        x = posx;
        z = posz;
        h = posh;
        w = posw;
        speed = nspeed;
    }

    void drawWall() {
        pushMatrix();
        noStroke();
        fill(color(r, g, b));
        translate(x, 0-w/2, z);
        box(w);
        for (int i = 0; i < h; i++) {
            translate(0, -w, 0);
            box(w);
        }
        popMatrix();
    }

    void move() {
        z += speed;
    }
}

class Ground {
    void update() {
        beginShape();
        texture(groundImage);
        vertex(-200, 0, -800, 0, 0);
        vertex(200, 0, -800, groundImage.width, 0);
        vertex(200, 0, 0, groundImage.width, groundImage.height);
        vertex(-200, 0, 0, 0, groundImage.height);
        endShape();
    }
}

Wall walls[];
Player player;
Player players[];
Ground ground;

void setup() {
    size(1200, 800, P3D);
    ground = new Ground();
    player = new Player();
    walls = new Wall[3 + id + round];
    for (int i = 0; i < walls.length; i++) {
        walls[i] = new Wall(random(-180, 180), random(-1400, -820), 40, 3, random(2, 2 + round / 4));
    }
    bg = loadImage("bg.jpg");
    bg.resize(400, 210);
    groundImage = loadImage("ground.jpg");
    scoreFont = createFont("Terminator Two", 20);
    round = 1;
    wallCords = "";
    for (int i = 0; i < walls.length; i++) {
        wallCords += walls[i].x + "$";
        wallCords += walls[i].z + "$";
        wallCords += walls[i].w + "$";
        wallCords += walls[i].h + "$";
        wallCords += walls[i].speed + "$";
        wallCords += walls[i].r + "$";
        wallCords += walls[i].g + "$";
        wallCords += walls[i].b + "$";
        wallCords += walls[i].active + "_";
    }
    PutRequest put = new PutRequest("http://processing-api.herokuapp.com/3d/1/" + id);
    put.addHeader("Content-Type", "application/json");
    put.addData("{\"x\":" + player.eyeX + ",\"y\":" + player.eyeY + ",\"z\":" + player.eyeZ + ",\"r\":" + player.charRotate + ",\"animation\":" + player.animation + ",\"round\":" + round + ",\"walls\":\"" + wallCords + "\",\"dead\":\"" + player.dead + "\",\"name\":\"" + name + "\"}");
    put.send();
    JSONObject response = parseJSONObject(put.getContent());
    n = response.getInt("n");
    String data = response.getString("data");
    players = new Player[n];
    if (n > 0) {
        String[] dataList = split(data, ",");
        for (int i = 0; i < dataList.length; i++) {
            players[i] = new Player();
        }
    }
    for (int i = 0; i < model.length; i++) {
        model[i] = loadShape("base" + (i + 1) + ".obj");
    }
    rocket = loadShape("rocket.obj");
    music = new SoundFile(this, "music.mp3");
    music.loop();
}

void draw() {
    x += round;
    if (id == 1) {
        if (newRound()) {
            round += 1;
            walls = new Wall[4 + round];
            for (int i = 0; i < walls.length; i++) {
                walls[i] = new Wall(random(-180, 180), random(-1400, -820), 40, 3, random(2, 2 + round / 4));
            }
        }
    }

    if (keyPressed) {
        if (id == 1) {
            if (key == 32) {
                started = true;
            }
            if (key == 'r' || key == 'R') {
                restart();
            }
        }
        if (keyCode == LEFT && player.eyeX > -200) {
            player.eyeX -= player.SPEED;
            player.centerX -= player.SPEED;
            player.charRotate = -90;
            player.animation += 0.2;
        }
        if (keyCode == RIGHT && player.eyeX < 200) {
            player.eyeX += player.SPEED;
            player.centerX += player.SPEED;
            player.charRotate = 90;
            player.animation += 0.2;
        }
        if (keyCode == UP && player.eyeZ > -600) {
            player.eyeZ -= player.SPEED;
            player.centerZ -= player.SPEED;
            player.charRotate = 1;
            player.animation += 0.2;
        }
        if (keyCode == DOWN && player.eyeZ < 0) {
            player.eyeZ += player.SPEED;
            player.centerZ += player.SPEED;
            player.charRotate = 180;
            player.animation += 0.2;
        }
    }
    music.amp(0.5 + abs(player.eyeZ / 1200));
    if (started == true) {
        moveScreen();
    }
    for (int i = 0; i < walls.length; i++) {
        if (abs(player.eyeZ - 80 - walls[i].z) <= walls[i].w && abs(player.eyeX - walls[i].x) <= walls[i].w / 1.3 && walls[i].active == true) {
            player.dead = true;
            break;
        }
    }
    if (load % 1 == 0) {
        thread("loadApi");
    }
    load += 1;
    updateScreen();
}

void updateScreen() {
    background(0);
    colorMode(HSB);
    pointLight(0, 0, 1000, 100, -200, 0);
    colorMode(RGB);
    textFont(scoreFont);
    pushMatrix();
    translate(0, 0, -780);
    image(bg, - bg.width/ 2, - bg.height);
    translate(0, 0, 4);
    text(alivePlayers, -180, -180);
    text("Round " + round, 40, -180);
    if (started == false && id == 1) {
        text("Press Space", -110, -60);
    }
    popMatrix();
    noCursor();
    player.drawPlayer(true);
    for (int i = 0; i < players.length; i++) {
        players[i].drawPlayer(false);
    }
    for (int i = 0; i < walls.length; i++) {
        if (walls[i].active == true) {
            walls[i].drawWall();
        }
    }
    ground.update();
    pushMatrix();
    noStroke();
    fill(255, 255, 0);
    translate(cos(radians(x/3)) * 160, - abs(sin(radians(x/3)) * 160), -750);
    rotateX(radians(abs(cos(radians(x/3))) * 90 + 90));
    scale(.2);
    shape(rocket);
    popMatrix();
}

void moveScreen() {
    for (int i = 0; i < walls.length; i++) {
        walls[i].move();
        if (walls[i].z > 0 & walls[i].active == true) {
            walls[i].active = false;
        }
    }
}

void restart() {
    round = 1;
    player.dead = false;
    walls = new Wall[4 + round];
    for (int j = 0; j < walls.length; j++) {
        walls[j] = new Wall(random(-180, 180), random(-1400, -800), 40, 3, random(2, 2 + round / 4));
    }
    started = false;
}

void loadApi() {
    wallCords = "";
    for (int i = 0; i < walls.length; i++) {
        wallCords += walls[i].x + "$";
        wallCords += walls[i].z + "$";
        wallCords += walls[i].w + "$";
        wallCords += walls[i].h + "$";
        wallCords += walls[i].speed + "$";
        wallCords += walls[i].r + "$";
        wallCords += walls[i].g + "$";
        wallCords += walls[i].b + "$";
        wallCords += walls[i].active + "_";
    }
    PostRequest post = new PostRequest("http://processing-api.herokuapp.com/3d/1/" + id);
    post.addHeader("Content-Type", "application/json");
    post.addData("{\"x\":" + player.eyeX + ",\"y\":" + player.eyeY + ",\"z\":" + player.eyeZ + ",\"r\":" + player.charRotate + ",\"animation\":" + player.animation + ",\"round\":" + round + ",\"walls\":\"" + wallCords + "\",\"dead\":\"" + player.dead + "\",\"name\":\"" + name + "\"}");
    post.send();
    JSONObject response = parseJSONObject(post.getContent());
    String data = response.getString("data");
    if (response.getInt("n") != n) {
        n = response.getInt("n");
        players = new Player[n];
        if (n > 0) {
            String[] dataList = split(data, ",");
            for (int i = 0; i < dataList.length; i++) {
                players[i] = new Player();
            }
        }
    }
    alivePlayers = "";
    if (player.dead == false) {
        alivePlayers += name + " ";
    }
    data = data.replace("[", "");
    data = data.replace("]", "");
    if (n > 0) {
        String[] dataList = split(data, ",");
        for (int i = 0; i < dataList.length; i++) {
            String[] playerList = split(dataList[i], ";");
            players[i].eyeX = float(trim(playerList[2]));
            players[i].eyeZ = float(trim(playerList[4]));
            players[i].charRotate = int(trim(playerList[5]));
            players[i].animation = int(trim(playerList[6]));
            players[i].dead = boolean(trim(playerList[9]));
            if (players[i].dead == false) {
                alivePlayers += playerList[10];
            }

            if (int(trim(playerList[0])) == 1) {
                round = int(playerList[7]);
                playerList[8] = playerList[8].substring(0, playerList[8].length()-1);
                String[] wallsList = split(playerList[8], "_");
                if (wallsList.length != walls.length) {
                    walls = new Wall[wallsList.length];
                    for (int j = 0; j < wallsList.length; j++) {
                        String[] wallList = split(wallsList[j], "$");
                        walls[j] = new Wall(float(wallList[0]), float(wallList[1]), int(wallList[2]), int(wallList[3]), float(wallList[4]));
                        walls[j].r = float(wallList[5]);
                        walls[j].g = float(wallList[6]);
                        walls[j].b = float(wallList[7]);
                        walls[j].active = boolean(wallList[8]);
                    }
                }
                else {
                    for (int j = 0; j < wallsList.length; j++) {
                        String[] wallList = split(wallsList[j], "$");
                        walls[j].z = float(wallList[1]);
                    }
                }
            }
        }
    }
}

boolean newRound() {
    for (int i = 0; i < walls.length; i++) {
        if (walls[i].active == true) {
            return false;
        }
    }
    return true;
}

Michael Kipp

2 Interaktion und Variablen

void setup() {
    size(100, 100);
}

void draw() {
    translate(50, 50);
    background(255);
    ellipse(0, 0, 80, 80);
    float lineY = cos(radians(mouseY * 3.6)) * -35;
    float lineX = sin(radians(mouseY * 3.6)) * 35;
    line(0, 0, lineX, lineY);
}

3 If-Anweisung

int x = 0;

void setup() {
    size(100, 100);
}
    
void draw() {
    translate(width/2, height/2);
    background(0);
    fill(0);
    stroke(255);
    ellipse(0, 0, 80, 80);
    fill(255);
    arc(0, 0, 80, 80, radians(-90), radians((x % 360) - 90));
    x+=5;
}
      

4 Objekte

String Stext = "hallo";
int x = 0;

void setup() {
    size(100, 100);
}

void draw() {
    background(0);
    textSize(14);
    text("click", 20, height-10);
    textAlign(CENTER);
    textSize(28);
    text(Stext.substring(x), width/2, height/2);
}

void mouseClicked() {
    if (x < Stext.length()){
        x++;
    }
    else {
        x = 0;
    }
}

5 Schleifen

void setup() {
    size(120, 120);
}
    
void draw() {
    translate(60, 60);
    background(0);
    for (int i = 0; i < 200; i++) {
        float range = map(i, 0, 200, 0, 50);
        float x = map(i, 0, 50, 0, 2*PI);
        noStroke();
        ellipse(-sin(x)*range, cos(x)*range, 3, 3);
    }
}
    

6 Arrays

PVector[] cords = new PVector[100];
int n = 0;
float zoom = 1.0;

void setup(){
    size(200, 200);
}

void draw(){
    pushMatrix();
    translate(width/2, height/2);
    background(0);
    stroke(200);
    for (int i = 0; i < n; i++) {
        ellipse(cords[i].x, cords[i].y, width/50*zoom, height/50*zoom);
        if (i + 1 < n) {
            line(cords[i].x, cords[i].y, cords[i + 1].x, cords[i + 1].y); 
        }
    }
    popMatrix();
    textSize(14);
    textAlign(CENTER);
    text("+, -, click, up, down, left, right", width/2, height-10);
}

void mouseClicked() {
    int found = -1;
    float transX = mouseX - width/2;
    float transY = mouseY - height/2;
    for (int i = 0; i < n; i++) {
        if (abs(cords[i].x - transX) <= width/50*zoom && abs(cords[i].y - transY) <= height/50*zoom) {
            found = i;
            break;
        }
    }
    if (found >= 0) {
        n--;
        for (int i = found; i < n; i++) {
            cords[i].x = cords[i+1].x;
            cords[i].y = cords[i+1].y;
        }
    }
    else {
        cords[n] = new PVector(transX, transY);
        n++;
    }
}

void keyPressed() {
    if (key == 32 && n > 0) {
        n--;
    }
    
    else if (key == '+') {
        for (int i = 0; i < n; i++) {
            cords[i].x *= 1.1;
            cords[i].y *= 1.1;
            zoom *= 1.025;
        }
    }
    
    else if (key == '-') {
        for (int i = 0; i < n; i++) {
            cords[i].x /= 1.1;
            cords[i].y /= 1.1;
            zoom /= 1.025;
        }
    }
    
    else if (keyCode == UP) {
        for (int i = 0; i < n; i++) {
            cords[i].y += 2;
        }
    } 
    else if (keyCode == DOWN) {
        for (int i = 0; i < n; i++) {
            cords[i].y -= 2;
        }
    }
    else if (keyCode == LEFT) {
        for (int i = 0; i < n; i++) {
            cords[i].x += 2;
        }
    }
    else if (keyCode == RIGHT) {
        for (int i = 0; i < n; i++) {
            cords[i].x -= 2;
        }
    }
}

E1 Algorithmen

int depth = 1;
int i;

void setup() {
    size(300, 200);
}

void draw() {
    background(255);
    i = 1;
    fill(0);
    translate(width/2, height/2);
    triangle(0, -height/2, -width/2, height/2, width/2, height/2);
    fill(255);
    sierpinski(i);
    fill(0);
    textSize(14);
    text("down/up (depth:" + depth + ")", -width/2+10, -height/2+10);
}

void sierpinski(int i) {
    triangle(0, height/pow(2, i), -width/pow(2, i+1), 0, width/pow(2, i+1), 0);
    if (i < depth) {
        i++;
        for (int j = -1; j < 2; j++) {
            pushMatrix();
            if (j == 0) {
                translate(0, -height/pow(2,i));
            }
            else {
                translate(width/pow(2,i)*j, height/pow(2,i));
            }
            sierpinski(i);
            popMatrix();
        }
    }
}

void keyPressed() {
    if (keyCode == UP) {
        depth++;
    }
    else if (keyCode == DOWN && depth > 1) {
        depth--;
    }
}
    

8 Klassen

class Ball {
    PVector pos;
    PVector speed;
    int d;
    color c = color(random(255), random(255), random(255));

    Ball (int w, int h, int du) {
        pos = new PVector(random(du/2, w-du/2), random(d/2, h-d/2));
        speed = new PVector(random(-2, 2), random(-2, 2));
        d = du;
    }

    void update() {
        pos.add(speed);
        if (pos.x < d / 2 || pos.x > width - d/2) {
            speed.x*=-1;
        }
        if (pos.y < d / 2 || pos.y > height - d/2) {
            speed.y*=-1;
        }
    }

    void render() {
        noStroke();
        fill(c);
        ellipse(pos.x, pos.y, d, d);
    }
}
 
class Link {
    Ball ball1;
    Ball ball2;

    Link(Ball b1, Ball b2) {
        ball1 = b1;
        ball2 = b2;
    }

    void render() {
        stroke(255);
        line(ball1.pos.x, ball1.pos.y, ball2.pos.x, ball2.pos.y);
    }
}

Ball[] balls;
Link[] links;
int linkn;
boolean start = false;

void setup() {
    size(200, 200);
    balls = new Ball[20];
    for (int i = 0; i < balls.length; i++) {
        balls[i] = new Ball(width, height, 8);
    }
    links = new Link[200];
    linkn = 0;
}

void draw() {
    background(0);
    for (int i = 0; i < balls.length; i++) {
        balls[i].render();
    }
    for (int i = 0; i < linkn; i++) {
        links[i].render();
    }

    if (start) {
        for (int i = 0; i < balls.length; i++) {
            balls[i].update();
        }
        for (int i = 0; i < balls.length; i++) {
            for (int j = i+1; j < balls.length; j++) {
                if (collide(balls[i], balls[j]) && linkn < links.length) {
                    links[linkn] = new Link(balls[i], balls[j]);
                    linkn++;
                }
            }
        }
    }
    fill(255);
    text("Space, R", 10, height-10);
}

boolean collide(Ball b1, Ball b2) {
    if (abs(b1.pos.x - b2.pos.x) <= b1.d / 2 && abs(b1.pos.y - b2.pos.y) <= b1.d / 2) {
        return true;
    }
    return false;
}

void keyPressed() {
    if (key == 32) {
        start = !start;
    }

    else if (key == 'r' || key == 'R') {
        balls = new Ball[20];
        for (int i = 0; i < balls.length; i++) {
            balls[i] = new Ball(width, height, 8);
        }
        links = new Link[500];
        linkn = 0;
    }
}
 

10 Transformationen

int x = 0;
int dir = 1;

void setup() {
    size(100, 100);
}

void draw() {
    background(0);
    fill(255);
    noStroke();
    translate(width/2, height/2);
    rotate(radians(x));
    pushMatrix();
    rectMode(CENTER);
    rect(0, 0, 60, 5);
    translate(30, 2.5);
    rotate(radians(x));
    fill(0, 255, 0);
    rect(0, 0, 20, 20);
    popMatrix();
    translate(-30, -2.5);
    rotate(radians(x));
    fill(255, 0, 0);
    rect(0, 0, 20, 20);
    x+=dir;
}

void mouseClicked() {
    dir *= -1;
}

12 Zustände und Listen

int score;
Ball[] ballList;

class Ball {
    int score;
    float r;
    PVector speed;
    PVector pos;
    boolean active = true;

    Ball (int nscore, float nr, PVector nspeed, PVector npos) {
        r = nr;
        score = nscore;
        speed = nspeed;
        pos = npos;
    }

    void move() {
        pos.add(speed);
        if (pos.x >= width - r || pos.x <= r) {
            speed.x *= -1;
        }
        if (pos.y >= height - r || pos.y <= r) {
            speed.y *= -1;
        }
    }

    void blit() {
        if (active) {
            fill(255);
            ellipse(pos.x, pos.y, r, r);
            fill(0);
            textAlign(CENTER);
            textSize(r-1);
            text(score, pos.x, pos.y + r/3);
        }
    }
}

void setup() {
    size(300, 300);
    score = 0;
    ballList = new Ball[10];
    for (int i = 0; i < ballList.length; i++) {
        float nr = random(15, 25);
        ballList[i] = new Ball(int(random(1, 10)), nr, new PVector(random(-2.5, 2.5), random(-2.5, 2.5)), new PVector(random(nr, width - nr), random(nr, height - nr)));
    }
}

void draw() {
    background(0);
    cursor(CROSS);
    for (int i = 0; i < ballList.length; i++) {
        ballList[i].move();
    }
    for (int i = 0; i < ballList.length; i++) {
        ballList[i].blit();
    }
    fill(255);
    textAlign(CENTER);
    textSize(28);
    text("score: " + score, width/2, 280);

    if (newRound()) {
        ballList = new Ball[10];
        for (int i = 0; i < ballList.length; i++) {
            float nr = random(15, 25);
            ballList[i] = new Ball(int(random(1, 10)), nr, new PVector(random(-2.5, 2.5), random(-2.5, 2.5)), new PVector(random(nr, width - nr), random(nr, height - nr)));
        }
    }
}

void mousePressed() {
    for (int i = 0; i < ballList.length; i++) {
        if (ballList[i].active == true && abs(ballList[i].pos.x - mouseX) <= ballList[i].r && abs(ballList[i].pos.y - mouseY) <= ballList[i].r) {
            ballList[i].active = false;
            score += ballList[i].score;
        }
    }
}

boolean newRound() {
    for (int i = 0; i < ballList.length; i++) {
        if (ballList[i].active == true) {
            return false;
        }
    }
    return true;
}

Nebenprojekte

Planeten

boolean start = false;
PImage img;

class Planet {
    float radius;
    PVector pos;
    PVector ellipseSize;
    color Color;
    int x;
    float speed;
    
    Planet (int _x, float _radius, float _speed, PVector _ellipseSize, color _Color) {
        x = _x;
        radius = _radius;
        speed = _speed;
        ellipseSize = _ellipseSize;
        pos = new PVector(cos(radians(x)) * ellipseSize.x, sin(radians(x)) * ellipseSize.y);
        Color = _Color;
    }
    
    void blit() {
        fill(lerpColor(color(255, 100, 30), Color, .5));
        beginShape();
        vertex(cos(radians(x-speed*10)) * ellipseSize.x, sin(radians(x-speed*10)) * ellipseSize.y);
        vertex(pos.x+radius/3, pos.y+radius/3);
        vertex(pos.x+radius/3, pos.y-radius/3);
        vertex(pos.x-radius/3, pos.y+radius/3);
        vertex(pos.x-radius/3, pos.y-radius/3);
        endShape(CLOSE);
        fill(Color);
        ellipse(pos.x, pos.y, radius, radius);
    }
    
    void move() {
        x += speed;
        pos.x = cos(radians(x)) * ellipseSize.x;
        pos.y = sin(radians(x)) * ellipseSize.y;
    }
}

Planet[] planets;

void setup() {
    size(400, 400);
    planets = new Planet[8];
    planets[0] = new Planet(0, 30, 1, new PVector(width/40, height/40), color(255, 190, 60));
    for (int i = 1; i<planets.length; i++) {
        float _radius = random(10, 15);
        planets[i] = new Planet(int(random(0, 180)), _radius, random(1, 1.5), new PVector(random(width/6, width/2-_radius), random(height/6, height/2-_radius)), color(random(255), random(255), random(255)));
    }
    img = loadImage("starz.jpg");
    img.resize(width, height);
}

void draw() {
    background(img);
    cursor(ARROW);
    noStroke();
    translate(width / 2, height / 2);
    
    for (int i = 0; i<planets.length; i++) {
        planets[i].blit();
    }
    
    fill(200);
    textAlign(CENTER);
    textSize(28);
    text(
    "" + day() + "." + month() + "." + year() + "-" + hour() + ":" + minute(), 
    0, 
    -height/2.25  
    );
    
    if (start) {
        for (int i = 0; i<planets.length; i++) {
            planets[i].move();
        }
        textSize(20);
        text("+, -, SPACE", -width/2.7, height/2.1);
    }
    
    else {
        fill(0, 200, 0);
        rect(-width/2.5, height/3, width/2.5*2, 50);
        fill(0);
        text("PRESS SPACE", 0, height/2.4);
    }
}

void keyPressed() {
    if (key == '+' && start) {
        for (int i = 0; i<planets.length; i++) {
            planets[i].radius *= 1.5;
            planets[i].ellipseSize.mult(1.5);
        }
    }
    
    else if (key == '-' && start) {
        for (int i = 0; i<planets.length; i++) {
            planets[i].radius /= 1.5;
            planets[i].ellipseSize.mult(1/1.5);
        }
    }
    
    if (key == 32) {
        start = !start;
    }
}
    

SortingVisualizer

float[] myList;
int idx = -1;

void setup() {
    size(152, 120);
    myList = new float[15];
    for (int i = 0; i < myList.length; i++) {
        myList[i] = random(100);
    }
}

void draw() {
    frameRate(10);
    background(200);
    for (int i = 0; i < myList.length; i++) {
        if (i == idx) {
            fill(random(255), random(255), random(255));
        }
        else {
            fill(255);
        }
        rect(i*10 + 2, 100-myList[i], 8, myList[i]);
    }
    idx = bubbleSort(myList);
    fill(0);
    text("BubbleSort - SPACE", 2, 115);
}

int bubbleSort(float[] arr) {
    float temp = 0;  
    for(int i=0; i < arr.length; i++){  
        for(int j=1; j < (arr.length-i); j++){  
            if(arr[j-1] > arr[j]){  
                temp = arr[j-1];  
                arr[j-1] = arr[j];  
                arr[j] = temp;
                return j;
            }     
        }  
    }
    return -1;
}

int insertionSort(float[] arr) {
    for (int i = 1; i < arr.length; i++) {
        float current = arr[i];
        int j = i - 1;
        while(j >= 0 && current < arr[j]) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = current;
        return i;
    }
    return -1;
}

void keyPressed() {
    if (key == 32) {
        for (int i = 0; i < myList.length; i++) {
            myList[i] = random(100);
        }
    }
}

DogeDodger

import processing.sound.*;
class Ball {
    PVector pos;
    PVector speed;
    int radius;
    color c;
    boolean active = true;
    
    Ball(PVector _pos, float _speed, int _radius, color _c, PVector _target) {
        pos = _pos;
        radius = _radius;
        c = _c;
        float disX = _target.x - pos.x;
        float disY = _target.y - pos.y;
        float disMax = abs(disX) + abs(disY);
        float factor = _speed / disMax;
        speed = new PVector(disX * factor, disY * factor);
    }
    
    void blit() {
        if (active) {
            fill(c);
            ellipse(pos.x, pos.y, radius, radius);
        }
    }
    
    void move() {
        pos.add(speed);
    }
}

class Player {
    PVector pos = new PVector(0, 0);
    int size = 30;
    int mode = 0;
    int Maxhp = 3;
    int hp = 3;
    float speed = 3;
    int x;
    
    void move() {
        if (mode == 0 && pos.y >= -height/2 + speed + doge.size/2) {
            pos.y -= speed;
        }
        else if (mode == 1 && pos.y <= height/2 - speed - doge.size/2) {
            pos.y += speed;
        }
        else if (mode == 2 && pos.x >= -width/2 + speed + doge.size/2) {
            pos.x -= speed;
        }
        else if (mode == 3 && pos.x <= width/2 - speed - doge.size/2) {
            pos.x += speed;
        }
        x+=1;
    }
    
    void blit() {
        image(dogeImg, doge.pos.x - doge.size/2, doge.pos.y - doge.size/2);
        pushMatrix();
        translate(doge.pos.x, doge.pos.y);
        fill(25, 255, 100);
        for (int i = 0; i<hp; i++) {
            float eX = map(i, 0, Maxhp, 0, 360)+x;
            ellipse(sin(radians(eX))*size*0.8, cos(radians(eX))*size*0.8, 3, 3);
        }
        popMatrix();
    }
}

Player doge;
PImage dogeImg;
PImage bgImg;
SoundFile music;
Ball[] enemies;
boolean run = false;
int round;

void setup() {
    size(400, 400);
    doge = new Player();
    dogeImg = loadImage("doge.png");
    dogeImg.resize(doge.size, doge.size);
    bgImg = loadImage("bg.jpg");
    bgImg.resize(width, height);
    reset();
    music = new SoundFile(this, "doge.mp3");
    music.loop();
}

void draw() {
    translate(width/2, height/2);
    background(bgImg);
    noStroke();
    if (run) {
        checkCollide();
        doge.move();
        for (int i = 0; i<enemies.length; i++) {
            enemies[i].move();
        }
        if (roundOver()) {
            enemies = new Ball[20];
            for (int i = 0; i<enemies.length; i++) {
                float eX = map(i, 0, enemies.length-1, 0, 720);
                float eFactor = map(i, 0, enemies.length-1, width/3.2, width);
                PVector ePos = new PVector(sin(radians(eX))*eFactor+doge.pos.x, cos(radians(eX))*eFactor+doge.pos.y);
                enemies[i] = new Ball(ePos, 2, 8, color(255, 0, 0), new PVector(doge.pos.x, doge.pos.y));
            }
            round += 1;
        }
    }
    for (int i = 0; i<enemies.length; i++) {
        enemies[i].blit();
    }
    doge.blit();
    fill(255);
    textSize(20);
    text("Round: " + round, -height/2.6, -height/2.3);
    text("HP: " + doge.hp, height/2.4, -height/2.3);
    if (run == false) {
        fill(200);
        rect(-width/4, height/3, width/2, height/10);
        fill(200, 50, 50);
        textAlign(CENTER);
        text("PRESS SPACE", 0, height/2.55);
    }
}

void keyPressed() {
    if (key == 32 && run == false) {
        reset();
        run = true;
    }
    char[] codes = {UP, DOWN, LEFT, RIGHT};
    for (int i = 0; i<codes.length; i++) {
        if (keyCode == codes[i]) {
            doge.mode = i;
        }
    }
}

void checkCollide() {
    for (int i = 0; i<enemies.length; i++) {
        if (abs(enemies[i].pos.x - doge.pos.x) <= doge.size / 2 && abs(enemies[i].pos.y - doge.pos.y) <= doge.size / 2 && enemies[i].active == true) {
            doge.hp -= 1;
            enemies[i].active = false;
            if (doge.hp <= 0) {
                run = false;
            }
        }
    }
}

boolean roundOver() {
    for (int i = 0; i<enemies.length; i++) {
        if (abs(enemies[i].pos.x) <= width / 2 && abs(enemies[i].pos.y) <= height / 2) {
            return false;
        }
    }
    return true;
}

void reset() {
    enemies = new Ball[20];
    for (int i = 0; i<enemies.length; i++) {
        float eX = map(i, 0, enemies.length-1, 0, 720);
        float eFactor = map(i, 0, enemies.length-1, width/3.2, width);
        PVector ePos = new PVector(sin(radians(eX))*eFactor+doge.pos.x, cos(radians(eX))*eFactor+doge.pos.y);
        enemies[i] = new Ball(ePos, 2, 8, color(255, 0, 0), new PVector(doge.pos.x, doge.pos.y));
    }
    doge.pos = new PVector(0, 0);
    doge.hp = doge.Maxhp;
    round = 1;
}

House3D

float r = 0;
PImage wallimg;
PImage roofimg;
PImage doorimg;
PImage bgimg;

void setup() {
    size(700, 400, P3D);
    wallimg = loadImage("wall.jpg");
    roofimg = loadImage("roof.jpg");
    doorimg = loadImage("door.jpg");
    bgimg = loadImage("bg.jpg");
}

void draw() {
    background(200);

    drawHouse();
    r+=0.5;
}

void drawHouse() {
    noStroke();
    translate(350, 200, -100);
    
    textureMode(NORMAL);
    
    beginShape(); // bg
    texture(bgimg);
    vertex(-700, -400, -200, 0, 0);
    vertex(700, -400, -200, 1, 0);
    vertex(700, 400, -200, 1, 1);
    vertex(-700, 400, -200, 0, 1);
    endShape(CLOSE);
    
    translate(0, 50, 0);
    rotateY(radians(r));
    rotateX(radians(r));
    
    beginShape(); // wall back
    texture(wallimg);
    vertex(-100, -100, -100, 0, 0);
    vertex(100, -100, -100, 1, 0);
    vertex(100, 100, -100, 1, 1);
    vertex(-100, 100, -100, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // wall front
    texture(wallimg);
    vertex(-100, -100, 100, 0, 0);
    vertex(100, -100, 100, 1, 0);
    vertex(100, 100, 100, 1, 1);
    vertex(-100, 100, 100, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // wall left
    texture(wallimg);
    vertex(-100, -100, 100, 0, 0);
    vertex(-100, -100, -100, 1, 0);
    vertex(-100, 100, -100, 1, 1);
    vertex(-100, 100, 100, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // wall right
    texture(wallimg);
    vertex(100, -100, 100, 0, 0);
    vertex(100, -100, -100, 1, 0);
    vertex(100, 100, -100, 1, 1);
    vertex(100, 100, 100, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // wall bottom
    texture(wallimg);
    vertex(-100, 100, 100, 0, 0);
    vertex(-100, 100, -100, 1, 0);
    vertex(100, 100, -100, 1, 1);
    vertex(100, 100, 100, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // roof front
    texture(roofimg);
    vertex(-120, -100, 120, 0, 1);
    vertex(0, -200, 0, 0, 0.5);
    vertex(120, -100, 120, 1, 1);
    endShape(CLOSE);
    
    beginShape(); // roof back
    texture(roofimg);
    vertex(-120, -100, -120, 0, 1);
    vertex(0, -200, 0, 0, 0.5);
    vertex(120, -100, -120, 1, 1);
    endShape(CLOSE);
    
    beginShape(); // roof left
    texture(roofimg);
    vertex(-120, -100, -120, 0, 1);
    vertex(0, -200, 0, 0, 0.5);
    vertex(-120, -100, 120, 1, 1);
    endShape(CLOSE);
    
    beginShape(); // roof right
    texture(roofimg);
    vertex(120, -100, -120, 0, 1);
    vertex(0, -200, 0, 0, 0.5);
    vertex(120, -100, 120, 1, 1);
    endShape(CLOSE);
    
    beginShape(); // roof bottom
    texture(roofimg);
    vertex(-120, -100, 120, 0, 0);
    vertex(-120, -100, -120, 1, 0);
    vertex(120, -100, -120, 1, 1);
    vertex(120, -100, 120, 0, 1);
    endShape(CLOSE);
    
    beginShape(); // door
    texture(doorimg);
    vertex(-50, -20, 101, 0, 0);
    vertex(0, -20, 101, 1, 0);
    vertex(0, 100, 101, 1, 1);
    vertex(-50, 100, 101, 0, 1);
    endShape(CLOSE);
}

Arbeit

String[] infoText = {"I", "n", "f", "o", "r", "m", "a", "t", "i", "k"};
int i = -1;
PImage bgImg;
int RotateSpeed = 1;
float BigRotateI = 0;

House[] houses = new House[10];
House[] rotateHouses = new House[10];
int nHouses = 0;

class House {
    PVector pos;
    float houseWidth;
    color LerpColor;
    int RotateI = 0;
    
    House (PVector _pos, float _HouseWidth, color _LerpColor) {
        pos = _pos;
        houseWidth = _HouseWidth;
        LerpColor = _LerpColor;
    }
    
    void drawHouse() {
        RotateI+=1*RotateSpeed;
        pushMatrix();
        translate(pos.x, pos.y);
        rotate(radians(RotateI));
        color oC = color(200);
        fill(lerpColor(oC, LerpColor, 0.3));
        beginShape(); // schornstein
        vertex(-90*houseWidth, -180*houseWidth);
        vertex(-30*houseWidth, -180*houseWidth);
        vertex(-30*houseWidth, 0);
        vertex(-90*houseWidth, 0);
        endShape(CLOSE);
        
        oC = color(160, 200, 100);
        fill(lerpColor(oC, LerpColor, 0.3));
        rectMode(CENTER);
        rect(0, 0, 200*houseWidth, 160*houseWidth); // haus
        
        oC = color(220, 80, 15);
        fill(lerpColor(oC, LerpColor, 0.3));
        triangle(-120*houseWidth, -80*houseWidth, 0, -200*houseWidth, 120*houseWidth, -80*houseWidth); // dach
        
        oC = color(180, 110, 15);
        fill(lerpColor(oC, LerpColor, 0.3));
        beginShape(); // tür
        vertex(-40*houseWidth, 20*houseWidth);
        vertex(0, 20*houseWidth);
        vertex(0, 80*houseWidth);
        vertex(-40*houseWidth, 80*houseWidth);
        endShape(CLOSE);
        
        oC = color(255);
        fill(lerpColor(oC, LerpColor, 0.3));
        rect(50*houseWidth, -10*houseWidth, 40*houseWidth, 40*houseWidth); // fenster
        
        line(30*houseWidth, -10*houseWidth, 70*houseWidth, -10*houseWidth);
        line(50*houseWidth, -30*houseWidth, 50*houseWidth, 10*houseWidth);
        popMatrix();
    }
}

void setup() {
    size(600, 600);
    bgImg = loadImage("house.jpg");
    bgImg.resize(width, height);
    for (int j = 0; j<rotateHouses.length; j++) {
        rotateHouses[j] = new House(new PVector(0, 0), 0.2, 
            color(random(255), random(255), random(255)));
    }
}

void draw () {
    background(bgImg);
    noCursor();
    for (int j = 0; j<nHouses; j++) {
        houses[j].drawHouse();
    }
    drawHouse();
    drawInfoText();
    textSize(20);
    text("Click, +, -, mouseX, mouseY", width-240, 30);
}

void drawHouse() {
    pushMatrix();
    translate(mouseX, mouseY);
    
    for (int j = 0; j<rotateHouses.length; j++) {
        BigRotateI += 0.1*RotateSpeed;
        float housePosX = cos(radians(j * 36 + BigRotateI)) * 150;
        rotateHouses[j].pos.x = housePosX;
        float housePosY = sin(radians(j*36 + BigRotateI)) * 150;
        rotateHouses[j].pos.y = housePosY;
        rotateHouses[j].drawHouse();
    }
    
    fill(200);
    beginShape(); // schornstein
    vertex(-90, -180);
    vertex(-30, -180);
    vertex(-30, 0);
    vertex(-90, 0);
    endShape(CLOSE);
    
    fill(160, 200, 100);
    rectMode(CENTER);
    rect(0, 0, 200, 160); // haus

    fill(220, 80, 15);
    triangle(-120, -80, 0, -200, 120, -80); // dach
    
    fill(180, 110, 15);
    beginShape(); // tür
    vertex(-40, 20);
    vertex(0, 20);
    vertex(0, 80);
    vertex(-40, 80);
    endShape(CLOSE);
    
    fill(255);
    rect(50, -10, 40, 40); // fenster
    
    line(30, -10, 70, -10);
    line(50, -30, 50, 10);
    popMatrix();
}

void drawInfoText() {
    String strInfoText = "";
    for (int j = 0; j-1<i % infoText.length; j++) {
        strInfoText += infoText[j];
    }
    fill(0);
    textSize(28);
    text(strInfoText, 10, 30);
}

void mousePressed() {
    i += 1;
    if (i % infoText.length == 0) {
        println("");
    }
    print(infoText[i % infoText.length]);
    RotateSpeed *= -1;
}

void keyPressed() {
    if (key == '+' && nHouses < houses.length -1) {
        houses[nHouses] = new House(new PVector(random(width), random(height)), 
        random(0.8), 
        color(random(255), random(255), random(255)));
        nHouses += 1;
    }
    else if (key == '-' && nHouses > 0) {
        houses[nHouses] = null;
        nHouses -= 1;
    }
}
    

Mehr Programme sind auf GitHub. :)