diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-02-28 09:32:30 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-02-28 09:32:30 +0100 |
| commit | 3af041fb5f8cf401a07360f773c74cfd4922b150 (patch) | |
| tree | 094979a71e5f39cfcd2abc8d2f66d3024e538d23 /Info | |
| parent | 61e6803a769686bd39a4a124415d1366617d144b (diff) | |
| download | unterricht-3af041fb5f8cf401a07360f773c74cfd4922b150.tar.gz unterricht-3af041fb5f8cf401a07360f773c74cfd4922b150.zip | |
add initial state of jumpnrun mini project
Diffstat (limited to 'Info')
| -rw-r--r-- | Info/10/2/JumpNRun/.gitignore | 1 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/.vis-lspc-settings.json | 10 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag1.tex | 184 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag2.tex | 103 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/arbeitsauftrag3.tex | 73 | ||||
| -rw-r--r-- | Info/10/2/JumpNRun/img/jumpnrun.png | bin | 0 -> 20085 bytes | |||
| -rw-r--r-- | Info/10/2/JumpNRun/lehrer_arbeitsauftrag1.pdf | bin | 0 -> 210923 bytes | |||
| -rw-r--r-- | Info/10/2/JumpNRun/slides.md | 625 |
8 files changed, 996 insertions, 0 deletions
diff --git a/Info/10/2/JumpNRun/.gitignore b/Info/10/2/JumpNRun/.gitignore new file mode 100644 index 00000000..f24158f3 --- /dev/null +++ b/Info/10/2/JumpNRun/.gitignore @@ -0,0 +1 @@ +arbeitsauftrag?.pdf diff --git a/Info/10/2/JumpNRun/.vis-lspc-settings.json b/Info/10/2/JumpNRun/.vis-lspc-settings.json new file mode 100644 index 00000000..9408be41 --- /dev/null +++ b/Info/10/2/JumpNRun/.vis-lspc-settings.json @@ -0,0 +1,10 @@ +{ + "ltex": + { + "latex": + { + "commands": {"\\texttt{}": "dummy"} + }, + "dictionary": {"de-DE": ["Snake"]} + } +} diff --git a/Info/10/2/JumpNRun/arbeitsauftrag1.tex b/Info/10/2/JumpNRun/arbeitsauftrag1.tex new file mode 100644 index 00000000..56340c65 --- /dev/null +++ b/Info/10/2/JumpNRun/arbeitsauftrag1.tex @@ -0,0 +1,184 @@ +\documentclass{handout} +\csname endofdump\endcsname +\usepackage{minted} +\usepackage{hyperref} +\usepackage[ngerman]{babel} +\usepackage{hyperref} +\geometry{margin=2cm} + +\title{JumpNRun Arbeitsauftrag 1} +\setcounter{section}{1} + +\begin{document} +\thispagestyle{empty} + +\subsection{\faIcon{pencil-alt} Modellierung} + +\begin{tabularx}{\textwidth}{p{0.5\textwidth} p{0.4\textwidth}} +\vspace{-5cm} +\begin{itemize} +\item Erstelle ein Klassendiagramm mit allen \textbf{Klassen}, die du im linken Screenshot ausmachen kannst. +\item Notiere die \textbf{Attribute}, die du sehen kannst und die, die Klassen haben müssen. +\item Notiere die \textbf{Methoden}, die die Klassen vermutlich haben. +\item Zeichne und beschrifte die Beziehungen zwischen den Klassen. +\end{itemize} +& +\includegraphics[keepaspectratio, width=0.4\textwidth]{img/jumpnrun.png} \\ +\end{tabularx} + +\begin{defbox}{Klassendiagramm} +\iflehrer{ +\begin{center} +\begin{tikzpicture} + \begin{class}[text width=3cm]{Spieler}{0,0} + \attribute{geschwindigkeit} + \attribute{position} + \operation{bewegen()} + \operation{springen()} + \end{class} + + \begin{class}[text width=3cm]{Flagge}{0,-4.5} + \attribute{position} + \end{class} + + \begin{class}[text width=3cm]{Platform}{5,-2.5} + \attribute{position} + \attribute{hoehe} + \attribute{breite} + \end{class} + \association{Spieler}{steht auf}{}{Platform}{}{}; + \association{Spieler}{erreicht}{}{Flagge}{}{}; +\end{tikzpicture} +\end{center} +}{\vspace{6cm}} +\end{defbox} + +\subsection*{Nutzereingabe} + +\begin{defbox}{Nutzereingabe} +\begin{tabularx}{\textwidth}{p{0.65\textwidth} p{0.05\textwidth} p{0.3\textwidth}} + Eine \boldred{Spiel-Engine} nimmt uns die meiste Arbeit ab, indem sie in einer Schleife die Nutzereingabe entgegen nimmt und an unser Spiel zur Verarbeitung weiterleitet. \\[12mm] + Unser Spiel übernimmt die Verarbeitung und teilt der Spiel-Engine die Veränderungen auf dem Bildschirm mit damit eine neue Ausgabe erzeugt werden kann. + && +\vspace{-1.85cm} +\begin{tikzpicture} + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt] (e) {Eingabe}; + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt, below=of e] (v) {Verarbeitung}; + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt, below=of v] (a) {Ausgabe}; + + \draw[-{Triangle}, line width=1pt] (e) to (v); + \draw[-{Triangle}, line width=1pt] (v) to (a); + + \draw[-{Triangle}, line width=1pt, dashed] + (a.east) -- + ($(a.east) + (0.5, 0)$) -- + ($(e.east) + (0.5, 0)$) -- + (e.east); +\end{tikzpicture} \\[0.5cm] +\end{tabularx} +\end{defbox} + +\begin{defbox}{Schnittstelle} +\begin{tabularx}{\textwidth}{p{0.65\textwidth} p{0.05\textwidth} p{0.3\textwidth}} +\vspace{-2cm} +Um in die Schleife integriert zu werden, müssen unsere Klassen von der Oberklasse \texttt{Actor} direkt oder über die Klasse \texttt{Sprite} erben. && +\begin{tikzpicture} +\node[line width=1pt, draw, minimum height=1cm, minimum width=3cm, rounded corners=5pt] (v) {Verarbeitung}; +\node[fill=white, line width=1pt, minimum height=1cm, minimum width=3cm, rounded corners=5pt, above=-0.1cm of v] (e) {Eingabe}; +\draw[line width=1pt, rounded corners=5pt] ($(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)$); + +\node[rotate=90] at ($(v.north west) - (0.3cm, 0.0cm)$) {\boldred{interface}}; +\end{tikzpicture} \\ +\end{tabularx} +\end{defbox} + +\subsection{\faIcon{desktop} Los gehts!} + +\begin{itemize} +\item Öffne das \textbf{JumpNRun Vorlage1} Projekt +\item Untersuche die bereits vorhandenen Klassen +\item Ergänze die Klasse \texttt{Player} um die Attribute: \texttt{vx}, \texttt{speed} vom Typ \mintinline{java}{double} +\item Initialisiere \texttt{vx} mit \texttt{0} und \texttt{speed} mit \texttt{10} +\end{itemize} + +\subsection{\faIcon{desktop} Bewegung des Spielers} + +Vervollständige die Methode \texttt{act} des Spielers. + +\begin{tcolorbox}[title=Tipp] +Vergiss nicht deine Implementierung regelmäßig zu testen. +\end{tcolorbox} + +\begin{itemize} +\item Bewege die Figur anhand ihrer Geschwindigkeit in X-Richtung (\texttt{vx}) horizontal\\ + (\mintinline{java}{move(double deltaX, double deltaY)}). +\item Ändere die Geschwindkeit, \emph{falls} eine Pfeiltaste gedrückt wird, um \texttt{speed} in die entsprechende Richtung + (\mintinline{java}{isKeyDown(int key)} und \mintinline{java}{Key.ArrowLeft}, \mintinline{java}{Key.ArrowRight}). +\item Bremse die Figur, falls \boldred{keine} der beiden Tasten gedrückt wird (setzte \texttt{vx} auf $80\%$ des aktuellen Werts). +\end{itemize} + +\subsection{\faIcon{desktop} Gravitation} + +Die Spielfigur soll nach unten fallen, wenn kein Boden unter ihr ist. +Dazu orientieren wir uns an der Gravitation. + +\begin{itemize} +\item Ergänze die Klasse \texttt{Spieler} um die Attribute: \texttt{vy}, \texttt{gravity}, \texttt{sprung} vom Typ \mintinline{java}{double}. +\item Initialisiere die Attribute \texttt{gravity} mit \texttt{0.8} und \texttt{sprung} mit \texttt{-15}. +\item Bewege die Figur entsprechend ihrer Geschwindigkeit in Y-Richtung \texttt{vy}. +\item Erhöhe \texttt{vy}, \emph{falls} die Figur \boldred{nicht} auf dem Boden steht, d.h. ihr Mittelpunkt einen Y-Wert (\mintinline{java}{getCenterY()}) $< 350$ hat, um \texttt{gravity}. +\item \emph{Ansonsten} setzte \texttt{vy} auf 0. +\end{itemize} + +\subsection{\faIcon{desktop} Springen} + +Um sich der Gravitation zu widersetzen, erhöhen wir die Geschwindigkeit in Y-Richtung um die Sprungkraft der Figur. + +\begin{itemize} +\item Erhöhe \texttt{vy} um \texttt{sprung}, \emph{falls} die Figur auf dem Boden steht, d.h. ihr Mittelpunkt einen Y-Wert $\geq 350$ hat, \boldred{und} die Pfeiltaste nach oben \mintinline{java}{Key.ArrowUp} gedrückt ist. +\end{itemize} + +\subsection{\faIcon{earlybirds} \faIcon{desktop} Animation} + +Die Figur soll auch so Aussehen, als würde sie sich bewegen. + +\begin{itemize} + \item Ergänze die Figur um das Attribut \texttt{headingRight} + \item Setze den Wert entsprechend, wenn die Figur die Richtung wechselt. + \item Spiegele die Figur damit die Blickrichtungzur Laufrichtung passt (\mintinline{java}{mirrorX()}). +\end{itemize} + +Die Online-IDE kann mehrere Bilder eines Sprites nacheinander anzeigen. + +\begin{itemize} + \item Betrachte die Sprites (Characters\_1) der Online-IDE, die zu unserem Spieler passen, unter \url{https://www.online-ide.de/spriteLibrary.html}. + \item Lies die Beschreibung der \mintinline{java}{Sprite.playAnimation(...)} Methode unter \url{https://www.online-ide.de/api_documentation.html}. + \item Spiele eine Animation, wenn der Spieler läuft und beende die Animation, wenn der Spieler steht (\mintinline{java}{stopAnimation()}). +\end{itemize} + +\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} + diff --git a/Info/10/2/JumpNRun/arbeitsauftrag2.tex b/Info/10/2/JumpNRun/arbeitsauftrag2.tex new file mode 100644 index 00000000..f886d958 --- /dev/null +++ b/Info/10/2/JumpNRun/arbeitsauftrag2.tex @@ -0,0 +1,103 @@ +\documentclass{handout} +\csname endofdump\endcsname +\usepackage{minted} +\usepackage{hyperref} +\usepackage[ngerman]{babel} +\geometry{margin=2cm} + +\newcommand{\Snake}{\texttt{Snake}} + +\title{Snake Arbeitsauftrag 2} +\setcounter{section}{2} + +\begin{document} +\thispagestyle{empty} + +\subsection{\faIcon{desktop} Essen} +\begin{itemize} +\item Erstelle eine neue Klasse \texttt{Essen}. +\item Ergänze die Klasse Essen um ein \textit{Attribut} \texttt{symbol} vom Typ \texttt{Rechteck}/ +\item Implementiere den \textit{Konstruktor} der Klasse \texttt{Essen}: + \begin{itemize} + \item Es soll die Position übergeben werden. + \item Initialisiere \texttt{symbol} mit einem neuen roten Rechteck an der richtigen Position mit der Größe 20x20. + \end{itemize} +\item Implementiere eine Methode \texttt{entferne()} der Klasse \texttt{Essen}, die das \texttt{symbol} mittels dessen Methode \texttt{Entfernen()} von der Zeichenfläche löscht. +\item Teste deine Klasse \texttt{Essen}, indem du neue Objekte von ihr anlegst und wieder entfernst. +\end{itemize} + +\subsection{\faIcon{desktop} Zeitgesteuertes Essen} +\begin{defbox}{Zeitgesteuerte Ereignisse} +Die Methode \mintinline{java}{public void Ausführen()} unserer Spiel-Klasse wird für jedes neue Bild von der Spiel-Engine aufgerufen. \\[0.2cm] +Um Aktionen in Abhängigkeit von der Zeit auszuführen, müssen wir wissen wie viel „\textit{Zeit}“ bereits vergangen ist. +\end{defbox} + +\begin{itemize} +\item Ergänze die Klasse \Snake{} um eine \textit{Attribut} \texttt{ticks}, das die Anzahl der bereits gezeichneten Bilder speichert. +\item Importiere in der Klasse \Snake{} die Java Klasse \texttt{Random}, indem du außerhalb deiner Klasse \Snake{} die Zeile \mintinline{java}{import java.util.Random;} einfügst. +\item Ergänze die Klasse \Snake{} um ein \textit{Attribut} \texttt{zufall} vom Typ \texttt{Random}, initialisiere das \textit{Attribut} im \textit{Konstruktor}. +\item Ergänze die Methode \mintinline{java}{Snake.Ausführen}: + \begin{itemize} + \item Erhöhe zu Beginn die Anzahl der bereits gezeichneten Bilder. + \item Falls das aktuelle Bild ein Vielfaches von 30 ist: + \begin{itemize} + \item Falls ein Essen in dem \textit{Attribut} \texttt{essen} der Klasse \Snake{} gespeichert ist, entferne es. + \item Erzeuge eine neues \texttt{Essen}-Objekt an einer zufälligen Position (\mintinline{java}{zufall.nextInt(max)} liefert dir eine Zufallszahl zwischen 0 und \texttt{max}). + \end{itemize} + + \end{itemize} +\end{itemize} + +\begin{defbox}{Modulo} +Die \boldred{Modulo-Operation}, in Java das Zeichen \texttt{\%}, liefert als Ergebnis, den Rest der Ganzzahldivision zweier Zahlen. \\[0.1cm] +\textbf{Beispiele}: \mintinline{java}{7 % 3 == 1; 64 % 30 == 4} +\end{defbox} + +\newpage +\subsection{\faIcon{desktop} Wachstum} + +Damit unsere Schlange wachsen kann, muss sie aus mehr Körperteilen als nur dem Kopf bestehen. + +\begin{itemize} +\item Ersetze das \textit{Attribut} Kopf der Schlange durch ein Feld namens \texttt{koerper} vom Typ \texttt{Rechteck}. +\item Initialisiere das Feld im \textit{Konstruktor} der Klasse \texttt{Schlange} mit Länge 0. +\item Ergänze die Klasse \texttt{Schlange} um die Methode \mintinline{java}{wachsen(int x, int y)}: + \begin{itemize} + \item Erzeuge ein neues Feld, das um ein Element länger ist als der aktuelle Körper der Schlange. + \item Erzeuge einen neuen Kopf an der richtigen Position (grün und 20x20 Pixel groß). + \item Speichere den neuen Kopf als erstes Element in dem neu erzeugten Feld. + \item Kopiere alle Elemente des aktuellen Körpers in das neue Feld. \\ + \textbf{Vergiss nicht}: Das neue Feld enthält bereits den Kopf am Index 0. + \item Speichere das neue Feld in dem \textit{Attribut} \texttt{koerper}. + \end{itemize} +\end{itemize} + +\subsection{\faIcon{desktop} Bewegung der Schlange} + +\begin{defbox}{Bewegung mehrere Körperteile} +\begin{tabular}{p{0.65\textwidth} p{5cm}} +\vspace{-3.5cm} +Es bietet sich an bei der Bewegung der Schlange die Bewegung der Raupen in der Natur nachzuahmen. +Dabei wird jedes Körperteil an die Position des Vorgängers gezogen. + +Du kannst ein Feld rückwärts durchlaufen, indem du die dir bereits bekannte \mintinline{java}{for} Schleife leicht modifizierst. + +\begin{minted}{java} +for (int i = feld.length -1; i >= 0; i--) { + ... +} +\end{minted} +& +\includegraphics[keepaspectratio, width=5cm]{img/Copyrighted/caterpillar_movement.png} \\ +\end{tabular} +\end{defbox} + +\begin{itemize} +\item Beginnend mit dem letzten Körperteil setze die Position auf die des Körperteils davor. +\item Verschiebe anschließend den Kopf wie gewohnt in die aktuelle Richtung. +\item Teste deine Methoden \texttt{bewegen} und \texttt{wachsen}, indem du alle 40 Bilder die Schlange in die aktuelle Richtung wachsen lässt. +\end{itemize} + +\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} diff --git a/Info/10/2/JumpNRun/arbeitsauftrag3.tex b/Info/10/2/JumpNRun/arbeitsauftrag3.tex new file mode 100644 index 00000000..936d4b71 --- /dev/null +++ b/Info/10/2/JumpNRun/arbeitsauftrag3.tex @@ -0,0 +1,73 @@ +\documentclass{handout} +\csname endofdump\endcsname +\usepackage{minted} +\usepackage{hyperref} +\usepackage[ngerman]{babel} +\geometry{margin=2cm} + +\newcommand{\Snake}{\texttt{Snake}} + +\title{Snake 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} + +\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} Kollision mit dem Rand} + +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} + +\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} + diff --git a/Info/10/2/JumpNRun/img/jumpnrun.png b/Info/10/2/JumpNRun/img/jumpnrun.png Binary files differnew file mode 100644 index 00000000..ee9b54c7 --- /dev/null +++ b/Info/10/2/JumpNRun/img/jumpnrun.png diff --git a/Info/10/2/JumpNRun/lehrer_arbeitsauftrag1.pdf b/Info/10/2/JumpNRun/lehrer_arbeitsauftrag1.pdf Binary files differnew file mode 100644 index 00000000..5a4344a8 --- /dev/null +++ b/Info/10/2/JumpNRun/lehrer_arbeitsauftrag1.pdf diff --git a/Info/10/2/JumpNRun/slides.md b/Info/10/2/JumpNRun/slides.md new file mode 100644 index 00000000..afac3e84 --- /dev/null +++ b/Info/10/2/JumpNRun/slides.md @@ -0,0 +1,625 @@ +--- +author: Florian Fischer +theme: metropolis +aspectratio: 169 +--- + +# Phase I - Modellierung eines Spiels + +## \faIcon{pencil-alt} Modellierung \hfill 10min + +::: {.columns align=center} +:::: {.column width=50%} +* Erstelle ein Klassendiagramm mit allen **Klassen**, die du im rechten Screenshot ausmachen kannst. +* Notiere die **Attribute**, die du sehen kannst und welche die Klassen haben müssen. +* Notiere die **Methoden**, die die Klassen vermutlich haben. +* Zeichne und beschrifte die Beziehungen zwischen den Klassen. +:::: + +:::: {.column width=50%} + +:::: +::: + +## "Offensichtliche" Klassen +::: {.columns} +:::: {.column width=45%} +### Spieler + +\vspace{-0.3cm} +*Attribute*: +\vspace{-0.2cm} + +* Geschwindigkeit +* Position + +\vspace{-0.3cm} +*Methoden*: +\vspace{-0.2cm} + +* Bewegen +* Springen + +\vspace{-0.3cm} +### Flagge +* Position + +\vspace{-0.3cm} +### Plattform +* Position +* Höhe +* Breite +::: + +:::: {.column width=55%} +\begin{tikzpicture} + \begin{class}[text width=3cm]{Spieler}{0,0} + \attribute{geschwindigkeit} + \attribute{position} + \operation{bewegen()} + \operation{springen()} + \end{class} + + \begin{class}[text width=3cm]{Flagge}{0,-4.5} + \attribute{position} + \end{class} + + \begin{class}[text width=3cm]{Platform}{5,-2.5} + \attribute{position} + \attribute{hoehe} + \attribute{breite} + \end{class} + \association{Spieler}{steht auf}{}{Platform}{}{}; + \association{Spieler}{erreicht}{}{Flagge}{}{}; +\end{tikzpicture} +:::: +::: + +## "Nicht sichtbare" Klassen +::: {.columns} +:::: {.column width=50%} +### Level +\vspace{-0.3cm} +*Attribute*: +\vspace{-0.2cm} + +* feste Objekte +* interaktive Objekte + +\vspace{-0.3cm} +*Methoden*: +\vspace{-0.2cm} + +* naechstes Level +* Spieler-Position setzen + +### Spiel +* Level +* Spieler +* Highscore +* Zeit +* ... +::: + +:::: {.column width=50%} +\begin{tikzpicture} + \begin{class}[text width=3cm]{Level}{0,0} + \attribute{festeObjekte} + \attribute{interaktiveObjekte} + \end{class} + + \begin{class}[text width=3cm]{Spiel}{0,-2.5} + \attribute{level} + \attribute{player} + \end{class} +\end{tikzpicture} +:::: +::: + + +## Klassendiagramm + +\centering +\begin{tikzpicture} + \begin{class}[text width=3cm]{Spieler}{6,1} + \attribute{geschwindigkeit} + \attribute{position} + \operation{bewegen()} + \operation{springen()} + \end{class} + + \begin{class}[text width=3cm]{Flagge}{4.5,-2.5} + \attribute{position} + \end{class} + + \begin{class}[text width=3cm]{Platform}{8,-3.75} + \attribute{position} + \attribute{hoehe} + \attribute{breite} + \end{class} + + \begin{class}[text width=3cm]{Spiel}{0,0} + \attribute{Level} + \attribute{Player} + \end{class} + \association{Spiel}{}{}{Spieler}{1}{}; + + \begin{class}[text width=3cm]{Level}{1,-4.5} + \attribute{festeObjekte} + \attribute{interaktiveObjekte} + \end{class} + \association{Spiel}{}{}{Level}{1}{}; + \association{Level}{}{}{Flagge}{}{}; + \association{Level}{}{}{Platform}{n}{}; +\end{tikzpicture} + +## {.standout} + +Wer ruft die Methoden des Spielers auf? + +## \faIcon{chalkboard-teacher} EVA-Prinzip {.t} + +::: {.columns} +:::: {.column width=65%} +\vspace{0.2cm} +\only<2->{ +Trennung der Datenverarbeitung in: + +\begin{itemize} +\item \boldred{E}ingabe: \texttt{input()} +\item \boldred{V}erarbeitung: \texttt{update()} +\item \boldred{A}usgabe: \texttt{output()} +\end{itemize} +} + +\vspace{0.1cm} +\only<3->{\textbf{\faIcon{lightbulb} Wie oft müssen wir die drei Schritte ausführen?}} + +\only<4->{ +Solange das Spiel läuft! + +\begin{block}{EVA-Loop} +\phantomsection\label{eva-loop} + +\texttt{solange Spiel aktiv}\\ +~~\texttt{input()}\\ +~~\texttt{update()}\\ +~~\texttt{output()}\\ +\end{block} +} +:::: + +:::: {.column width=30%} +\vspace{1.5cm} +\begin{tikzpicture} +\only<2->{ + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt] (e) {Eingabe}; + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt, below=of e] (v) {Verarbeitung}; + \node[line width=1pt, draw, minimum width=3cm, rounded corners=5pt, below=of v] (a) {Ausgabe}; + + \draw[-{Triangle}, line width=1pt] (e) to (v); + \draw[-{Triangle}, line width=1pt] (v) to (a); +} + +\only<4>{ + \draw[-{Triangle}, line width=1pt, dashed] + (a.east) -- + ($(a.east) + (0.5, 0)$) -- + ($(e.east) + (0.5, 0)$) -- + (e.east); +} +\end{tikzpicture} +:::: +::: + +## \faIcon{chalkboard-teacher} \only<2->{Spieleengine} + +**\faIcon{lightbulb} Sind wir die ersten mit diesem Problem?** +\pause + +Sicher nicht! +Also lasst uns das Rad nicht neu erfinden, sondern eine \boldred{Spieleengine} verwenden, die uns die lästigen Dinge abnimmt. + +\pause +### Online-IDE + +``` +solange Spiel aktiv <- Online-IDE + input() <- Online-IDE + update() <- Wir + output() <- Online-IDE +``` + +## Wie werden unsere Methoden aufgerufen? + +::: {.columns} +:::: {.column width=75%} +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`. +:::: + +:::: {.column width=25%} +\hspace{-1.25cm} +\scalebox{1.1}{ +\begin{tikzpicture} +\node[fill=magenta!20, line width=1pt, draw, minimum height=1cm, minimum width=3cm, rounded corners=5pt] (v) {Verarbeitung}; +\node[fill=bg, minimum height=1cm, minimum width=3cm, rounded corners=5pt, above=-0.1cm of v] (e) {Eingabe}; +\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) {Eingabe}; + +\node[rotate=90] at ($(v.north west) - (0.3cm, 0.0cm)$) {\boldred{interface}}; +\end{tikzpicture} +} +:::: +::: + +\pause +**Java** +`class Player extends Actor`{.java} + +\pause + +**Methoden** + +* `void act()`{.java} + +## Wie erhalten wir die Eingaben? + +::: {.columns} +:::: {.column width=75%} +\faIcon{lightbulb} Wir fragen die Online-IDE. + +\vspace{0.1cm} +Die Online-IDE bietet Methoden, um die Eingaben zu erfragen. + +\vspace{0.1cm} +Wir haben die Methoden bereits von der Klasse `Actor` geerbt. +:::: + +:::: {.column width=25%} +\hspace{-1.25cm} \scalebox{1.1}{ +\begin{tikzpicture} +\node[line width=1pt, draw, minimum height=1cm, minimum width=3cm, rounded corners=5pt] (v) {Verarbeitung}; +\node[fill=bg, minimum height=1cm, minimum width=3cm, rounded corners=5pt, above=-0.1cm of v] (e) {Eingabe}; +\draw[line width=1pt, rounded corners=5pt, fill=cyan!20] ($(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.05cm, 0.2cm)$) -- + ($(v.north east) - (-0.05cm, 0.3cm)$) -- + ($(v.north west) - (0.05cm, 0.3cm)$) -- + ($(v.north west) + (-0.05cm, 0.2cm)$) -- + ($(v.north east) + (0.05cm, 0.2cm)$); + +\draw[-Latex, bend right=35, line width=0.75pt] (v.east) to ($(e.east) + (0, 2mm)$); +\node[minimum height=1cm, minimum width=3cm, above=-0.1cm of v] (e) {Eingabe}; + +\node[rotate=90] at ($(v.north west) - (0.3cm, 0.0cm)$) {\boldred{interface}}; +\end{tikzpicture} +} +:::: +::: + +\pause +**Methoden** + +* `boolean isGamepadButtonDown(int gamepadIndex, int buttonIndex)`{.java} +* `boolean isGamepadConnected(int gamepadIndex)`{.java} +* `boolean isKeyDown(String key)`{.java} +* `boolean isKeyUp(String key)`{.java} + +## \faIcon{desktop} Arbeitsauftrag: Los gehts! \hfill 10 min + +\let\tightlist\relax +* Öffne das **JumpNRun Vorlage1** Projekt. +* Untersuche die bereits vorhandenen Klassen. +* Ergänze die Klasse `Player` um die Attribute: `vx`, `speed` vom Typ `double`{.java}. +* Initialisiere `vx` mit `0` und `speed` mit 10. + +## \faIcon{desktop} Arbeitsauftrag: Spieler bewegen \hfill 15 min + +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` +* *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. + +\faIcon{play} Teste deine Implementierung. + +## \faIcon{desktop} Arbeitsauftrag: Fallen \hfill 10 min + +\let\tightlist\relax +* Ergänze den Spieler um die Attribute: `vy`, `gravity`, `sprung` vom Typ `double`{.java}. +* Initialisiere die Attribute `gravity` mit `0.8` und `sprung` mit `-15`. +* Die Figur soll sich auch entsprechend ihrer Geschwindigkeit in Y-Richtung (`vy`) vertical bewegen. + **Tipp**: Passe den `move(...)` Methoden-Aufruf in der `act`-Methode an. +* *Falls* die Figur **nicht** auf dem Boden steht, d.h. ihr Mittelpunkt einen Y-Wert (`getCenterY()`) *kleiner* als 350 hat, soll sich ihre Geschwindigkeit in Y-Richtung `vy` um `gravity` erhöhen. +* *Ansonsten* wenn sie auf dem Boden steht, soll ihre Y-Geschwindigkeit `vy` auf `0` gesetzt werden. + +## \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. + +\faIcon{play} Teste deine Implementierung. + +## \faIcon{desktop} Arbeitsauftrag: Blickrichtung + +### \faIcon{earlybirds} Für Schnelle + +Die Figur soll in die Richtung ihrer Bewegung blicken. + +\let\tightlist\relax +* Ergänze die Klasse `Player` um das Attribute: `headingRight` vom Typ `boolean`{.java} +* *Falls* eine Pfeiltaste gedrückt wurde und ein Richtungswechsel statt findet + * passe den Wert des Attributs `headingRight` entsprechend an + * spiegele die Figur durch einen Aufruf der Methode `mirrorX()` + +# Phase II - Plattformen und Kollision + +## Plattformen und Level + +::: {.columns} +:::: {.column width=50%} +\begin{center} +\begin{tikzpicture} + \begin{class}[text width=4cm]{Plattform}{0,-4.5} + \attribute{position} + \attribute{hoehe} + \attribute{breite} + \end{class} + + \begin{class}[text width=4cm]{Level}{0,0} + \attribute{festeObjekte} + \attribute{interaktiveObjekte} + \end{class} +\end{tikzpicture} +\end{center} + +\vspace{1cm} +Ein Level soll mehrer feste Plattformen haben. +:::: + +:::: {.column width=50%} + +:::: +::: + +<!-- +## Zufall + +Die Java Klasse `java.util.Random` stellt *pseudo* zufällige Zahlen bereit. + +\pause +### Verwendung + +* 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 +### Größe des Welt + +Das Zeichenfenster misst 800x600 Pixel. + +## Tischlein deck dich + +::: {.columns} +:::: {.column width=50%} + +:::: + +:::: {.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); + } + ... +} +``` +:::: +::: + + +## Wachstum + +Die Schlange soll im Laufe des Spiels länger werden. + +**\faIcon{lightbulb} Welcher Datentyp eignet sich dazu eine unbekannte Anzahl an Rechtecken zuspeichern?** +\pause + +### Das Attribut `koerper` + +* 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. + +## Bewegung + +**\faIcon{lightbulb} Wie kommt die Schlange um die Ecke?** + +\pause + +::: {.columns align=center} +:::: {.column width=50%} +\only<3>{Jedes Körperteil folgt seinem Vorgänger.} +:::: + +:::: {.column width=50%} +{.center width=100%} +:::: +::: + +## Bewegung + +```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() + ... +} +``` + + +# Phase III - Kollisionserkennung + +## Wann frisst die Schlange das Essen + +::: {.columns align=center} +:::: {.column width=50%} +\vspace{0.3cm} + +:::: + +:::: {.column width=50%} +Berührt der Kopf das Essen? +:::: +::: + +## Wann frisst die Schlange das Essen + +### \faIcon{lightbulb} Wo findet die Überprüfung statt? +\pause +In der `Ausführen`-Methode der Welt-Klasse `Snake`, da + +>- dort Schlange und Essen bekannt sind +>- dort die Schlange bewegt wird + +\pause +### Pseudocode +``` +Schlange bewegen +Falls Kopf das Essen berührt + entferne Essen + Schlange wachse +``` + +## Kollision mit dem Rand der Welt + +::: {.columns align=center} +:::: {.column width=50%} +\vspace{0.3cm} + +:::: + +:::: {.column width=50%} +Ist die Position des Kopfes noch Teil der Welt? +:::: +::: + +## Kollision mit dem Rand der Welt + +### \faIcon{lightbulb} Wo findet die Überprüfung statt? +\pause +In der `bewegen`-Methode der Klasse `Schlange`, nachdem der Kopf bewegt wurde + +### \faIcon{lightbulb} Woher weiß das Spiel das die Schlange kollidiert ist? +\pause +Die Methode `bewegen` gibt einen Wahrheitswert zurück, ob sie erfolgreich war. + +\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 +``` + +## Kollision mit sich selbst + +::: {.columns align=center} +:::: {.column width=50%} +\vspace{0.3cm} + +:::: + +:::: {.column width=50%} +Berührt der Kopf der Schlange eins der eigenen Körperteile? +:::: +::: + +## 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. + +\pause +### Pseudocode +``` +Koerper bewegen +Kopf bewegen +... + +Für jedes koerperteil hinter dem kopf + Falls kopf beruehrt koerperteil + return false + +return true +``` + +## {.standout} + +Dieses Werk ist lizenziert unter einer [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) Lizenz \faCreativeCommons\ \faCreativeCommonsBy\ \faCreativeCommonsSa. +--> |
