diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-04-13 21:25:29 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-04-13 21:25:29 +0200 |
| commit | 68745ae09ec4a9583a9c48b84137207c61731249 (patch) | |
| tree | 8af3231dd706ee185cc2e6f712f1fe158361446d | |
| parent | 95ef32c5a7ddd5dd7aa93a1444bfc16da1eb676c (diff) | |
| download | unterricht-68745ae09ec4a9583a9c48b84137207c61731249.tar.gz unterricht-68745ae09ec4a9583a9c48b84137207c61731249.zip | |
add rough draft of the last part of the jumpnrun
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag3.tex | 134 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/slides.md | 147 |
2 files changed, 239 insertions, 42 deletions
diff --git a/Info/10/2/JumpNRun/arbeitsauftrag3.tex b/Info/10/2/JumpNRun/arbeitsauftrag3.tex index 936d4b71..6ad4311a 100644 --- a/Info/10/2/JumpNRun/arbeitsauftrag3.tex +++ b/Info/10/2/JumpNRun/arbeitsauftrag3.tex @@ -5,69 +5,119 @@ \usepackage[ngerman]{babel} \geometry{margin=2cm} -\newcommand{\Snake}{\texttt{Snake}} - -\title{Snake Arbeitsauftrag 3} +\title{JumpNRun Arbeitsauftrag 3} \setcounter{section}{3} \begin{document} \thispagestyle{empty} -\subsection{\faIcon{desktop} Kollisionserkennung} -Damit unsere \textit{Snake}-Variante tatsächlich zu einem echten Spiel wird, müssen wir gewissen Ereignisse erkennen und behandeln. - -\subsubsection{\faIcon{desktop} Kollision mit dem Essen} - -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} +\subsection{Interaktive Objekte} -\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} Interaktive Objekte verwalten} -\subsubsection{\faIcon{desktop} Kollision mit dem Rand} +\begin{itemize} +\item Implementiere in einer neuen Datei das Interface \texttt{InteractiveElement}: +\begin{minted}{java} +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 Zerstöre auch alle interaktiven Objekte, wenn das gesamte Level zerstört wird. + (\textbf{Tipp:} \mintinline{java}|Level.destroy() { ... }|) +\end{itemize} -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. +\subsubsection{\faIcon{desktop} Mit Interaktive Objekte interagieren} \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. + \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. +\end{itemize} -\subsection{\faIcon{desktop} Spielende} -Nachdem die Methode \texttt{bewegen} eine Kollision festgestellt hat (Rückgabewert \mintinline{java}{false}) soll das Spiel beendet werden. +\subsubsection{\faIcon{desktop} Ziel in Sicht} \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. +\item Implementiere die Klasse \texttt{Goal} die von der Klasse \texttt{Sprite} \emph{erbt} und das Interface \texttt{InteraktiveElement} \emph{implementiert}. + (\mintinline{java}{implements InteractiveElement}) +\item Implementiere den Konstruktor der Klasse \texttt{Goal}. +\begin{itemize} + \item Wähle das Sprite $160$ aus der Sprite-Bibliothek \texttt{SpriteLibrary.Plattforms} aus. \\ + (\mintinline{java}{super(x, y, SpriteLibrary.Plattforms, 160);}) + \item Mit der Anweisung \mintinline{java}{playAnimation(160, 161, RepeatType.loop, 3);} lässt du die Flagge im "Wind" wehen. +\end{itemize} +\item Implementiere die Methode \texttt{onCollisionWithPlayer} der Klasse \texttt{Goal} die zum nächsten Level weiter schaltet. \\ + (\textbf{Tipp:} Implementiere die Methode \mintinline{java}{JumpNRun.nextLevel(Level level)} und rufe sie mit dem Nachfolger des aktuellen Levels auf) \end{itemize} -\subsection{\faIcon{desktop} Für Schnelle} -Es fehlt unserem Spiel an einigen Ecken noch an Feinschliff. +\subsection{\faIcon{desktop} Baue dein eigenes Spiel} +Verändere das nun fertige Grundspiel nach deinen Vorstellungen. + +\begin{tcolorbox}[] \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. + \item Ergänze eine Stopuhr pro Level. + \item Füge sich bewegende Hindernisse/Gegner hinzu. + \item Ergänze Powerups die eingesammelt werden müssen. + \item Erweitere das Spiel um einen zweiten Spieler. + \item ... \end{itemize} +\end{tcolorbox} + \vfill 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 bff23279..c4191131 100644 --- a/Info/10/2/JumpNRun/slides.md +++ b/Info/10/2/JumpNRun/slides.md @@ -577,4 +577,151 @@ Das Attribut `Shape standsOn`{.java} der Klasse `Player` merkt sich auf welchem ## {.standout} +Wir wollen, dass etwas passiert! + +## Erinnerung: Interaktive Elemente + +Neben mehrere feste Plattformen soll ein Level auch **interaktive Elemente** enthalten. + +::: {.columns} +:::: {.column width=50%} +\begin{center} +\begin{tikzpicture} + \begin{class}[text width=4cm]{InteraktivesObjekt}{0,-3.5} + \attribute{?} + \attribute{?} + \operation{onCollision(player)} + \end{class} + + \begin{class}[text width=4cm]{Level}{0,0} + \attribute{festeObjekte} + \attribute{\textcolor{red}{interaktiveObjekte}} + \end{class} + \association{Plattform}{n}{}{Level}{enthält}{1}; +\end{tikzpicture} +\end{center} +:::: + +:::: {.column width=50%} + +:::: +::: + +## Mehrere Klassen mit den gleichen Methoden? +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} +\end{itemize} +\end{tcolorbox} + +::: {.columns} +:::: {.column width=70%} +\pause\pause\pause +\vspace{0.1cm} +Ein neues \boldred{Interface}: +```java +interface InteractiveElement { + void onCollisionWithPlayer(Player player, + JumpNRun jumpNRun); +} +``` +:::: + +:::: {.column width=30%} +\only<4->{ +\begin{tikzpicture} +\node[fill=magenta!20, line width=1pt, draw, minimum height=1cm, minimum width=3cm, rounded corners=5pt] (v) {Interakt. Objekt}; +\node[fill=bg, minimum height=1cm, minimum width=3cm, rounded corners=5pt, above=-0.1cm of v] (e) {Player}; +\draw[line width=1pt, rounded corners=5pt, fill=bg] ($(v.north west) + (0, 1cm)$) -- + ($(v.north east) + (0, 1cm)$) -- + (v.north east) {[sharp corners] -- + ($(v.north east) - (0.625cm, 0)$) -- + ($(v.north east) - (0.6cm, 0.2cm)$) -- + ($(v.north east) - (0.8cm, 0.2cm)$) -- + ($(v.north east) - (0.775cm, 0)$) -- + ($(v.north east) - (1.525cm, 0)$) -- + ($(v.north east) - (1.5cm, 0.2cm)$) -- + ($(v.north east) - (1.7cm, 0.2cm)$) -- + ($(v.north east) - (1.675cm, 0)$) -- + ($(v.north east) - (2.425cm, 0)$) -- + ($(v.north east) - (2.4cm, 0.2cm)$) -- + ($(v.north east) - (2.6cm, 0.2cm)$) -- + ($(v.north east) - (2.575cm, 0)$)} -- + (v.north west) -- + ($(v.north west) + (0, 1cm)$); + +\draw[line width=1pt, red] ($(v.north east) + (0.1cm, 0.2cm)$) -- + ($(v.north east) - (-0.1cm, 0.3cm)$) -- + ($(v.north west) - (0.1cm, 0.3cm)$) -- + ($(v.north west) + (-0.1cm, 0.2cm)$) -- + ($(v.north east) + (0.1cm, 0.2cm)$); + +\draw[-Latex, bend left=35, line width=0.75pt] ($(e.east) + (0, 1mm)$) to ($(v.east)-(0,1mm)$); +\node[minimum height=1cm, above=-0.1cm of v] (e) {Player}; + +\node[rotate=90] at ($(v.north west) - (0.3cm, 0.0cm)$) {\boldred{interface}}; +\end{tikzpicture} +} + +:::: +::: + +## \faIcon{desktop} Arbeitsauftrag: Interaktive Objekte verwalten \hfill{} 10min + +\let\tightlist\relax +* Implementiere in einer neuen Datei das Interface `InteractiveElement`: + ```java + interface InteractiveElement { + void onCollisionWithPlayer(Player player, JumpNRun jumpNRun); + } + ``` +* Ergänze die Klasse `Level` um das Attribut `interactiveObjects`, das die *Gruppe* aller interaktiver Objekte speichern soll. +* Zerstöre auch alle interaktiven Objekte, wenn das gesamte Level zerstört wird. + (**Tipp:** `Level.destroy() { ... }`{.java}) + +## \faIcon{desktop} Arbeitsauftrag: Mit interaktiven Objekte interagieren \hfill{} 10min + +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> +::: + +* 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.) +* Rufe für jedes kollidierende interaktive Objekt die Methode `onCollisionWithPlayer` mit dem Player Objekt (`this`{.java}) und dem gesamten `jumpNRun` Spiel-Objekts auf. + +## \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 den Konstruktor der Klasse `Goal`. + * 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. + (**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 + +Verändere das nun fertige Grundspiel nach deinen Vorstellungen. + +### Vorschläge {.example} +* Ergänze eine Stopuhr pro Level. +* Füge sich bewegende Hindernisse/Gegner hinzu. +* Ergänze Powerups die eingesammelt werden müssen. +* 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. |
