aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Info/10/2/JumpNRun/img/oide_mouse_coordinates.pngbin0 -> 6562 bytes
-rw-r--r--Info/10/2/JumpNRun/slides.md289
2 files changed, 123 insertions, 166 deletions
diff --git a/Info/10/2/JumpNRun/img/oide_mouse_coordinates.png b/Info/10/2/JumpNRun/img/oide_mouse_coordinates.png
new file mode 100644
index 00000000..27482880
--- /dev/null
+++ b/Info/10/2/JumpNRun/img/oide_mouse_coordinates.png
Binary files differ
diff --git a/Info/10/2/JumpNRun/slides.md b/Info/10/2/JumpNRun/slides.md
index afac3e84..16c4d61c 100644
--- a/Info/10/2/JumpNRun/slides.md
+++ b/Info/10/2/JumpNRun/slides.md
@@ -40,12 +40,14 @@ aspectratio: 169
* Bewegen
* Springen
-\vspace{-0.3cm}
+\vspace{-0.2cm}
### Flagge
+\vspace{-0.3cm}
* Position
-\vspace{-0.3cm}
+\vspace{-0.2cm}
### Plattform
+\vspace{-0.3cm}
* Position
* Höhe
* Breite
@@ -108,7 +110,7 @@ aspectratio: 169
\attribute{interaktiveObjekte}
\end{class}
- \begin{class}[text width=3cm]{Spiel}{0,-2.5}
+ \begin{class}[text width=3cm]{Spiel}{0,-4.5}
\attribute{level}
\attribute{player}
\end{class}
@@ -142,15 +144,15 @@ aspectratio: 169
\attribute{Level}
\attribute{Player}
\end{class}
- \association{Spiel}{}{}{Spieler}{1}{};
+ \association{Spiel}{}{enthält}{Spieler}{1}{};
\begin{class}[text width=3cm]{Level}{1,-4.5}
\attribute{festeObjekte}
\attribute{interaktiveObjekte}
\end{class}
- \association{Spiel}{}{}{Level}{1}{};
+ \association{Spiel}{}{ist aktiv}{Level}{1}{};
\association{Level}{}{}{Flagge}{}{};
- \association{Level}{}{}{Platform}{n}{};
+ \association{Level}{}{enthält}{Platform}{n}{};
\end{tikzpicture}
## {.standout}
@@ -234,13 +236,13 @@ solange Spiel aktiv <- Online-IDE
::: {.columns}
:::: {.column width=75%}
-Wir erfüllen mit unserer `Spieler`-Klasse das \boldred{interface}, das die Online-IDE vorgibt.
+Wir erfüllen mit unserer Spieler Klasse das \boldred{interface}, das die Online-IDE vorgibt.
\vspace{0.1cm}
Ein Interface gibt zu implementierende Methoden vor.
\vspace{0.1cm}
-Um automatisch das Interface zu erfüllen, erben wir von der Klasse `Actor`.
+Um automatisch das Interface zu erfüllen, erben wir von der Klasse `Sprite` bzw. `Actor`.
::::
:::: {.column width=25%}
@@ -284,7 +286,7 @@ Um automatisch das Interface zu erfüllen, erben wir von der Klasse `Actor`.
\pause
**Java**
-`class Player extends Actor`{.java}
+`class Player extends Sprite`{.java}
\pause
@@ -351,6 +353,31 @@ Wir haben die Methoden bereits von der Klasse `Actor` geerbt.
* `boolean isKeyDown(String key)`{.java}
* `boolean isKeyUp(String key)`{.java}
+## Koordinaten in der Online-IDE
+
+Die Online-IDE benutzt ein Koordinatensystem, dessen \boldred{Ursprung} in der **linken oberen** Ecke liegt.
+
+::: {.columns}
+:::: {.column width=40%}
+\begin{tikzpicture}
+\node at (-0.5, 0.5) {\small $(0, 0)$};
+\node at (1.5, 0.25) {\small $x$};
+\draw[->] (0, 0) -- (3, 0);
+\node at (3, 0.5) {\small $(800,0)$};
+\draw[->] (0, 0) -- (0, -3);
+\node at (-0.25, -1.5) {\small $y$};
+\node at (-0.5, -3.3) {\small $(0,600)$};
+\end{tikzpicture}
+::::
+
+:::: {.column width=60%}
+![](img/oide_mouse_coordinates.png){.center height=60%}
+
+Die Koordinaten des Mauszeigers werden über dem Spielfeld angezeigt.
+::::
+:::
+
+
## \faIcon{desktop} Arbeitsauftrag: Los gehts! \hfill 10 min
\let\tightlist\relax
@@ -361,14 +388,14 @@ Wir haben die Methoden bereits von der Klasse `Actor` geerbt.
## \faIcon{desktop} Arbeitsauftrag: Spieler bewegen \hfill 15 min
-Vervollständige die Methode `act` des Spielers
+Vervollständige die Methode `act` des Spielers.
* Die Figur soll sich entsprechend ihrer Geschwindigkeit in X-Richtung (`vx`) horizontal bewegen.
- **Tipp**: Verwende die Methode `move(double deltaX, double deltaY)`{.java} der Klasse `Sprite`
+ **Tipp**: Verwende die Methode `move(double deltaX, double deltaY)`{.java} der Klasse `Sprite`.
* *Falls* eine Pfeiltaste gedrückt wird, soll sich Figur mit der Geschwindigkeit `speed` in die entsprechende Richtung bewegen.
**Tipp**: Verwende die Methode `isKeyDown(int key)`{.java} mit den beiden Pfeiltasten: `Key.ArrowLeft`{.java} und `Key.ArrowRight`{.java}
* Wird **keine** der beiden Tasten gedrückt, soll die Figur abbremsen.
- Setzte ihre Geschwindigkeit in X-Richtung auf $80%$ des aktuellen Werts.
+ Setzte ihre Geschwindigkeit in X-Richtung auf $80\%$ des aktuellen Werts.
\faIcon{play} Teste deine Implementierung.
@@ -384,7 +411,7 @@ Vervollständige die Methode `act` des Spielers
## \faIcon{desktop} Arbeitsauftrag: Springen \hfill 10 min
-*Falls* die Figur auf dem Boden steht, d.h. ihr Mittelpunkt einen Y-Wert *größer gleich* 350 hat, **und** die Pfeiltaste nach oben gedrückt ist `Key.ArrowUp` soll sich ihre Geschwindigkeit in Y-Richtung `vy` um `sprung` erhöhen.
+*Falls* die Figur auf dem Boden steht, d.h. ihr Mittelpunkt einen Y-Wert *größer gleich* 350 hat, **und** die Pfeiltaste nach oben gedrückt ist `Key.ArrowUp`, \newline soll sich ihre Geschwindigkeit in Y-Richtung `vy` um `sprung` erhöhen.
\faIcon{play} Teste deine Implementierung.
@@ -404,11 +431,13 @@ Die Figur soll in die Richtung ihrer Bewegung blicken.
## Plattformen und Level
+Ein Level soll mehrere feste Plattformen haben.
+
::: {.columns}
:::: {.column width=50%}
\begin{center}
\begin{tikzpicture}
- \begin{class}[text width=4cm]{Plattform}{0,-4.5}
+ \begin{class}[text width=4cm]{Plattform}{0,-3.5}
\attribute{position}
\attribute{hoehe}
\attribute{breite}
@@ -418,11 +447,9 @@ Die Figur soll in die Richtung ihrer Bewegung blicken.
\attribute{festeObjekte}
\attribute{interaktiveObjekte}
\end{class}
+ \association{Plattform}{n}{}{Level}{enthält}{1};
\end{tikzpicture}
\end{center}
-
-\vspace{1cm}
-Ein Level soll mehrer feste Plattformen haben.
::::
:::: {.column width=50%}
@@ -430,196 +457,126 @@ Ein Level soll mehrer feste Plattformen haben.
::::
:::
-<!--
-## Zufall
+## \faIcon{lightbulb} Plattformen und Level
-Die Java Klasse `java.util.Random` stellt *pseudo* zufällige Zahlen bereit.
+### Klassiker
-\pause
-### Verwendung
+Wie speichern wir mehrere Plattformen in einem Level?
-* Importieren der Klasse: `import java.util.Random;`
-* Deklarieren und Initialisieren eins Attributs vom Typ `Zufall`.
-* Die Methode `nextInt(int max)` liefert eine Zahl zwischen 0 und `max`.
-
-**\faIcon{lightbulb} In welchem Bereich soll das Essen platziert werden?**
+\pause$\rightarrow$ mit einem Feld (`Platform[]`{.java})!
\pause
-### Größe des Welt
+### **Besser:** `Group`
-Das Zeichenfenster misst 800x600 Pixel.
+Die Online-IDE bietet die Klasse `Group` zur Verwaltung mehrer graphischer Objekte (`Shape`).
-## Tischlein deck dich
+**Methoden**:
-::: {.columns}
-:::: {.column width=50%}
-![](img/tischlein_deck_dich.png)
-::::
-
-:::: {.column width=50%}
-```java
-void Ausführen() {
- ticks++;
- if (ticks % 30 == 0) {
- if (essen) {
- essen.entfernen();
- }
- int x = zufall.nextInt(780);
- int y = zufall.nextInt(580);
- essen = new Essen(x, y);
- }
- ...
-}
-```
-::::
-:::
+* `void add(T shape)` - Fügt ein Objekt der Gruppe hinzu
+* `void destroyAllChildren()` - Zerstört alle Objekte der Gruppe
+* ...
+## \faIcon{desktop} Arbeitsauftrag: Level1 \hfill{} 15min
-## Wachstum
+\let\tightlist\relax
+* (Implementiere die Klasse `Level`)
+* Implementiere die Klasse `Level1`, die von der Klasse `Level` erbt.
+ * Erzeuge ein `Rectangle` für den Boden.
+ * Erzeuge ein `Rectangle` als linke Spielrand-Begrenzung.
+ * Erzeuge vier `Rectangle` als aufsteigende Platformen.
+ Vorschlag: `new Rectangle(200 + 450 * i, 470 - 40 * i, 300, 25)`{.java}
+ * Füge alle erzeugten Rechtecke der `solidObjekt` Gruppe hinzu.
+* Die Methode `Level next()`{.java} soll nichts zurückgeben, da es kein zweites Level gibt (`return null;`{.java}).
+* Implementiere die Methode `void spawnPlayer(Player player)`{.java} und setzte das `player` Objekt an eine geeignete Startposition (`100, 400`).
-Die Schlange soll im Laufe des Spiels länger werden.
+## \faIcon{desktop} Arbeitsauftrag: Spielstart \hfill{} 5min
-**\faIcon{lightbulb} Welcher Datentyp eignet sich dazu eine unbekannte Anzahl an Rechtecken zuspeichern?**
-\pause
+Vervollständige den Konstruktor der Klasse `JumpNRun`.
-### Das Attribut `koerper`
+\let\tightlist\relax
+* Erzeuge in `Level1` Objekt und initialisiere damit das `Level` Attribut der Klasse `JumpNRun`.
+* Rufe die `spawnPlayer`-Methode des ersten Levels mit dem `Player` Attribute der Klasse `JumpNRun` auf.
-* Das Attribut `koerper` der Klasse `Schlange` vom Typ `Rechteck[]` verwaltet alle Körperteile
-* Felder haben eine **feste** Länge, deshalb muss jedes mal ein neues größeres Feld erzeugt werden und die einzelnen Rechtecke von dem alten Feld in das neue Kopiert werden.
+\faIcon{play} Teste deine Implementierung.
-## Bewegung
+## {.standout}
-**\faIcon{lightbulb} Wie kommt die Schlange um die Ecke?**
+Wir fallen einfach durch den Boden!
-\pause
+## \only<2->{Kollision}
-::: {.columns align=center}
-:::: {.column width=50%}
-\only<3>{Jedes Körperteil folgt seinem Vorgänger.}
-::::
+\faIcon{lightbulb} Wie erkennen wir, dass zwei graphische Objekte sich berühren?
-:::: {.column width=50%}
-![](img/Copyrighted/caterpillar_movement.png){.center width=100%}
-::::
-:::
-
-## Bewegung
+\pause
+Wir müssen prüfen, ob sie sich in \emph{mindestens} einem Punkt im Koordinatensystem überschneiden.
-```java
-void bewegen() {
- for (int i = koerper.length - 1; i > 0; i--) {
- Rechteck vorgaenger = koerper[i-1];
- koerper[i].PositionSetzen(vorgaenger.x, vorgaenger.y);
- }
-
- Rechteck kopf = koerper[0];
- // Kopf je nach aktueller Richtung verschieben
- // kopf.Verschieben()
- ...
-}
+\pause
+```\begin{pseudocode}```{=latex}
```
+für alle Objekte
+ für alle anderen Objekte
+ Finde Überschneidung
+ Falls Überschneidung
+ Behandle Überschneidung
+```
+```\end{pseudocode}```{=latex}
-# Phase III - Kollisionserkennung
-
-## Wann frisst die Schlange das Essen
-
-::: {.columns align=center}
-:::: {.column width=50%}
-\vspace{0.3cm}
-![](img/snake_eating.png)
-::::
-
-:::: {.column width=50%}
-Berührt der Kopf das Essen?
-::::
-:::
+## Kollision: Online-IDE
-## Wann frisst die Schlange das Essen
+Damit wir nicht selbst prüfen müssen, ob sich Objekte berühren, fragen wir einfach die Online-IDE.
-### \faIcon{lightbulb} Wo findet die Überprüfung statt?
-\pause
-In der `Ausführen`-Methode der Welt-Klasse `Snake`, da
+Die Methode `getCollidingShapes(Group g)`{.java} eines `Sprite` Objektes gibt alle Objekte einer Gruppe `g` zurück, die mit dem `Sprite` kollidieren.
->- dort Schlange und Essen bekannt sind
->- dort die Schlange bewegt wird
+Mit der `foreach`-Variante der `for`-Schleife können wir alle Kollisionen behandeln.
-\pause
-### Pseudocode
-```
-Schlange bewegen
-Falls Kopf das Essen berührt
- entferne Essen
- Schlange wachse
+```java
+Shape[] collidingShapes = getCollidingShapes(jumpNRun.level.solidObjects);
+for (Shape shape: collidingShapes) {
+ // Behandle Kollision
+}
```
-## Kollision mit dem Rand der Welt
-
-::: {.columns align=center}
-:::: {.column width=50%}
-\vspace{0.3cm}
-![](img/snake_crash.png)
-::::
+## \faIcon{desktop} Arbeitsauftrag: Kollision erkennen \hfill{} 5min
-:::: {.column width=50%}
-Ist die Position des Kopfes noch Teil der Welt?
-::::
-:::
+Implementiere in der `void act()`{.java} des Spielers die Kollisionserkennung.
-## Kollision mit dem Rand der Welt
+\let\tightlist\relax
+* Speichere alle \emph{soliden} kollidierenden Objekte, des aktuellen Levels als Variable.
+ (`Shape[] collidingShapes = getCollidingShapes(jumpnrun.level.solidObjects);`{.java}
+* Implementiere eine `foreach`-Wiederholung, die alle kollidierenden Objekte behandeln soll.
+ (`for(Shape shape: collidingShapes) {}`{.java}
-### \faIcon{lightbulb} Wo findet die Überprüfung statt?
-\pause
-In der `bewegen`-Methode der Klasse `Schlange`, nachdem der Kopf bewegt wurde
+## \faIcon{desktop} Arbeitsauftrag: Kollision behandeln \hfill{} 10min
-### \faIcon{lightbulb} Woher weiß das Spiel das die Schlange kollidiert ist?
-\pause
-Die Methode `bewegen` gibt einen Wahrheitswert zurück, ob sie erfolgreich war.
+\begin{tcolorbox}[colframe=yellow, colback=yellow!20, title=\textcolor{black}{\faIcon{lightbulb} Idee}]
+Der Spieler, soll die aktuelle Bewegung, die zur Kollision geführt hat, rückgängig machen, bis es zu keiner Kollision mehr kommt.
+\end{tcolorbox}
-\pause
-### Pseudocode
-```
-Koerper bewegen
-Kopf bewegen
-Falls kopf.x < 0 oder kopf.x > Weltbreite
- oder kopf.y < 0 oder kopf.y > Welthöhe
- return false
-return true
-```
+Implementiere `void reactToCollisionWithShape(Shape shape)`{.java} im Spieler:
-## Kollision mit sich selbst
+* Bestimme die Richtung, aus der der Spieler mit `shape` kollidiert ist. (`Direction direction = directionRelativeTo(shape);`{.java})
+* Setze je nach Richtung (`top`, `left`, `right`, `bottom`), die Geschwindigkeit dieser Richtung auf 0.
+* Mache die letzte Bewegung mit `moveBackFrom(shape, false)`{.java} rückgängig. (`moveBackFrom(Shape otherShape, boolean keepColliding)`{.java})
+* Wiederholung die letzte Bewegung in die Richtung, die \emph{nicht} zur Kollision führt.
+
-::: {.columns align=center}
-:::: {.column width=50%}
-\vspace{0.3cm}
-![](img/snake_eating_itself.png)
-::::
+## \faIcon{desktop} Arbeitsauftrag: Auf dem Boden stehen \hfill{} 10min
-:::: {.column width=50%}
-Berührt der Kopf der Schlange eins der eigenen Körperteile?
-::::
+:::{.block}
+### Wir wollen erkennen, wann wir auf festem Boden stehen!
+* Springen erlauben
+* Laufanimation abspielen
:::
-## Kollision mit sich selbst
-### \faIcon{lightbulb} Wo findet die Überprüfung statt?
-\pause
-In der `bewegen`-Methode der Klasse `Schlange`, nachdem die Schlange bewegt wurde.
+Das Attribut `Shape standsOn`{.java} der Klasse `Player` merkt sich auf welchem Shape der Spieler steht.
-\pause
-### Pseudocode
-```
-Koerper bewegen
-Kopf bewegen
-...
-
-Für jedes koerperteil hinter dem kopf
- Falls kopf beruehrt koerperteil
- return false
-
-return true
-```
+* (Ergänze das `standsOn` Attribut vom Typ `Shape` in der Klasse `Player`)
+* (Ändere die Gravitation zu einer Prüfung `standsOn == null`)
+* Bei Kollision von \emph{oben}, speichere das kollidierende `shape` im Attribut `standsOn`.
+* Überprüfe vor der Kollisionserkennung, ob der Spieler noch mit einem möglicherweise gespeicherten `standsOn` Objekt kollidiert. (`standOn != null && !collidesWith(standsOn)`{.java})
+* \emph{Falls nein} setze `standOn` auf `null`{.java}
## {.standout}
Dieses Werk ist lizenziert unter einer [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) Lizenz \faCreativeCommons\ \faCreativeCommonsBy\ \faCreativeCommonsSa.
--->