diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-04-17 20:44:47 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-04-17 20:44:47 +0200 |
| commit | c38d85decda449be5b7e557f6052d8ed3bd41cdc (patch) | |
| tree | 31982e5432272788f945951cae587b31b44bf552 /Info/10 | |
| parent | 102ab3bede6592dff2771fe5d818d0837f5d3308 (diff) | |
| download | unterricht-c38d85decda449be5b7e557f6052d8ed3bd41cdc.tar.gz unterricht-c38d85decda449be5b7e557f6052d8ed3bd41cdc.zip | |
significantly improve jumpnrun material
* mention combining of collision detection and handling
* specify the need to cast to InteractiveElement
Diffstat (limited to 'Info/10')
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag2.tex | 29 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag3.tex | 63 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/slides.md | 78 |
3 files changed, 86 insertions, 84 deletions
diff --git a/Info/10/2/JumpNRun/arbeitsauftrag2.tex b/Info/10/2/JumpNRun/arbeitsauftrag2.tex index d09cc882..65175949 100644 --- a/Info/10/2/JumpNRun/arbeitsauftrag2.tex +++ b/Info/10/2/JumpNRun/arbeitsauftrag2.tex @@ -87,6 +87,7 @@ für alle Objekte \end{defbox} Die Methode \mintinline{java}{getCollidingShapes(Group g)} eines Sprites gibt alle Objekte einer Gruppe \texttt{g} zurück, die mit dem \texttt{Sprite} kollidieren. +\label{subsection:collision-detection} Mit der \texttt{foreach}-Variante der \texttt{for}-Schleife können wir alle Kollisionen behandeln. @@ -108,6 +109,7 @@ Implementiere in der \mintinline{java}{void act()} des Spielers die Kollisionser \end{itemize} \subsection{\faIcon{desktop} Kollision behandeln} +\label{subsection:collision-handling} \begin{defbox}{Kollision was jetzt?} \begin{tabular}{p{0.37\textwidth} p{0.6\textwidth}} @@ -140,16 +142,39 @@ Implementiere im Spieler die Methode \mintinline{java}{void reactToCollisionWith \item Wiederholung die letzte Bewegung in die Richtung, die \emph{nicht} zur Kollision führt. \end{itemize} +\subsection*{\faIcon{desktop} Kollision erkennen \emph{und} behandeln} + +Der folgende Pseudocode beschreibt das Zusammenspiel der Erkennung von Kollision und ihrer anschließenden Behandlung. + +\begin{pseudocode} +\texttt{für alle überschneidenden Objekte} + +\hspace{5mm}\texttt{behandle Überschneidung} +\end{pseudocode} + +Wir wollen also unsere \textbf{Kollisionserkennung} \mintinline{java}{getCollidingShapes(Group group)} (Siehe: \ref{subsection:collision-detection}) mit unserer \textbf{Kollisionsbehandlung} \mintinline{java}{reactToCollisionWithShape(Shape shape)} (Siehe: \ref{subsection:collision-handling}) verbinden. + +\vspace{3mm} +\begin{center} +\textbf{Kollisionserkennung} \hspace{5mm} \faIcon{link} \hspace{5mm} \textbf{Kollisionsbehandlung} +\end{center} +\vspace{3mm} + +\begin{itemize} + \item Rufe mit \emph{jedem} kollidierenden Shape in \texttt{collidingShapes} die Methode \mintinline{java}{reactToCollisionWithShape} auf. +\end{itemize} + + \subsection{\faIcon{desktop} Auf dem Boden stehen} Bei Kollision \textbf{von oben} wollen wir erkennen, das wir auf festem Boden stehen! -Das erlaubt uns abzuspringen und gegebenenfalls eine Laufanimation anzuzeigen. +Das erlaubt Gravitation wirken zu lassen, abzuspringen und gegebenenfalls eine Laufanimation anzuzeigen. Das Attribut \mintinline{java}{Shape standsOn} der Klasse \texttt{Player} merkt sich auf welchem Shape der Spieler steht. \begin{itemize} \item (Ergänze das \texttt{standsOn} Attribut vom Typ \texttt{Shape} in der Klasse \texttt{Player}) -\item (Ändere die Gravitation zu einer Prüfung \mintinline{java}{standsOn == null}) +\item (Ändere die Prüfung, ob Gravitation wirkt zu: \mintinline{java}{standsOn == null}) \item Bei Kollision von \emph{oben}, speichere das kollidierende \texttt{shape} im Attribut \texttt{standsOn}. \item Überprüfe vor der Kollisionserkennung, ob der Spieler noch mit einem möglicherweise gespeicherten \texttt{standsOn} Objekt kollidiert. (\mintinline{java}{standOn != null && !collidesWith(standsOn)}) \item \emph{Falls nein} setze \texttt{standOn} auf \mintinline{java}{null} diff --git a/Info/10/2/JumpNRun/arbeitsauftrag3.tex b/Info/10/2/JumpNRun/arbeitsauftrag3.tex index 6ad4311a..c4285715 100644 --- a/Info/10/2/JumpNRun/arbeitsauftrag3.tex +++ b/Info/10/2/JumpNRun/arbeitsauftrag3.tex @@ -22,7 +22,7 @@ interface InteractiveElement { void onCollisionWithPlayer(Player player, JumpNRun jumpNRun); } \end{minted} -\item Ergänze die Klasse \texttt{Level} um das Attribut \texttt{interactiveObjects}, das die *Gruppe* aller interaktiver Objekte speichern soll. +\item Ergänze die Klasse \texttt{Level} um das Attribut \texttt{interactiveObjects}, das die \emph{Gruppe} aller interaktiver Objekte speichern soll. \item Zerstöre auch alle interaktiven Objekte, wenn das gesamte Level zerstört wird. (\textbf{Tipp:} \mintinline{java}|Level.destroy() { ... }|) \end{itemize} @@ -32,7 +32,10 @@ interface InteractiveElement { \begin{itemize} \item Ergänze die Methode \texttt{act} der Klasse \texttt{Player}, um die Kollisionserkennung mit allen interaktiven Objekten eines Levels. \\ (Tipp: Du kannst viel von der Kollisionserkennung der \texttt{solidObjekts} kopieren.) - \item Rufe für jedes kollidierende interaktive Objekt die Methode \texttt{onCollisionWithPlayer} mit dem Player Objekt (\mintinline{java}{this}) und dem gesamten \texttt{jumpNRun} Spiel-Objekts auf. + \item Rufe für jedes kollidierende interaktive Objekt die Methode \texttt{onCollisionWithPlayer} mit dem Player Objekt (\mintinline{java}{this}) und dem gesamten \texttt{jumpNRun} Spiel-Objekts auf. \\ + (\textbf{Hinweis}: Um die Methode \mintinline{java}{onCollisionWithPlayer(...)} aufzurufen, musst das Objekt vom Typ \texttt{InteractiveElement} sein. + Wandle das Shape mit dem \href{https://inf-schule.de/oop/java/experten/vererbung/konzept_typumwandlung}{Cast}: \mintinline{java}{((InteractiveElement)shape).onC...}) + \end{itemize} \subsubsection{\faIcon{desktop} Ziel in Sicht} @@ -56,9 +59,9 @@ Verändere das nun fertige Grundspiel nach deinen Vorstellungen. \begin{tcolorbox}[] \begin{itemize} - \item Ergänze eine Stopuhr pro Level. + \item Ergänze eine Stoppuhr pro Level. \item Füge sich bewegende Hindernisse/Gegner hinzu. - \item Ergänze Powerups die eingesammelt werden müssen. + \item Ergänze Powerups die eingesammelt werden können. \item Erweitere das Spiel um einen zweiten Spieler. \item ... \end{itemize} @@ -69,55 +72,3 @@ Verändere das nun fertige Grundspiel nach deinen Vorstellungen. Dieses Werk ist lizenziert unter einer \href{https://creativecommons.org/licenses/by-sa/4.0/}{CC BY-SA 4.0} Lizenz \faCreativeCommons\ \faCreativeCommonsBy\ \faCreativeCommonsSa. \end{document} - -% Damit unsere \textit{Snake}-Variante tatsächlich zu einem echten Spiel wird, müssen wir gewissen Ereignisse erkennen und behandeln. - -% \subsubsection{\faIcon{desktop} Interaktive Objekte verwalten} - -% Wenn der Kopf der Schlange das Essen berührt, soll das Essen verschwinden und die Schlange soll wachsen. -% \begin{defbox}{Kollision} -% \begin{tabular}{p{0.75\textwidth} p{0.5cm} p{0.2\textwidth}} -% \vspace{-1.8cm} -% Von einer Kollision spricht man, wenn zwei Objekte sich \textbf{überschneiden}. -% Eine solche Überschneidung zu erkennen kann je nach Form der Objekte kompliziert sein. -% Unsere Spieleengine \textit{GraphicAndGames} bietet dazu die Methode \mintinline{java}{GrafikSymbol.Schneidet(Area)} an. & & -% \begin{tikzpicture} -% \node[draw, opacity=0.7, minimum size=1.5cm, fill=red] {}; -% \node[circle, draw, minimum size=1cm, fill=blue] at (0.5, 0.5) {}; -% \end{tikzpicture} \\ -% \end{tabular} -% \end{defbox} - -% \begin{itemize} -% \item Implementiere eine Methode \mintinline{java}{beruehrt(Rechteck)} in der Klasse \texttt{Schlange}, die überprüft, ob der Kopf der Schlange ein anderes Rechteck schneidet (das \texttt{GrafikSymbol} der Klasse \texttt{Rechteck} ist dessen Attribut \texttt{symbol}, jedes \texttt{GrafikSymbol} hat wiederum ein Attribut \texttt{form} vom Typ \texttt{Area}). -% \item Ergänze die Methode \texttt{Ausführen} der Klasse \Snake{} um die Überprüfung, ob die Schlange das Essen berührt. Falls ja, entferne das Essen und rufe die \texttt{wachsen}-Methode der Schlange mit den Koordinaten des Essens auf. -% \end{itemize} - -% \subsubsection{\faIcon{desktop} Mit Interaktive Objekte interagieren} - -% Da es sich bei dem Rand der Welt nicht um ein Objekt handelt, können wir nicht auf die \texttt{beruehrt}-Methode der Klasse \texttt{Schlange} zurückgreifen. - -% \begin{itemize} -% \item Ändere die Methode \texttt{bewegen} der Klasse \texttt{Schlange}, sodass sie als Rückgabewert immer \mintinline{java}{true} liefert. -% \item Erweitere die Methode \texttt{bewegen} der Klasse \texttt{Schlange} um eine Überprüfung, ob der die Koordinaten des Kopfes außerhalb der Welt liegen (die Welt ist \textbf{800x600} Pixel groß). Falls der Kopf außerhalb der Welt liegt, soll \mintinline{java}{false} zurückgegeben werden. -% \end{itemize} - -% \subsubsection{\faIcon{desktop} Kollision mit sich selbst} -% Erweitere die Methode \texttt{bewegen} der Klasse \texttt{Schlange} um eine Überprüfung, ob der Kopf der Schlange eines der im folgenden Körperteile berührt (dazu kannst du auf die Methode \texttt{beruehrt} zurückgreifen). Falls ja, soll \mintinline{java}{false} zurückgegeben werden. - -% \subsection{\faIcon{desktop} Spielende} -% Nachdem die Methode \texttt{bewegen} eine Kollision festgestellt hat (Rückgabewert \mintinline{java}{false}) soll das Spiel beendet werden. - -% \begin{itemize} -% \item Implementiere eine Methode \texttt{gameOver} der Klasse \Snake{}, die das Spiel mittels der Methode \mintinline{java}{Zeichenfenster.TaktgeberStoppen();} anhält. -% \item Erweitere die Methode \texttt{gameOver} um die Ausgabe einer Nachricht. Die Klasse \texttt{Text} erlaubt es dir Text auf dem Zeichenfenster anzuzeigen. -% \end{itemize} - -% \subsection{\faIcon{desktop} Für Schnelle} -% Es fehlt unserem Spiel an einigen Ecken noch an Feinschliff. - -% \begin{itemize} -% \item Sorge dafür das Essen nur auf gerader Linie der Schlange erscheint (Ein Vielfaches der Seitenlänge des Rechtecks). -% \item Ergänze das Spiel um einen Highscore (du kannst bspw. das Attribut \texttt{ticks} wiederverwenden). -% \item Implementiere, dass die Geschwindigkeit des Spiels zunimmt. Du kannst die Taktfrequenz, in der die \texttt{Ausführen}-Methode aufgerufen wird, mit der Methode \mintinline{java}{Zeichenfenster.TaktdauerSetzen(ms);} ändern. -% \end{itemize} diff --git a/Info/10/2/JumpNRun/slides.md b/Info/10/2/JumpNRun/slides.md index c4191131..a7f620e0 100644 --- a/Info/10/2/JumpNRun/slides.md +++ b/Info/10/2/JumpNRun/slides.md @@ -506,7 +506,7 @@ Wir fallen einfach durch den Boden! \faIcon{lightbulb} Wie erkennen wir, dass zwei graphische Objekte sich berühren? \pause -Wir müssen prüfen, ob sie sich in \emph{mindestens} einem Punkt im Koordinatensystem überschneiden. +Wir müssen prüfen, ob sie sich in *mindestens* einem Punkt im Koordinatensystem überschneiden. \pause ```\begin{pseudocode}```{=latex} @@ -540,7 +540,7 @@ for (Shape shape: collidingShapes) { Implementiere in der `void act()`{.java} des Spielers die Kollisionserkennung. \let\tightlist\relax -* Speichere alle \emph{soliden} kollidierenden Objekte, des aktuellen Levels als Variable. +* Speichere alle *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}) @@ -556,13 +556,30 @@ Implementiere `void reactToCollisionWithShape(Shape shape)`{.java} im Spieler: * 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. - +* Wiederholung die letzte Bewegung in die Richtung, die *nicht* zur Kollision führt. + +## \faIcon{desktop} Arbeitsauftrag: Kollision behandeln 2 \hfill{} 5min + +```\begin{pseudocode}```{=latex} +``` +für alle überschneidenden Objekte + Behandle Überschneidung +``` +```\end{pseudocode}```{=latex} + +Wir wollen unsere **Kollisionserkennung** `getCollidingShapes(Group group)`{.java} mit unserer **Kollisionsbehandlung** `reactToCollisionWithShape(Shape shape)`{.java} verbinden. + +\begin{center} +\textbf{Kollisionserkennung} \hspace{5mm} \faIcon{link} \hspace{5mm} \textbf{Kollisionsbehandlung} +\end{center} + +* Rufe mit *jedem* kollidierenden Shape in `collidingShapes` die `reactToCollisionWithShape` Methode auf. ## \faIcon{desktop} Arbeitsauftrag: Auf dem Boden stehen \hfill{} 10min :::{.block} ### Wir wollen erkennen, wann wir auf festem Boden stehen! +* Nicht fallen * Springen erlauben * Laufanimation abspielen ::: @@ -570,10 +587,10 @@ Implementiere `void reactToCollisionWithShape(Shape shape)`{.java} im Spieler: Das Attribut `Shape standsOn`{.java} der Klasse `Player` merkt sich auf welchem Shape der Spieler steht. * (Ergänze das `standsOn` Attribut vom Typ `Shape` in der Klasse `Player`) -* (Ändere die Gravitation zu einer Prüfung `standsOn == null`{.java}) -* 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} +* (Ändere die Prüfung, ob Gravitation wirkt zu: `standsOn == null`{.java}) +* Bei Kollision von *oben*, speichere das kollidierende `shape` im Attribut `standsOn`. +* Überprüfe vor der Kollisionserkennung, ob der Spieler *nicht mehr* mit dem gespeicherten `standsOn` Objekt kollidiert. (`standOn != null && !collidesWith(standsOn)`{.java}) + * *Falls ja* setze `standOn` auf `null`{.java} ## {.standout} @@ -581,7 +598,7 @@ Wir wollen, dass etwas passiert! ## Erinnerung: Interaktive Elemente -Neben mehrere feste Plattformen soll ein Level auch **interaktive Elemente** enthalten. +Neben mehreren festen Plattformen soll ein Level auch **interaktive Elemente** enthalten. ::: {.columns} :::: {.column width=50%} @@ -612,8 +629,8 @@ Wir müssen sicherstellen, dass alle Objekte mit dem Player interagieren können \begin{tcolorbox}[colframe=yellow, colback=yellow!20, title=\textcolor{black}{\faIcon{lightbulb} Idee(n)}] \begin{itemize} - \item<2-> Gemeinsmane Oberklasse - \item<3-> \boldred{Interface} + \item<2-> Gemeinsame Oberklasse? (\textit{Keine gemeinsamen Attribute}) + \item<3-> \boldred{Interface}! \end{itemize} \end{tcolorbox} @@ -672,7 +689,7 @@ interface InteractiveElement { ## \faIcon{desktop} Arbeitsauftrag: Interaktive Objekte verwalten \hfill{} 10min \let\tightlist\relax -* Implementiere in einer neuen Datei das Interface `InteractiveElement`: +* Implementiere in einer *neuen Datei* das Interface `InteractiveElement`: ```java interface InteractiveElement { void onCollisionWithPlayer(Player player, JumpNRun jumpNRun); @@ -684,30 +701,40 @@ interface InteractiveElement { ## \faIcon{desktop} Arbeitsauftrag: Mit interaktiven Objekte interagieren \hfill{} 10min +\vspace{-0.2cm} +::: {.columns align=center} +:::: {.column width=55%} Damit etwas passiert, wenn der Spieler ein interaktives Objekt berührt, wollen wir `onCollisionWithPlayer(Player, JumpNRun)`{.java} bei einer Kollision aufrufen. +:::: -:::{.block} -### Interaktions Beispiele {.example} - -* Flagge wird berührt -> Level wechseln -* Gegner wird berührt -> Leben verlieren -* ...<M-Escape> +:::: {.column width=45%} +\begin{tcolorbox}[title=Interaktions Beispiele, colframe=green!80!black] + \small + \begin{itemize} + \setlength\itemsep{-2mm} + \item \textit{Flagge -> Level wechseln} + \item \textit{Gegner -> Leben verlieren} + \item \textit{...} + \end{itemize} +\end{tcolorbox} +:::: ::: +\let\tightlist\relax * Ergänze die Methode `act` der Klasse `Player`, um die Kollisionserkennung mit allen interaktiven Objekten eines Levels. - (Tipp: Du kannst viel von der Kollisionserkennung der `solidObjekts` kopieren.) + (**Tipp**: Du kannst viel von der Kollisionserkennung der `solidObjekts` kopieren.) * Rufe für jedes kollidierende interaktive Objekt die Methode `onCollisionWithPlayer` mit dem Player Objekt (`this`{.java}) und dem gesamten `jumpNRun` Spiel-Objekts auf. + (**Hinweis**: Um die Methode `onCollisionWithPlayer`{.java} aufzurufen, musst das Objekt vom Typ `InteractiveElement` sein. Wandle das Shape mit dem [Cast](https://inf-schule.de/oop/java/experten/vererbung/konzept_typumwandlung): `((InteractiveElement)shape).onC...`{.java}) ## \faIcon{desktop} Arbeitsauftrag: Ziel in Sicht \hfill{} 10min \let\tightlist\relax -* Implementiere die Klasse `Goal` die von der Klasse `Sprite` *erbt* und das Interface `InteraktiveElement` *implementiert*. - (`implements InteractiveElement`{.java}) +* Implementiere die Klasse `Goal` die von der Klasse `Sprite` **erbt** und das Interface `InteraktiveElement` **implementiert** (`implements InteractiveElement`{.java}). * Implementiere den Konstruktor der Klasse `Goal`. - * Wähle das Sprite *160* aus der Sprite-Bibliothek `SpriteLibrary.Plattforms` aus. + * Wähle das Sprite **160** aus der Sprite-Bibliothek `SpriteLibrary.Plattforms` aus. (`super(x, y, SpriteLibrary.Plattforms, 160);`{.java}) * Mit der Anweisung `playAnimation(160, 161, RepeatType.loop, 3);`{.java} lässt du die Flagge im "Wind" wehen. -* Implementiere die Methode `onCollisionWithPlayer` der Klasse `Goal` die zum nächsten Level weiter schaltet. +* Implementiere die Methode `onCollisionWithPlayer` der Klasse `Goal`, die zum nächsten Level weiter schaltet. (**Tipp:** Implementiere die Methode `JumpNRun.nextLevel(Level level)` und rufe sie mit dem Nachfolger des aktuellen Levels auf) ## \faIcon{desktop} Arbeitsauftrag: Baue dein eigenes Spiel @@ -715,13 +742,12 @@ Damit etwas passiert, wenn der Spieler ein interaktives Objekt berührt, wollen Verändere das nun fertige Grundspiel nach deinen Vorstellungen. ### Vorschläge {.example} -* Ergänze eine Stopuhr pro Level. +* Ergänze eine Stoppuhr pro Level. * Füge sich bewegende Hindernisse/Gegner hinzu. -* Ergänze Powerups die eingesammelt werden müssen. +* Ergänze Powerups die eingesammelt werden können. * Erweitere das Spiel um einen zweiten Spieler. * ... - ## {.standout} Dieses Werk ist lizenziert unter einer [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) Lizenz \faCreativeCommons\ \faCreativeCommonsBy\ \faCreativeCommonsSa. |
