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. :)