diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..8a274cf
Binary files /dev/null and b/.DS_Store differ
diff --git a/Coder.JPG b/Coder.JPG
new file mode 100644
index 0000000..a2b51c0
Binary files /dev/null and b/Coder.JPG differ
diff --git a/Invader.js b/Invader.js
new file mode 100644
index 0000000..0f966ef
--- /dev/null
+++ b/Invader.js
@@ -0,0 +1,66 @@
+class Helper {
+ static setCharsAt(str,index,chr) {
+ if(index > str.length-1) return str;
+ return str.substr(0,index) + chr + str.substr(index+chr.length);
+ }
+}
+
+class Invader {
+ constructor(appearance, id) {
+ this.appearance = appearance;
+ this.id = id;
+ }
+
+ shootLaser() {
+ console.log("Invader " +this.id+" Laser shot")
+ }
+
+ explode() {
+ console.log("Invader "+this.id+" exploded")
+ }
+
+ isHitByBullet(bulletX, bulletY) {
+ //prüfen ob der Bullet den Invader trifft
+ }
+}
+
+class InvaderRow {
+ constructor(posX, posY, width, height, invaders, id) {
+ this.id = id;
+ this.posX = posX;
+ this.posY = posY;
+ this.width = width;
+ this.height = height;
+ this.invaders = invaders;
+ }
+
+ static generateInvader(width, height) {
+ let currentInvader = [];
+ for (let y = 0; y < height; y++) {
+ currentInvader[y] = " ".repeat(width*2+1);
+ for (let x = 0; x < width; x++) {
+ let randomNumber = Math.random();
+ if (randomNumber >= 0.5) {
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], x,'▧'));
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], 2 * width - x,'▨'));
+ }
+ }
+ }
+ return currentInvader;
+ }
+
+ static generateInvaderRow(invaderWidth, invaderHeight) {
+ let currentInvaders = [];
+ let rowWidth = Math.floor(cols*0.8);
+ let wholeInvader = invaderWidth * 2;
+ let spacerWidth = invaderWidth/2;
+ let numInvaders = Math.floor((rowWidth / ((wholeInvader+spacerWidth))));
+ let invaderAppearance = InvaderRow.generateInvader(invaderWidth, invaderHeight);
+ //let numInvaders = Math.floor(spacing);
+ for(let i = 0; i < numInvaders ; i++) { // gerundet(x = ((breite - breite*0,2) / invaderbreite) + (x - 1) * invaderbreite/2 ))
+ let newInv = new Invader(invaderAppearance, i);
+ currentInvaders.push(newInv);
+ }
+ return currentInvaders;
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 424b110..1885835 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,242 @@
# 01_03_spacebase
-Base for Space Invaders
+
+# Dokumentation Space Invader
+##### Maximilian Becht und Tara Monheim
+>Maximilian Becht auf [Github](https://github.com/maxicozy).
+
+>Tara Monheim auf [Github](https://github.com/taramonheim).
+
+Unser Space Invader Projekt wurde im Laufe des ersten Semesters im Fach Programmiersprachen 1 gecoded. Das Space Invader
+Projekt soll es dem Spieler ermöglichen mit dem Spaceship die Invaders zu treffen und sie zum explodieren zu bringen.
+Die Invader Reihe kommt langsam immer weiter runter. Also ran an die Tasten und probier es aus!
+
+Den Code haben wir mithilfe unseres Dozenten[ Florian Geiselhart](https://github.com/fg-uulm) (das bist du)
+geschrieben. Er basiert auf dem Basis Code von unserem Dozenten und wurde von uns erweitert. Den Basis Code findet man
+[hier](https://github.com/hfgcoding/01_03_spacebase).
+Auch das Internet hilft in der Regel, aber da es sehr viele Space Invader Games gibt, die programmiert wurden,verliert
+man schnell den Überblick.
+Also ransetzen, denken und coden! Was immer hilft:
+Die Klassen und Eigenschaften einfach mal aufzuschreiben. Mit Papier und Stift. Ganz Old School.
+
+Eigenschaften des Spiels, an denen wir gearbeitet haben:
+
+1. Die Invader werden radom gerendert.
+
+2. Die Invader werden in einer Reihe generiert.
+3. Es werden so viele Invader generiert, wie in das Feld passen.
+4. Wenn die Invader Reihe an den Rand des Felds kommt bewegt sie sich eine Zeile runter und in die andere Richtung.
+5. Das Spaceship schießt auf die Invader, trifft ein Bullet den Invader, explodiert dieser.
+6. Ein Score am Rand zählt hoch, wenn man einen Invader trifft.
+7. Unser Code baut auf Klassen auf, die wir in der Javascript Datei definiert haben.
+
+
+
+
+
+# Usage / Benutzung
+
+Um das Spiel selbst zu erleben, kann man den Code entweder einfach von Github downloaden und in einen Code Editor
+öffnen, um ihn zu individualisieren oder man öffnet ihn mit einem Browser.
+Im Code Editor braucht man
+die [classes.js](classes.js) und die [index.html](index.html), die auf Github zu finden sind.
+Um das ganze in einem belibiegen Browser öffnen zu können, muss man das Repository auf Github forken und clonen und dann
+die Html Datei mit einem Browser öffnen.
+Sobald die Seite geladen ist startet auch das Spiel. Die Invader bewegen sich in ihrer Reihe von links nach rechts,
+treffen sie an den Rand, rücken sie eine Zeile nach unten und ändern ihre BEwegungsrichtung nun nach links.Das Spaceship
+kann man mit den key left und key right Tasten bewegen. Durch die
+Leertaste schießt das Spaceship auf die Invader. Diese explodieren, sobald sie getroffen werden. Durch die
+Barriere, die das Spaceship schützen soll, kann man nicht durchschießen.
+Die Invaders selber können zur Zeit noch nicht auf das Spaceship schießen.
+Würde das funktionieren, müsste auch die Barriere, bei Abschuss derer, Stück für Stück verschwinden.
+Durch den Reload Button des Fensters kann man das Spiel neu starten.
+
+# Structure / Aufbau
+
+Wir haben das Spiel anhand von Klassen aufgebaut,
+deren Eigenschaften wir in der Javascript Datei angegeben haben. In der Html Datei greifen wir auf diese Klassen zu.
+
+### **class Invader**:
+
+
+class Invader {
+ constructor(appearance, ischBinKaputt, explodeTime, id) {
+ this.appearance = appearance;
+ this.id = id;
+ this.ischBinKaputt = ischBinKaputt;
+ this.explodeTime = explodeTime;
+ }
+ shootLaser() {
+ console.log("Invader " + this.id + " Laser shot")
+ }
+ explode() {
+ this.appearance = [" ",
+ " \\ | / ",
+ " - p u f f - ",
+ " / | \\ ",
+ " "
+ ];
+ }
+}
+
+
+* hier haben wir der Klasse Invader die Eigenschaften `appearance`, `ischBinKaputt`, `explodeTime` und `id` zugeorndet.
+Außerdem haben wir ihm die Methode `explode()` gegeben,um sein Aussehen nach dem Explodieren zu bestimmen.
+
+### **class InvaderRow**
+
+class InvaderRow {
+ constructor(posX, posY, width, height, invaders, id) {
+ this.id = id;
+ this.posX = posX;
+ this.posY = posY;
+ this.width = width;
+ this.height = height;
+ this.invaders = invaders;
+ }
+
+
+* Die Klasse `InvaderRow` beinhaltet ihre eigene Position und invader.
+
+### **static generateInvader:**
+
+>Das static Schüsselwort definiert statische Methoden für eine Klasse.
+
+ static generateInvader(width, height) {
+ let currentInvader = [];
+ for (let y = 0; y < height; y++) {
+ currentInvader[y] = " ".repeat(width * 2 + 1);
+ for (let x = 0; x < width; x++) {
+ let randomNumber = Math.random();
+ if (randomNumber >= 0.5) {
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], x, '#'));
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], 2 * width - x, '#'));
+ }
+ }
+ }
+ return currentInvader;
+ }
+
+
+* `width, height`: Invadergröße (Property)
+* `currentInvader`: ist ein Array, in das so viele Strings generiert werden, wie der Invader hoch ist
+* eine zufällige Zahl wird generiert ist diese größer oder gleich `0.5`, so wird ein `"#"` an diese Stelle des
+currentInvaders Arrays geschrieben. Somit hat man die Hälfte dieses Invaders. Diese wird anschließend gespiegelt.
+
+### **static generateInvaderRow:**
+
+ static generateInvaderRow(invaderWidth, invaderHeight) {
+ let currentInvaders = [];
+ let rowWidth = Math.floor(cols * 0.8);
+ let wholeInvader = invaderWidth * 2;
+ let spacerWidth = invaderWidth / 2;
+ let numInvaders = Math.floor((rowWidth / ((wholeInvader + spacerWidth))));
+ let invaderAppearance = InvaderRow.generateInvader(invaderWidth, invaderHeight);
+ for (let i = 0; i < numInvaders; i++) {
+ let newInv = new Invader(invaderAppearance, false, 0, i);
+ currentInvaders.push(newInv);
+ }
+ return currentInvaders;
+ }
+}
+
+* hier wird ausgerechnet wie viele Invader in 80 % der Spielfeldbreite passen. Anschließend werden so viele Invader in ein Array gepusht.
+
+### function renderInvaderrow
+
+
+function renderInvaderRow(invaders) {
+ let currentInvXPos = invaders[rowId].posX;
+ for (let j = 0; j < invaders[rowId].invaders.length; j++) {
+ for (let i = 0; i < invaders[rowId].invaders[j].appearance.length; i++) {
+ renderStr = Helper.setCharsAt(renderStr,xyToStringPos(invaders[rowId].invaders[j].id + currentInvXPos, invaders[rowId].posY+i), invaders[rowId].invaders[j].appearance[i]);
+ }
+ currentInvXPos = currentInvXPos + invaderWidth* 2 + invaderWidth/2;
+ }
+ }
+
+* Diese Funktion läuft durch die aktuelle Invaderrow und deren Invader und schreibt diese anschließend in den Renderstring.
+
+### function renderBullets
+
+
+function renderBullets() {
+ currentSpaceshipBullets = currentSpaceshipBullets.filter(bullet => bullet.y > 1);
+ currentSpaceshipBullets.forEach((bullet) => {
+ bullet.y -= 1;
+ if (renderStr[xyToStringPos(bullet.x, bullet.y - 1)] == '#') {
+ let currentId = 0;
+ for (let invaderPos = invaders[rowId].posX; invaderPos <= invaders[rowId].posX + (invaderWidth * 2 + invaderWidth / 2); invaderPos = invaderPos + invaderWidth * 2 + invaderWidth / 2) {
+ if (bullet.x > invaderPos && bullet.x < invaderPos + invaderWidth * 2) {
+ invaders[rowId].invaders[currentId].ischBinKaputt = true;
+ invaders[rowId].invaders[currentId].explode();
+ invaderPoints++;
+ break;
+ }
+ currentId++;
+ }
+ currentSpaceshipBullets = currentSpaceshipBullets.filter(currentBullet => currentBullet != bullet);
+ }
+ if (renderStr[xyToStringPos(bullet.x, bullet.y - 1)] == '=') {
+ currentSpaceshipBullets = currentSpaceshipBullets.filter(currentBullet => currentBullet != bullet};
+ }
+ renderStr = Helper.setCharsAt(renderStr, xyToStringPos(bullet.x, bullet.y), "|");
+ })
+}
+
+
+* Ein Großteil dieser Funktion wurde von unserem Dozenten gecoded. Wir haben hier die Funktion hinzugefügt, die prüft, ob die Bullet den Invader trifft. Das funktioniert über einen abgleich ob sich im Feld über der Bullet ein Hashtag befindet, also der Character aus dem ein Invader besteht.
+Wenn dies der Fall ist wird nun abhängig von der aktuellen Anfangsposition der Invaderreihe ausgerechnet an welchem Invader sich die Bullet befindet, dann führt der getroffene Invader die Methode
+`explode()` aus, ausserdem wird eine Variable mit jedem Treffer um eins hochgezählt.
+Ausserdem wird die aktuell gerenderte Bullet aus dem currentSpaceshipBullets Array herausgefiltert, falls diese einen Invader getroffen hat.
+
+* Das gleiche Prinzip haben wir für die Obstacles übernommen, dass die aktuell gerenderte Bullet auch checkt ob sich über ihr ein `=` befindet, auch in diesem Fall wird die Bullet gelöscht.
+
+
+
+
+
+### Zusammenfassung
+Abläufe:
+* die Invaderreihe wird generiert und bewegt sich dann:
+
+* ein Invader wird abgeschossen:
+
+
+
+
+
+
+
+
+## ToDos
+
+1. Man muss die Invaders selber schießen lassen. Dies muss random passieren.
+
+2. Es sollen mehrere Reihen von Invaders aufeinander folgen.
+3. Das Hindernis muss bei Abschuss der Invader kaputt gehen.
+4. Wenn die Invader eine gewissen Punkt auf der y-Achse erreichen, sollte der Spieler verloren haben.
+5. Man kann noch eine Game Over/ Win Schrift einbauen.
+6. Wenn die Invader getroffen werden, erhöhen sie auch die Geschwindigkeit, damit es schwieriger wird sie Abzuschießen.
+7. Einen New Game Button, um das Spiel mit dem Button neu zu starten.
+8. Das Spaceship hat mehrere Leben und eine Lebensanzeige, die bei Treffer durch Invader weniger werden.
+9. Ein Invader Boss, der auftaucht und mehr Punkte bringt.
+10. Hintergrundmusik und Soundeffekte
+13. Verschiedene Level mit unterschiedlichen Schwierigkeitsstufen.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/classes.js b/classes.js
new file mode 100644
index 0000000..c120523
--- /dev/null
+++ b/classes.js
@@ -0,0 +1,92 @@
+class Helper {
+ static setCharsAt(str, index, chr) {
+ if (index > str.length - 1) return str;
+ return str.substr(0, index) + chr + str.substr(index + chr.length);
+ }
+}
+
+//Die constructor Methode ist eine spezielle Methode für das erzeugen und initialisieren von Objekten, die mit dem Schlüsselwort class erzeugt wurden.
+//gibt dem Invader sein Aussehen, den Status, ob er kaputt ist oder nicht, eine explodeTime und eine id
+class Invader {
+ constructor(appearance, ischBinKaputt, explodeTime, id) {
+ this.appearance = appearance;
+ this.id = id;
+ this.ischBinKaputt = ischBinKaputt;
+ this.explodeTime = explodeTime;
+ }
+ shootLaser() {
+ console.log("Invader " + this.id + " Laser shot")
+ }
+ //hier definieren wir das Aussehen des Invaders, beim Abschießen/explodieren dessen.
+ /*wir müssen darauf achten, dass man in jede Zeile 16 Zeichen setzt und es 5 Spalten gibt,
+ damit das Ganze symetrisch aussieht. (ganze Invader Breite: 16 und die Höhe beträgt 5)*/
+ explode() {
+ this.appearance = [" ",
+ " \\ | / ",
+ " - p u f f - ",
+ " / | \\ ",
+ " "
+ ];
+ }
+}
+
+//wir weisen der InvaderRow verschiedene Eigenschaften zu (Position, Größe, invaders und wir weisen der InvaderRow eine id zu)
+class InvaderRow {
+ constructor(posX, posY, width, height, invaders, id) {
+ this.id = id;
+ this.posX = posX;
+ this.posY = posY;
+ this.width = width;
+ this.height = height;
+ this.invaders = invaders;
+ }
+ //mit dieser Methode kann die Invaderrow sich selbst in die angegebene Richtung verschieben
+ step(direction) {
+ if (direction == 1) {
+ this.posX += 1;
+ }
+ if (direction == -1) {
+ this.posX -=1;
+ }
+ if (direction == "down") {
+ this.posY += 1;
+ }
+ }
+
+ //mit dieser Methode wird ein Invader generiert
+ static generateInvader(width, height) {
+ let currentInvader = [];
+ for (let y = 0; y < height; y++) {
+ currentInvader[y] = " ".repeat(width * 2 + 1);
+ for (let x = 0; x < width; x++) {
+ let randomNumber = Math.random();
+ if (randomNumber >= 0.5) { //Zahl ist größer oder gleich 0.5 dann wird an diese Stelle ein Hastag gesetzt
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], x, '#'));
+ currentInvader[y] = (Helper.setCharsAt(currentInvader[y], 2 * width - x, '#'));
+ }
+ }
+ }
+ return currentInvader;
+ }
+
+
+ static generateInvaderRow(invaderWidth, invaderHeight) {
+ let currentInvaders = [];
+ /*hier haben wir eine Formel erstellt, die berechnet wie viele Invaders in die Größe der cols (in unserem Fall 140) passen.
+ Die Formel ist so aufgestellt, dass man die cols Breite verändern kann und somit auch entsprechend Invader in die Viewbox gerendert werden.
+ */
+ let rowWidth = Math.floor(cols * 0.8); //Die Reihe der Invader soll 80 % der Breite einnehmen.
+ let wholeInvader = invaderWidth * 2; //ein Invader ist in unserem Fall (8 * 2) 16 groß (da der Invader in der Mitte gespiegelt wird)
+ let spacerWidth = invaderWidth / 2; //Der Space zwischen den Invadern solll die Hälfte des Invaders betragen
+ let numInvaders = Math.floor((rowWidth / ((wholeInvader + spacerWidth)))); //Hier wird die Anzahl der Invader berechnet
+ let invaderAppearance = InvaderRow.generateInvader(invaderWidth, invaderHeight); /* hier wird auf die Klasse InvaderRow zugegriffen
+ und dann auf die innere Klasse generateInvader */
+
+ //hier generiert die Reihe genau die Invader die sie beinhaltet
+ for (let i = 0; i < numInvaders; i++) {
+ let newInv = new Invader(invaderAppearance, false, 0, i);
+ currentInvaders.push(newInv);
+ }
+ return currentInvaders;
+ }
+}
\ No newline at end of file
diff --git a/coder2.JPG b/coder2.JPG
new file mode 100644
index 0000000..170f380
Binary files /dev/null and b/coder2.JPG differ
diff --git a/fastinvader1.wav b/fastinvader1.wav
new file mode 100644
index 0000000..e2dac5f
Binary files /dev/null and b/fastinvader1.wav differ
diff --git a/index.html b/index.html
index 3c31ba7..496be70 100644
--- a/index.html
+++ b/index.html
@@ -1,181 +1,242 @@
-
-
-
- - -- - + + //Es geht los - alle 40 Millisekunden rendern + newGame(); + setInterval(render, 40); + + \ No newline at end of file diff --git a/indexspace.html b/indexspace.html new file mode 100644 index 0000000..dc509b9 --- /dev/null +++ b/indexspace.html @@ -0,0 +1,231 @@ + + + + + +
+ ++ + + + + \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..88f2e33 --- /dev/null +++ b/style.css @@ -0,0 +1,39 @@ + +pre { + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + border: 1px solid gray; +} + +body { + color: white; + background-color: black; +} + +.scoreboard { + font-family: 'Righteous', cursive; + background-color: white; + color: black; + font-size: 50px; + text-align: center; + border: 1px solid white; + position: absolute; + top: 5vh; + right: 1.5vh; + width: 15ch; +} + +.spaceinvaders { + font-family: 'Righteous', cursive; + background-color: black; + color: white; + font-size: 50px; + text-align: center; + position: absolute; + top: 5vh; + right: 58vw; + width: 15ch; +} \ No newline at end of file