<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-x-formal">
	<id>https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Franzih</id>
	<title>GlossarWiki - Benutzerbeiträge [de-formal]</title>
	<link rel="self" type="application/atom+xml" href="https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Franzih"/>
	<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/Spezial:Beitr%C3%A4ge/Franzih"/>
	<updated>2026-07-17T17:30:35Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball02&amp;diff=46453</id>
		<title>MMProg: Praktikum: WiSe 2018/19: Ball02</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball02&amp;diff=46453"/>
		<updated>2018-11-30T10:30:00Z</updated>

		<summary type="html">&lt;p&gt;Franzih: /* Aufgabe 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2018/19:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball02/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Ball02.git Git-Repository]) &lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
Importieren Sie das leere Git-Projekt [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/Ball02.git Ball02] in WebStorm.&lt;br /&gt;
Laden Sie anschließend mittels &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt; alle benötigten Node.js-Module in das Projekt.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig.&lt;br /&gt;
Falls Sie dies machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
git remote remove origin&lt;br /&gt;
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Ball02.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ziel==&lt;br /&gt;
&lt;br /&gt;
Ziel dieser Praktikumsaufgabe ist es, die “HTML5 Creation Engine” PixiJS v4 kennenzulernen.&amp;lt;ref&amp;gt;[http://www.pixijs.com/ PixiJS v4: The HTML5 Creation Engine]&amp;lt;/ref&amp;gt; &lt;br /&gt;
Bei PixiJS handelt es sich um eine sehr mächtige (und damit auch sehr große) JavaScript-Bibliothek zur Realisierung von 2D-Animationen und -Spielen. &lt;br /&gt;
&lt;br /&gt;
Mit HTML5 wurde das Canvas-Element (Leinwand-Element) eingeführt.&amp;lt;ref&amp;gt;[https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API MDN web docs: Canvas API]&amp;lt;/ref&amp;gt;&lt;br /&gt;
„Auf“ einem Canvas-Element können Grafiken gezeichnet werden. Aktuelle Browser unterstützen üblicherweise sowohl den &amp;lt;code&amp;gt;CanvasRenderingContext2D&amp;lt;/code&amp;gt; &lt;br /&gt;
zum Erstellen von 2D-Grafiken&amp;lt;ref&amp;gt;[https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D MDN web docs: CanvasRenderingContext2D]&amp;lt;/ref&amp;gt; &lt;br /&gt;
als auch &amp;lt;code&amp;gt;WebGL&amp;lt;/code&amp;gt; zum Erstellen von 3D-Grafiken (auf Basis von [[OpenGL]])&amp;lt;ref&amp;gt;[https://developer.mozilla.org/de/docs/Web/API/WebGL_API/Tutorial/Einf%C3%BChrung_in_WebGL MDN web docs: Einführung in WebGL]&amp;lt;/ref&amp;gt;. Die Erstellung von Grafiken mit WebGL ist wesentlich effizienter als die&lt;br /&gt;
Erstellung von Grafiken mit dem &amp;lt;code&amp;gt;CanvasRenderingContext2D&amp;lt;/code&amp;gt;, zumindest dann wenn, eine Grafikkarte zur Verfügung steht, deren Prozessor&lt;br /&gt;
([[GPU]]) OpenGL nativ unterstützt. Dies ist insbesondere dann von Bedeutung, wenn Animationen erstellt werden, {{dh}}, wenn 60 mal pro Sekunde (also&lt;br /&gt;
alle 16,7 ms) eine neue Grafik auf dem Canvas angezeigt werden soll.&lt;br /&gt;
&lt;br /&gt;
PixiJS ist als Ersatz für den &amp;lt;code&amp;gt;CanvasRenderingContext2D&amp;lt;/code&amp;gt; gedacht. Die Bibliothek stellt im Wesentlichen dieselben Grafik-Befehle &lt;br /&gt;
wie der 2D-Kontext zur Verfügung, erstellt aber, wann immer möglich, die 2D-Grafiken mit Hilfe von WebGL. Nur wenn diese Schnittstelle vom &lt;br /&gt;
Browser nicht zur Verfügung gestellt wird, erfolgt als Fallback das Rendering mit Hilfe des 2D-Kontextes. Dies hat allerdings meist einen deutlichen &lt;br /&gt;
Performanz-Einbruch zur Folge.&lt;br /&gt;
 &lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie wiederum mehrere Web-Anwendungen: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die gepackte Version von &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;game01.js&amp;lt;/code&amp;gt; einbindet. Et cetera.&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;game&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
&lt;br /&gt;
Diese Aufgabe entspricht Aufgabe 1 der Praktikumsaufgabe [[MMProg: Praktikum: WiSe 2017/18: GameLoop01]]:&lt;br /&gt;
&#039;&#039;Lassen Sie die Eule horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Im Projekt &amp;lt;code&amp;gt;WK_Ball02_Empty&amp;lt;/code&amp;gt; ist eine mögliche Lösung dieser Aufgabe bereits enthalten, wobei allerdings ein Kreis „fliegt“ anstelle einer Eule.&lt;br /&gt;
Ihre Aufgabe ist es nun, sich die Unterschiede zur Lösung der ersten Praktikumsaufgabe &amp;lt;code&amp;gt;WK_Ball01&amp;lt;/code&amp;gt;, die sich durch die Verwendung von PixiJS&lt;br /&gt;
ergeben, klar zu machen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Es wird zusätzlich die in der JavaScript-Bibliothek &amp;lt;code&amp;gt;pixi.js&amp;lt;/code&amp;gt; enthaltene  Klasse &amp;lt;code&amp;gt;Application&amp;lt;/code&amp;gt; importiert. Beachten Sie, dass hier diejenige Klasse der PixiJS-Bibliothek importiert wird, die auch wirklich benötigt wird. Man könnte auch &amp;lt;code&amp;gt;import * as PIXI from &#039;pixi.js&#039;;&amp;lt;/code&amp;gt; schreiben und damit alle PixiJS-Klassen, -Funktionen und -Objekte in der Variablen &amp;lt;code&amp;gt;PIXI&amp;lt;/code&amp;gt; speichern. Es ist allerdings besser, nur die benötigten Teil der PixiJS-Bibliothek einzubinden, da webpack dann die Chance hat, im Web-Ordner kleinere JavaScript-Dateien zu erzeugen. Dies kann eine deutliche Reduktion der Ladezeiten der Web-App zur Folge haben. &lt;br /&gt;
* Anstelle des GameLoop-Objektes könnte auch der PixiJS-Ticker verwendet werden. Dieser stellt jedoch nicht sicher, dass das Model garantiert 60 mal pro Sekunde aktualisiert wird. Wenn Sie irgendwann PixiJS-Animationen einsetzen möchten, müssen Sie den PixiJS-Ticker allerdings zusätzlich starten, da ansonsten die Animationen nicht animiert werden. &lt;br /&gt;
* Das Root-Objekt der PixiJS-Anwendung wird erstellt. Die wichtigsten Argumente sind die Breite und Höhe der Bühne sowie das Canvas-Element, auf dem die Grafiken gezeichnet werden. (Wenn man der Anwendung kein Canvas-Element zuteilt, erstellt sie selbst eines, das man anschließend per JavaScript in das HTML-Dokument einfügen muss.) Darüber hinaus gibt es diverse weitere Optionen, wie {{zB}} die Festlegung, ob die Leinwand transparent ist, damit der HTML-Hintergrund durchscheint.&amp;lt;ref&amp;gt;[http://pixijs.download/dev/docs/PIXI.Application.html PixiJS API Documentation: PIXI.Application ]&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Das Spiel wird mit Hilfe einer Methode &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; initialisiert, bevor die Game Loop gestartet werden kann. Das ist notwendig, da die Grafikobjekte, die später animiert werden sollen, zunächst erstellt werden müssen. In der [[MMProg: Praktikum: WiSe 2018/19: Ball01|ersten Praktikumsaufgabe]] wurde diese Tätigkeit per CSS (und nicht per JavaScript) erledigt. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;game01.js&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* Der Ordner &amp;lt;code&amp;gt;ball&amp;lt;/code&amp;gt; wurde in &amp;lt;code&amp;gt;game&amp;lt;/code&amp;gt; umbenannt und die Datei &amp;lt;code&amp;gt;ball01.js&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;game01.js&amp;lt;/code&amp;gt; unbenannt, da hier nicht nur das Ball-Objekt, sondern auch alle andere Aspekte des „Spiels“  „Ein Ball bewegt sich hin und her“ definiert werden.&lt;br /&gt;
* Es wird die in der PixiJS-Bibliothek enthaltene  Klasse &amp;lt;code&amp;gt;Graphics&amp;lt;/code&amp;gt; importiert, um damit eine View für das Ball-Objekt zu zeugen.&lt;br /&gt;
* Es gibt eine Initialisierungsfunktion (Initfunktion), die zu Beginn der Anwendung aufgerufen wird, um sie zu initialisieren. &lt;br /&gt;
* Darüber hinaus gibt es auch noch eine Resetfunktion, die jedes Mal aufgerufen wird, wenn die Anwendung neu gestartet wird, {{zB}} weil ein neues Spiellevel begonnen werden soll. (Diese Funktion gab es im Gegensatz zur Initfunktion auch schon in der ersten Praktikumsaufgabe.) Diese Funktion ist für wiederkehrende Initialisierungaufgaben verantwortlich, wohingegen die Initialisierungsfunktion nur ein einziges Mal zu Spielbeginn aufgerufen wird. Um [[DRY|Code-Duplikationen]] zu vermeiden, ruft die Initialisierungsfunktion auch die Resetfunktion auf.&lt;br /&gt;
* Das Modell der Bühne (&amp;lt;code&amp;gt;v_stage&amp;lt;/code&amp;gt;) wird nur teilweise initialisiert. Die Breite und Höhe wird erst später von der Initfunktion festgelegt.&lt;br /&gt;
* Das Ballobjekt &amp;lt;code&amp;gt;v_ball&amp;lt;/code&amp;gt; wird erst durch die Resetfunktion initialisiert. Diese wird erstmals von der Init-Funktion aufgerufen und kann später von der Game Loop bei Spielstart oder -neustart damit zurückgesetzt werden. &lt;br /&gt;
* Das Ballobjekt beinhaltet schon die y-Koordinate und die y-Geschwindigkeit des Balls. In der ursprünglichen Aufgabe fehlten diese Attribute noch. Sie wurden erst in der zweiten Aufgabe („Ball vertikal fliegen lassen“) eingeführt. Außerdem wurde der Durchmesser (&amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt;) durch den Radius (&amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt;) ersetzt.&lt;br /&gt;
* Der Ankerpunkt des Balls wurde von der linken oberen Ecke der Eule ins Zentrum des Balls verschoben. Dies hat Auswirkungen auf die Implementierung der Kollisionserkennung und -behandlung.&lt;br /&gt;
* Die Renderfunktion unterscheidet sich leicht. In der ursprünglichen Aufgabe wurden CSS-Attribute des animierten &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt;-Elements verändert. Nun müssen die Attribute des PixiJS-Grafikobjekts, das in der Init-Funktion erzeugt wurde, an die aktuellen Modellwerte angepasst werden. &lt;br /&gt;
&lt;br /&gt;
Die Initfunktion nimmt folgende Aufgaben wahr:&lt;br /&gt;
* Breite und Höhe des Bühnenmodells werden an die Breite und Höhe der PixiJS-Anwendung angepasst.&lt;br /&gt;
* Die Modelle des Spiels werden initialisiert.&lt;br /&gt;
* Die View des Balls wird initialisiert und auf der PixiJS-Bühne platziert. Dies kann erst jetzt erfolgen, da das Application-Objekt der PixiJS-Anwendung erst jetzt zur Verfügung steht. Mit Hilfe der PixJS-Klasse [http://pixijs.download/dev/docs/PIXI.Graphics.&amp;lt;code&amp;gt;Graphics&amp;lt;/code&amp;gt;]wird zunächst ein Grafikobjekt erzeugt. Dieses wird mit Inhalt gefüllt (einem Kreis von bestimmter Farbe mit einem Rand in einer anderen Farbe) und zu guter Letzt zur PixiJS-Bühne ({{dh}} im Prinzip zum zugehörigen Canvaselement) hinzugefügt. Wenn sich später bestimmte Attribute des Grafikobjektes – wie {{zB}} die Position oder die Größe – ändern, wird die graphische Darstellung des Objektes auf dem Canvas automatisch von PixiJS angepasst. Die Änderung der Grafikattribute werden in der Funktion &amp;lt;code&amp;gt;render&amp;lt;/code&amp;gt; vorgenommen. Dort wird derzeit allerdings nur die Position aus dem Model in die View übertragen. Andere Attribute der View ändern sich in dieser Anwendung nicht.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie eine erste Version der Lösung der Aufgabe 2, indem Sie die Lösung der Aufgabe 1 kopieren:&lt;br /&gt;
* Kopieren Sie &amp;lt;code&amp;gt;src/js/game/game01.js&amp;lt;/code&amp;gt; nach  &amp;lt;code&amp;gt;src/js/game/game02.js&amp;lt;/code&amp;gt;&lt;br /&gt;
* Kopieren Sie &amp;lt;code&amp;gt;src/js/app01.js&amp;lt;/code&amp;gt; nach  &amp;lt;code&amp;gt;src/js/app02.js&amp;lt;/code&amp;gt; und ersetzen Sie in dieser Datei &amp;lt;code&amp;gt;&#039;./game/game01.js&#039;&amp;lt;/code&amp;gt; durch &amp;lt;code&amp;gt;&#039;./game/game02.js&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Kopieren Sie &amp;lt;code&amp;gt;src/index01.html&amp;lt;/code&amp;gt; nach  &amp;lt;code&amp;gt;src/index02.html&amp;lt;/code&amp;gt; und ersetzen Sie in dieser Datei &amp;lt;code&amp;gt;&amp;amp;lt;title&amp;amp;gt;Ball02 (app01)&amp;amp;lt;/title&amp;amp;gt;&amp;lt;/code&amp;gt; durch &amp;lt;code&amp;gt;&amp;amp;lt;title&amp;amp;gt;Ball02 (app02)&amp;amp;lt;/title&amp;amp;gt;&amp;lt;/code&amp;gt;. (Einen Verweis auf die JavaScript-Datei &amp;lt;code&amp;gt;app02.js&amp;lt;/code&amp;gt; gibt es in dieser Datei nicht. Der korrekte Verweis wird von webpack automatisch beim Erstellen der Dateien des Web-Ordners injiziert.)&lt;br /&gt;
* Starten Sie &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; neu, damit auch die neu erstellten Dateien automatisch von webpack übersetzt werden.&lt;br /&gt;
&lt;br /&gt;
Lösen Sie Aufgabe 2 der [[MMProg: Praktikum: WiSe 2018/19: Ball01#Aufgabe 2|ersten Praktikumsaufgabe]] mit Hilfe von PixiJS. Das heißt, ändern Sie Ihre Version von&lt;br /&gt;
Aufgabe 2, die Sie gerade durch Kopieren erstellt haben so ab, dass Folgendes passiert: &lt;br /&gt;
&#039;&#039;Lassen Sie den Ball nicht waagerecht, sondern in der horizontalen Mitte des Browserfensters senkrecht von Fensterrand zu Fensterrand fliegen.&#039;&#039; Anstelle einer Eule verwenden Sie bitte analog zu Aufgabe 1 einen farbigen „Ball“ mit Rand.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht auch die Kollisionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und denken Sie daran, &amp;lt;code&amp;gt;npm run dev&amp;lt;/code&amp;gt; oder besser noch &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; zu verwenden. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2a===&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie zunächst wie in Aufgabe 2 beschrieben eine Kopie der Lösung von Aufgabe 2 und nennen Sie sie 2a (&amp;lt;code&amp;gt;index02a.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app02a.js&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game02a.js&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Ändern Sie nun die View des Balls: Anstelle eines farbigen Kreises stellen Sie bitte eine Eule oder einen Pinguin dar.&lt;br /&gt;
Importieren Sie zunächst das gewünschte graphische Objekt in die Datei &amp;lt;code&amp;gt;game02a.js&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import imgBall from &#039;../../img/owl-150.png&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
oder&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import imgBall from &#039;../../img/tux-150.png&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Genau genommen weisen Sie webpack mit dieser Anweisung an, das Grafikobjekt im Ordner &amp;lt;code&amp;gt;web/img&amp;lt;/code&amp;gt; zu erzeugen und die zugehörige URL in der&lt;br /&gt;
Variablen &amp;lt;code&amp;gt;imgBall&amp;lt;/code&amp;gt; zu speichern. Ohne  webpack müssten Sie das Bild von Hand in diesem Ordner ablegen und dem Spriteobjekt – siehe unten – die korrekte URL übergeben.)&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus müssen Sie dafür sorgen, das von &amp;lt;code&amp;gt;pixi.js&amp;lt;/code&amp;gt; nicht mehr die Klasse &amp;lt;code&amp;gt;Graphics&amp;lt;/code&amp;gt;,&lt;br /&gt;
sondern stattdessen die Klasse &amp;lt;code&amp;gt;Sprite&amp;lt;/code&amp;gt; importiert wird.&lt;br /&gt;
&lt;br /&gt;
Ändern Sie in der Initfunktion die Befehle zur Erstellung der View so ab, dass kein Kreis mehr gezeichnet, sondern das Bild&lt;br /&gt;
der Eule oder des Pinguins dargestellt wird. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
let&lt;br /&gt;
  ...&lt;br /&gt;
  v_ball_view = Sprite.fromImage(imgBall); // imgBall contains the URL of the image&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der Initfunktion wird nur noch der Ankerpunkt in die Mitte des Viewobjekts verschoben.&lt;br /&gt;
Sie müssen die vier Befehle zur ERzeugung des Grafikobjektes also löschen.&lt;br /&gt;
Dieses Objekt wird dann wieder zur PixiJS-Bühne hinzugefügt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball_view.anchor.set(0.5); // center the anchor&lt;br /&gt;
p_pixi_app.stage.addChild(v_ball_view);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
Erstellen Sie zunächst wie in Aufgabe 2 beschrieben eine Kopie der Lösung von Aufgabe 2a und nennen Sie sie 3 (&amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app03.js&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game03.js&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Lösen Sie Aufgabe 3 der [[MMProg: Praktikum: WiSe 2017/18: GameLoop01#Aufgabe 2|ersten Praktikumsaufgabe]] mit Hilfe von PixiJS:&lt;br /&gt;
&#039;&#039;Lassen Sie der Ball von der Mitte des Browserfensters aus schräg über den Bildschirm fliegen. In x-Richtung soll er doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&#039;&#039; &lt;br /&gt;
(Diesmal sollten Sie gleich eine Eule oder einen Pinguin fliegen lassen und nicht erst einen Kreis.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3a===&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie zunächst wie in Aufgabe 2 beschrieben eine Kopie der Lösung von Aufgabe 3 und nennen Sie sie 3a (&amp;lt;code&amp;gt;index03a.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app03a.js&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game03a.js&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Einen Nachteil hat die Lösung der Aufgaben 2a  und 3: Das Bild des Vogels wird mittels &amp;lt;code&amp;gt;Sprite.fromImage&amp;lt;/code&amp;gt; synchron vom Web-Server geladen.&lt;br /&gt;
Das heißt, solange bis das Bild geladen wurde, ist die Anwendung „eingefroren“. Bei einem kleinen Bild ist das sicher kein Problem, wenn aber&lt;br /&gt;
eine Vielzahl von oder große Medien geladen werden müssen – wie dies bei realen Web-Anwendungen der Fall ist –, ist dies sicher keine Option mehr.&lt;br /&gt;
&lt;br /&gt;
Nehmen Sie an Ihrer Kopie 3a folgende Änderung vor:&lt;br /&gt;
Laden Sie das Bild des Vogels asynchron mit Hilfe eines PixiJS-Loader-Objektes &lt;br /&gt;
([http://pixijs.download/dev/docs/PIXI.loaders.Loader.html MDN web doc: PIXI.loaders.Loader ], [https://github.com/englercj/resource-loader  GitHub: resource-loader])&amp;lt;ref&amp;gt;[http://pixijs.download/dev/docs/PIXI.loaders.Loader.html PixiJS API Documentation: PIXI.loaders.Loader]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[https://github.com/englercj/resource-loader GitHub: resource-loader&lt;br /&gt;
]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Zunächst ein wenige Theorie:&lt;br /&gt;
&lt;br /&gt;
====Asynchronität in EcmaScript 2017====&lt;br /&gt;
&lt;br /&gt;
Eine wesentliche Änderung, die sich wegen der Asynchronität ergibt, ist, dass der Ladevorgang später endet als die Ausführung der Initialisierungsfunktion.&lt;br /&gt;
Wenn man direkt im Anschluss an die Ausführung der Initialisierungsfunktion die Game Loop startet, ist die Wahrscheinlichkeit groß, dass die Bilder noch gar nicht&lt;br /&gt;
geladen wurden und die Anwendung daher abstürzt. Abhilfe schafft hier der Einsatz von  modernen asynchronen JavaScript-Anweisungen:&lt;br /&gt;
* &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekte ([https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise MDN web docs: Promise])&lt;br /&gt;
*&amp;lt;code&amp;gt;async&amp;lt;/code&amp;gt;-Funktionen ([https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/async_function MDN web docs: async function])&lt;br /&gt;
* &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt;-Operator ([https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await MDN web docs: await])&lt;br /&gt;
&lt;br /&gt;
Diese Konstrukte wurden eingeführt, da man in einem klassischen ES5-Programm häufig den Wald vor lauter Bäumen,&lt;br /&gt;
{{dh}} den Code vor lauter Callback-Funktionen nicht mehr gesehen hat, wenn eine Vielzahl von asynchronen Anweisungen benötigt wurden.&lt;br /&gt;
&lt;br /&gt;
Mit ES 2015 wurde die globale Klasse &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt; eingeführt.&lt;br /&gt;
Ein &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt führt eine Aktion, wie das Laden eines Bildes oder das Warten auf ein Timer-Ereignis, asynchron aus. Sobald&lt;br /&gt;
die Aktion erfolgreich beendet wird, führt sie eine Callback-Funktion aus, die ihr in der Methode &amp;lt;code&amp;gt;then&amp;lt;/code&amp;gt; übergeben wurde.&lt;br /&gt;
Der Callback-Funktion wird das Ergebnis der asynchronen Aktion als Ergebnis übergeben, so dass sie damit weiterarbeiten kann. &lt;br /&gt;
Falls diese Funktion wieder ein &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt  als Ergebnis liefert, kann man den nächsten asynchronen Befehl mittels eines&lt;br /&gt;
weiteren Aufrufs der Methode &amp;lt;code&amp;gt;then&amp;lt;/code&amp;gt; anfügen. Etc. pp. Auf diese Weise konnte man eine Abfolge von asynchronen Anweisungen zumindest&lt;br /&gt;
linear notieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
myPromise&lt;br /&gt;
  .then(function(p_value) { ...})&lt;br /&gt;
  .then(function(p_value) { ...})&lt;br /&gt;
  .then(function(p_value) { ...})&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man die kürzere Arrow-Schreibweise für Funktionen verwendet, die mit ES 2015 eingeführt wurde ([https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Pfeilfunktionen MDN web doc: Pfeilfunktionen]), wird der oder noch etwas kompakter und damit lesbarer:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
myPromise&lt;br /&gt;
  .then(p_value =&amp;gt; { ...})&lt;br /&gt;
  .then(p_value =&amp;gt; { ...})&lt;br /&gt;
  .then(p_value =&amp;gt; { ...})&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allerdings ist das auch nicht sonderlich schön zu lesen, vor allem wenn man umfangreiche asynchrone Funktionen zu definieren hat.&lt;br /&gt;
Und jede dieser Funktionen muss ein eigenes &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt erstellen, was den Code auch nicht gerade lesbarer macht.&lt;br /&gt;
&lt;br /&gt;
Daher wurden in ES 2017 die asynchronen Funktionen eingeführt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
async function myFunction(...)&lt;br /&gt;
{ ...}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In dieser Funktionen werden Anweisungen geschrieben, wie in jeder anderen Funktion auch. Und diese Anweisungen werden der Reihe nach abgearbeitet.&lt;br /&gt;
Allerdings gibt es einen fundamentalen Unterschied. Der Funktionsrumpf wird asynchron ausgeführt. Das Ergebnis der Funktion ist ein (implizites)&lt;br /&gt;
&amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt, dessen &amp;lt;code&amp;gt;then&amp;lt;/code&amp;gt;-Funktion erst aufgerufen wird, sobald alle asynchronen Befehle im Rumpf &lt;br /&gt;
der Funktion erfolgreich beendet wurden.&lt;br /&gt;
&lt;br /&gt;
Da heißt, bei Aufruf der Funktion wird diese sofort wieder beendet. Der Browser wird durch die Funktion nicht blockiert, wie es {{zB}} beim &lt;br /&gt;
synchronen Laden eines Bildes der Fall wäre.  Die im Rumpf der Funktion enthaltenen Befehle werden trotzdem der Reihe nach ausgeführt, aber asynchron.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie die Funktion &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; in der Datei &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt; näher betrachten, fällt Ihnen auf, das sie als &amp;lt;code&amp;gt;async&amp;lt;/code&amp;gt;-Funktion&lt;br /&gt;
definiert wurde. In ihrem Rumpf befinden sich neben drei Standard-Anweisungen auch die Anweisung &amp;lt;code&amp;gt;await wait(500);&amp;lt;/code&amp;gt;. Die Funktion &amp;lt;code&amp;gt;wait&amp;lt;/code&amp;gt;&lt;br /&gt;
wurde von mir in der Datei &amp;lt;code&amp;gt;src/lib/wk/util/wait.js&amp;lt;/code&amp;gt; definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function wait(p_time)&lt;br /&gt;
{ return new Promise(function(p_resolve)&lt;br /&gt;
                     { setTimeout(p_resolve, p_time); }&lt;br /&gt;
                    )&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(In Wirklichkeit habe ich die modernere Arrow-Schreibweise verwendet, &lt;br /&gt;
aber das Ergebnis ist dasselbe.)&lt;br /&gt;
&lt;br /&gt;
Die Funktion &amp;lt;code&amp;gt;wait&amp;lt;/code&amp;gt; erstellt ein &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt, das die&lt;br /&gt;
Funktion &amp;lt;code&amp;gt;setTimeout&amp;lt;/code&amp;gt; ausführt ([https://developer.mozilla.org/de/docs/Web/API/WindowTimers/setTimeout MDN web doc: &lt;br /&gt;
WindowTimers.setTimeout()]). Diese Funktion wartet eine gewisse Zeit &amp;lt;code&amp;gt;p_time&amp;lt;/code&amp;gt; und ruft dann eine Callback-Funktion auf.&lt;br /&gt;
Das ist die typische ES5-Vorgehensweise  zur Behandlung von asynchronen Aktionen. In diesem Fall wird die Callback-Funktion &amp;lt;code&amp;gt;p_resolve&amp;lt;/code&amp;gt;&lt;br /&gt;
aufgerufen. Das ist eine Funktion, die dem &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt mitteilt, dass die asynchrone Aktion erfolgreich beendet wurde&lt;br /&gt;
(und das &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekt nun die &amp;lt;code&amp;gt;then&amp;lt;/code&amp;gt;-Funktion ausführen könnte).&lt;br /&gt;
&lt;br /&gt;
Seit ES 2017 kann man in &amp;lt;code&amp;gt;async&amp;lt;/code&amp;gt;-Funktionen den &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt;-Operator verwenden, um das Ergebnis eines  &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objekts &lt;br /&gt;
zu verarbeiten. Das ist &#039;&#039;&#039;viel&#039;&#039;&#039; eleganter, als mit den (auch schon wieder veralteten) &amp;lt;code&amp;gt;then&amp;lt;/code&amp;gt;-Funktionen.&lt;br /&gt;
Sie schreiben einfach den Befehl &amp;lt;code&amp;gt;await wait(500);&amp;lt;/code&amp;gt; in den Rumpf Ihrer &amp;lt;code&amp;gt;async&amp;lt;/code&amp;gt;-Funktion. Dann wird die (asynchrone) Verarbeitung&lt;br /&gt;
des Rumpfes dieser funktion um 500 ms ({{dh}} um eine halbe Sekunde) unterbrochen, bevor der nächste Befehl abgearbeitet wird.&lt;br /&gt;
&lt;br /&gt;
====Asynchrones Laden von Bildern für PixiJS====&lt;br /&gt;
&lt;br /&gt;
PixiJS stellt das Object &amp;lt;code&amp;gt;PIXI.loader&amp;lt;/code&amp;gt; zur Verfügung&lt;br /&gt;
([http://pixijs.download/dev/docs/PIXI.loaders.Loader.html PixiJS API Documentation: PIXI.loaders.Loader]),&lt;br /&gt;
mit dem Sie Bilder (oder auch andere Medien) asynchron laden können. Die Bilder werden dabei gleich so gespeichert,&lt;br /&gt;
dass sie problemlos von PixiJS weiterverarbeitet werden können.&lt;br /&gt;
&lt;br /&gt;
Importieren Sie diesen Loader in Ihre Datei &amp;lt;code&amp;gt;app03.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Ersetzen Sie&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import {Application} from &#039;pixi.js&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
durch&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import {loader, Application} from &#039;pixi.js&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Fügen Sie außerdem folgenden Import-Befehl in die Datei &amp;lt;code&amp;gt;app03.js&amp;lt;/code&amp;gt; ein:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import imgBall from &#039;/img/tux-150.png&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Diesen Befehl kennen Sie schon. Er befindet sich noch in der Datei &amp;lt;code&amp;gt;game03a.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Dort sollten Sie ihn löschen (In der Datei &amp;lt;code&amp;gt;game03.js&amp;lt;/code&amp;gt; dürfen sie ihn dagegen nicht löschen.)&lt;br /&gt;
Wie Sie wissen, bewirkt dieser Import-Befehl, dass die&lt;br /&gt;
URL des Bildes &amp;lt;code&amp;gt;/img/tux-150.png&amp;lt;/code&amp;gt; in der Variablen&lt;br /&gt;
&amp;lt;code&amp;gt;imgBall&amp;lt;/code&amp;gt; gespeichert ist (und das Bild in den &lt;br /&gt;
Web-Ordner kopiert wird).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie nun vor der Initfunktion den folgenden Befehl ein.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
loader.add(&#039;imgBall&#039;, imgBall);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Damit teilen Sie dem Loader mit, welches Bild er später asynchron laden soll.&lt;br /&gt;
Als Argumente erwartet einen Namen, mit dem später auf das Bild zugegriffen werden kann, &lt;br /&gt;
sowie die URL des Bildes, under der er es im Web-Auftritt findet.&lt;br /&gt;
Es ist durchaus üblich, eine Vielzahl von Medien auf einmal ({{dh}} parallel) zu laden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
p_pixi.loader&lt;br /&gt;
  .add(...)&lt;br /&gt;
  .add(...)&lt;br /&gt;
  .add(...)&lt;br /&gt;
  .add(...)...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt könnten Sie die Bilder mittels &amp;lt;code&amp;gt;loader.load(geeigneteCallbackFunktion)&amp;lt;/code&amp;gt;&lt;br /&gt;
asynchron laden. Da PixiJS keine Proimises unterstützt, müsste man hier auf die alte ES-5-Methode zurückgreifen.&lt;br /&gt;
 &lt;br /&gt;
Unter &amp;lt;code&amp;gt;/wk_pixi/loader/asyncLoader&amp;lt;/code&amp;gt; finden Sie eine kleine Funktion, die das&lt;br /&gt;
eleganter mit Hilfe eines &amp;lt;code&amp;gt;Promise&amp;lt;/code&amp;gt;-Objektes macht. Importieren Sie diese Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import loadResources from &#039;/wk_pixi/loader/asyncLoader&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Jetzt können Sie die Ressourcen ganz elegant mit &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt; laden.&lt;br /&gt;
Fügen Sie  folgenden Code als erste Zeile in den Rumpf der Initfunktion ein:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const c_resources = await loadResources();&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Damit wird die asynchrone Ausführung der Initfunktion solange unterbrochen, bis alle Bilder geladen wurden.&lt;br /&gt;
Danach wird der nächste Befehl ausgeführt.&lt;br /&gt;
Das ist der Befehl, der das Spiel initialisiert:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
game.init(c_pixi_app);&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Ersetzen Sie ihn durch:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
game.init(c_pixi_app, c_resources);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das heißt, übergeben Sie der Initfunktion nicht nur das PixiJS-App-Objekt, sondern auch die Ressourcen (das Bild), das Sie geladen haben.&lt;br /&gt;
Jetzt müssen Sie nur noch die Initfunktion in der Datei &amp;lt;code&amp;gt;game03a.js&amp;lt;/code&amp;gt; anpassen. &lt;br /&gt;
&lt;br /&gt;
Ersetzen Sie dort in der &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;-Anweisung&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball = {},&lt;br /&gt;
v_ball_view =  ...;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
durch&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball = {},&lt;br /&gt;
v_ball_view;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das heißt, das Ball-View-Objekt wird nicht mehr hier erzeugt, sondern erst in der Initfunktion.&lt;br /&gt;
Fügen Sie zu diesem Zweck den Parameter &amp;lt;code&amp;gt;p_resources&amp;lt;/code&amp;gt; in die Parameterliste&lt;br /&gt;
der Initfunktion ein:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function init(p_pixi_app, p_resources)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In diesem Parameter werden der Funktion die Ressourcen (Bilder) übergeben,&lt;br /&gt;
die Sie zuvor asynchron) geladen haben. Damit können Sie jetzt die View erzeugen.&lt;br /&gt;
&lt;br /&gt;
Fügen Sie vor die beiden Befehle&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball_view.anchor.set(0.5),&lt;br /&gt;
p_pixi_app.stage.addChild(v_ball_view);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
den Befehl&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball_view = new Sprite(p_resources[&#039;imgBall&#039;].texture);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird, wie auch schon in den Aufgaben 2a und 3, ein &amp;lt;code&amp;gt;Sprite&amp;lt;/code&amp;gt;-Objekt&lt;br /&gt;
erstellt. Diesmal wird jedoch das Bild nicht aus einer Datei gelesen (&amp;lt;code&amp;gt;Sprite.fromImage...)&amp;lt;/code&amp;gt;)&lt;br /&gt;
sondern aus dem vom Loader erstellten Ressourcen-Objekt unter dem Namen &amp;lt;code&amp;gt;&#039;imgBall&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
extrahiert. Warum man nicht direkt das Objekt &amp;lt;code&amp;gt;p_resources[&#039;imgBall&#039;]&amp;lt;/code&amp;gt; verwenden kann, sondern dessen Textur verwenden muss, &lt;br /&gt;
ist eines von den unergründlichen Geheimnissen von PixiJS. &lt;br /&gt;
&lt;br /&gt;
BTW: Man bräuchte das Objekt &amp;lt;code&amp;gt;p_resources&amp;lt;/code&amp;gt; gar nicht als Argument an die Initfunktion übergeben.&lt;br /&gt;
Man könnte auch in der Datei &amp;lt;/code&amp;gt;game3a.js&amp;lt;/code&amp;gt;, auch wieder den Loader importieren&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import {loader, Sprite} from &#039;pixi.js&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
und dann mittels &amp;lt;code&amp;gt;load.resources&amp;lt;/code&amp;gt; auf dieses Objekt zugreifen. &lt;br /&gt;
Allerdings ist die Kommunikation zweier Module über ein globales Objekt (wie das Objekt &amp;lt;code&amp;gt;loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
&#039;&#039;deprecated&#039;&#039;, da man nicht weiß, wann und ob überhaupt das darin enthaltene Ressourcenobjekt sauber initialisiert wurde.&lt;br /&gt;
Eine direkte Kommunikation mittels Parametern und Argumenten ist dem vorzuziehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3b===&lt;br /&gt;
Erstellen Sie zunächst wie in Aufgabe 2 beschrieben eine Kopie der Lösung von Aufgabe 3a und nennen Sie sie 3b (&amp;lt;code&amp;gt;index03b.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;app03b.js&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;game03b.js&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Erweitern Sie Ihre Lösung von Aufgabe 3 so, dass 5 unterschiedliche Vögel auf unterschiedlichen Routen über die Bühne fliegen.&lt;br /&gt;
(Hier benötigen Sie Ihr Wissen über den Umgang mit Arrays: siehe Praktikumsaufgaben [[MMProg: Praktikum: WiSe 2018/19: EcmaScript01|EcmaScript01]] und [[MMProg: Praktikum: WiSe 2018/19: EcmaScript02|EcmaScript02]].)&lt;br /&gt;
&lt;br /&gt;
Gehen Sie dazu folgendermaßen vor:&lt;br /&gt;
&lt;br /&gt;
* Laden Sie in der Datei &amp;lt;code&amp;gt;app03b.js&amp;lt;/code&amp;gt; die beiden Bilder &amp;lt;code&amp;gt;/img/owl-150.png&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;/img/owl-150.png&amp;lt;/code&amp;gt; asynchron mittels des PixiJS-Loaders.&lt;br /&gt;
* Bearbeiten Sie nun die Datei &amp;lt;code&amp;gt;game03b.js&amp;lt;/code&amp;gt;*&lt;br /&gt;
* Legen Sie in einer Variablen oder Konstanten &amp;lt;code&amp;gt;v_ball_nr&amp;lt;/code&amp;gt; die Anzahl der Vögel fest, die fliegen sollen. Initialisieren Sie diese mit der Zahl &amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Ersetzen Sie &amp;lt;code&amp;gt;v_ball&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;v_ball_view&amp;lt;/code&amp;gt; durch &amp;lt;code&amp;gt;v_balls&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;v_ball_views&amp;lt;/code&amp;gt;. Diese Variablen sollen jeweils ein Array mit &amp;lt;code&amp;gt;v_ball_nr&amp;lt;/code&amp;gt; Model-Objekten bzw. &amp;lt;code&amp;gt;v_ball_nr&amp;lt;/code&amp;gt; zugehörigen View-Objekten beinhalten. Die Variable &amp;lt;code&amp;gt;v_ball_views&amp;lt;/code&amp;gt; wird in der Initfunktion initialisiert und die Variable &amp;lt;code&amp;gt;v_balls&amp;lt;/code&amp;gt; in der Resetfunktion.&lt;br /&gt;
* Initialisieren Sie das Array &amp;lt;code&amp;gt;v_ball_views&amp;lt;/code&amp;gt; in der Initfunktion mit Hilfe einer Schleife und des [https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/push Push-Befehls]. Sie müssen &amp;lt;code&amp;gt;v_ball_nr&amp;lt;/code&amp;gt; Sprite-Objekte erzeugen und ins Array einfügen. Als Bild wählen Sie per Zufallsentscheidung (&amp;lt;code&amp;gt;Math.random() &amp;lt; 0.5&amp;lt;/code&amp;gt;) jeweils die Eule oder Tux.&lt;br /&gt;
* Initialisieren Sie das Array &amp;lt;code&amp;gt;v_balls&amp;lt;/code&amp;gt; in der Resetfunktion mit Hilfe einer Schleife und des Push-Befehls. Der Radius aller fünf Bälle sei 75. Die Position wählen Sie zufällig &amp;lt;code&amp;gt;Math.random()&amp;lt;/code&amp;gt; innerhalb der Bühne, die Geschwindigkeit in $x$- und $y$-Richtung ebenfalls zufällig jeweils zwischen 100 und 400.&lt;br /&gt;
* Sorgen Sie in der Updatefunktion mit Hilfe einer Schleife dafür, dass all 5 Objekte im Array &amp;lt;code&amp;gt;v_balls&amp;lt;/code&amp;gt; aktualisiert werden.&lt;br /&gt;
* Sorgen Sie in der Renderfunktion mit Hilfe einer Schleife dafür, dass all 5 Objekte im Array &amp;lt;code&amp;gt;v_ball_views&amp;lt;/code&amp;gt; rerendert werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgaben 4 bis 10===&lt;br /&gt;
&lt;br /&gt;
Nun können und sollten Sie zur Übung die Aufgaben 4 bis 10 der [[MMProg: Praktikum: WiSe 2017/18: GameLoop01#Aufgabe 2|ersten Praktikumsaufgabe]] &lt;br /&gt;
ebenfalls mit Hilfe von PixiJS lösen. Laden Sie dabei die Bilder wieder asynchron und verwenden Sie JSON zur Konfiguration. Sie sollten ruhig auch mal&lt;br /&gt;
mehr als einen Vogel animieren, {{zB}} indem Sie mehrere Eulen hintereinander die Wand entlang fliegen lassen. &lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;11&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Franzih</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46309</id>
		<title>MMProg: Praktikum: WiSe 2018/19: Ball01</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46309"/>
		<updated>2018-11-21T11:59:44Z</updated>

		<summary type="html">&lt;p&gt;Franzih: /* Aufgabe 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2018/19:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Ball01.git Git-Repository]) &lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Im Git-Repository finden Sie zwei WebStorm-Projekte zum Thema GameLoop:&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop01.git WK_GameLoop01]&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop02.git WK_GameLoop02]&lt;br /&gt;
&lt;br /&gt;
Machen Sie sich mit den Projekten vertraut. Die Web-Anwendung &amp;lt;code&amp;gt;src/js/app&amp;lt;/code&amp;gt; des zweiten Projektes dient als Ausgangsbasis für diese Praktikumsaufgabe.    &lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel finden Sie diverse Game-Loop-Varianten. Schrittweise werden potentielle&lt;br /&gt;
Probleme behoben. Dieses Projekt verfolgt das didaktische Ziel, Ihnen die Probleme und potentielle&lt;br /&gt;
Lösungen im Zusammenhang mit JavaScript-Animationen zu verdeutlichen.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel wurde eine Game-Loop-Klasse realisiert, die sie für dieses Praktikum&lt;br /&gt;
nutzen können und sollten. Diese Klasse basiert auf den Ergebnissen des ersten Projektes,&lt;br /&gt;
stellt aber – im Gegensatz zu einigen Web-Anwendungen des ersten Projekt – bislang keine Informationen &lt;br /&gt;
über die aktuelle Frame-Rate bereit. Dies ist aber für diese Praktikumsaufgabe nicht von Interesse.&lt;br /&gt;
&lt;br /&gt;
Importieren Sie das leere Git-Projekt [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/Ball01.git Ball01] in WebStorm.&lt;br /&gt;
Laden Sie annschließend mittels &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt; alle benötigten Node.js-Module in das Projekt.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig.&lt;br /&gt;
Falls Sie da machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
git remote remove origin&lt;br /&gt;
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Ball01.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie 10 Web-Anwendungen vor: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die JavaScript-Datei &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;ball01.js&amp;lt;/code&amp;gt; einbindet. &amp;lt;code&amp;gt;index02.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt; etc. sind analog aufgebaut.&lt;br /&gt;
Wenn Sie irgendeine dieser Anwendungen im Browser öffnen, sehen Sie eine Eule in der linken oberen Bildschirmecke. Diese sollen&lt;br /&gt;
sie auf unterschiedliche Art und Weise animieren. Beachten Sie, dass im Folgenden der Avatar nicht „Eule“, sondern „Ball“ genannt wird.&lt;br /&gt;
Die Eule ist lediglich eine View des ballartigen Objektes.&lt;br /&gt;
&lt;br /&gt;
Lösen Sie jede der folgenden Aufgaben in einer der vorgegebenen Apps.&lt;br /&gt;
Scheuen Sie sich nicht davor, eigene Experimente durchzuführen. Wenn die vorgegebenen Apps nicht ausreichen sollten, legen Sie einfach&lt;br /&gt;
noch ein paar an.&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;src/js/ball/ball&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
Passen Sie zur Lösung dieser Aufgabe die Datei &amp;lt;code&amp;gt;src/js/ball/ball01.js&amp;lt;/code&amp;gt; an.&lt;br /&gt;
Lassen Sie sich durch den Code der Datei &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt; aus dem Beispiel &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; inspirieren.&lt;br /&gt;
(Sie könnten auch &amp;lt;code&amp;gt;ball_interpolate.js&amp;lt;/code&amp;gt; verwenden, aber das verwirrt Sie vermutlich zurzeit deutlich mehr, als dass es &lt;br /&gt;
Ihnen nützt.) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lassen Sie den Ball horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tipp: http://ryanve.com/lab/dimensions/&lt;br /&gt;
&lt;br /&gt;
Berücksichtigen Sie, dass der Ball 150 Pixel breit ist, {{dh}} einen Radius von 75 Pixel hat, &lt;br /&gt;
und dass der Ankerpunkt im linken oberen Eck des zugehörigen Bildes liegt. &lt;br /&gt;
Sie müssen im Ball-Objekt auch die Radius des Balls speichern und diesen Wert bei der Kollissionserkennung&lt;br /&gt;
und -behandlung berücksichtigen. Übrigens, wenn Sie &amp;lt;code&amp;gt;v_ball_view&amp;lt;/code&amp;gt; wie in &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt;&lt;br /&gt;
von &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; definieren, können Sie mittels &amp;lt;code&amp;gt;v_ball_view.offsetWidth/2;&amp;lt;/code&amp;gt;&lt;br /&gt;
die aktuelle Breite des Ballobjektes aus der View auslesen.&lt;br /&gt;
&lt;br /&gt;
Ein Tipp noch: Wenn Sie das Ball-Objekt zunächst als leeres Objekt definieren und danach in der&lt;br /&gt;
Reset-Funktion initialisieren, funktionieren Ihre Anwendungen auch noch, wenn Sie später einen&lt;br /&gt;
Start/Stopp- und einen Pause-Button einfügen (vgl. {{zB}} &amp;lt;code&amp;gt;index_start_stop_toggling.html&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt;). &lt;br /&gt;
Sollten Sie keine Buttons zur Steuerung einfügen wollen, können Sie die Objekte auch direkt bei &lt;br /&gt;
der Definition initialisieren.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, die Sourcen mittels &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; zu übersetzen. Und beachten Sie,&lt;br /&gt;
dass im Browser nur die Dateien &amp;lt;code&amp;gt;web/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; funktionieren. Wenn Sie versuchen,&lt;br /&gt;
&amp;lt;code&amp;gt;src/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; erhalten Sie im Browser einen leeren Screen und in der Browser-Konsole drei Fehlermeldungen, &lt;br /&gt;
dass gewissen Dateien nicht geladen werden können.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie den Ball nicht waagerecht, sondern in der horizontalen Mitte des Browserfensters senkrecht von Fensterrand zu Fensterrand fliegen.&lt;br /&gt;
&lt;br /&gt;
Um die Aufgabe zu lösen, müssen Sie für der Ball zusätzlich eine y-Position und eine y-Geschwindigkeit definieren. Die Berechnung der aktuellen y-Position funktioniert&lt;br /&gt;
analog zur Berechnung der aktuellen x-Position. &lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, auch die Kollissionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und Sie müssen natürlich die Render-Funktion anpassen, sodass die aktuelle y-Position beim Rendern auch berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball von der Browsermitte aus schräg über den Bildschirm fliegen. In x-Richtung soll er doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 4===&lt;br /&gt;
&lt;br /&gt;
Setzen Sie die x-Start-Position des Balls auf &amp;lt;code&amp;gt;-100&amp;lt;/code&amp;gt; und starten Sie die Web-App. Den Effekt, den Sie sehen, nennt&lt;br /&gt;
man [[Kollisionserkennung und -behandlung|Penetration]]. Die Eule hängt in der Wand fest, da sie nicht den Kollissionsbereich&lt;br /&gt;
(die linke Wand) in einem Schritt verlässt. Daher besteht die Kollission fort und im nächsten Schritt ändert sie wieder ihre Flugrichtung.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie das, indem Sie die Kollisionserkennung und -behandlung verbessern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung analog an. &lt;br /&gt;
&lt;br /&gt;
Sie können und sollten sogar noch einen Schritt weiter gehen und den Ball &lt;br /&gt;
wieder zurück auf die Bühne schieben, wenn er in die Wand eingedrungen ist.&lt;br /&gt;
In die Wand einzudringen ist zwar physikalisch nicht möglich, aber leider in&lt;br /&gt;
einer Simulation der physikalischen Welt nur schwer zu vermeiden, da die&lt;br /&gt;
Position nur alle 16,7 ms berechnet wird. War der Ball zu einem Zeitpunkt&lt;br /&gt;
noch vor der Mauer, kann er beim nächsten Schritt schon drinnen stecken.&lt;br /&gt;
Insbesondere bei sehr schnellen Objekten kann das dann zu den&lt;br /&gt;
beobachteten Penetrationseffekten führen.&lt;br /&gt;
&lt;br /&gt;
Also schieben Sie den Ball besser zurück auf die Bühne.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.x = v_stage.left;&lt;br /&gt;
  v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.x = v_stage.right - 2*v_ball.r;&lt;br /&gt;
  v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung wiederum analog an.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 5===&lt;br /&gt;
&lt;br /&gt;
Ändern Sie die Kollisionserkennung und -behandlung so ab, dass sich der Ball ausgehend von der linken oberen Fensterecke&lt;br /&gt;
im Uhrzeigersinn immer entlang des Fensterrandes bewegt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte: Hier ist es besonders wichtig, dass Sie den Ball wieder auf die Bühne zurückschieben, wenn er mit einer&lt;br /&gt;
Wand kollidiert. Ansonsten verschwindet der Ball schnell im Nirgendwo.&lt;br /&gt;
&lt;br /&gt;
(Anmerkung: Dies war einmal eine Aufgabe im Rahmen des Prüfungspraktikums, wobei die Lösung zur 3. Aufgabe vorgegeben war.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 6===&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie diesmal nicht die Lösung von Aufgabe 5, sondern die von Aufgabe 4. Im Folgenden arbeiten Sie&lt;br /&gt;
wieder mit der normalen Kollissionserkennung und -behandlung. Positionieren Sie den Ball allerdings wieder im linken oberen Eck&lt;br /&gt;
(in Aufgabe 4 hatten Sie sie außerhalb der Bühne platziert).&lt;br /&gt;
&lt;br /&gt;
Die neue Position des Balls berechnen Sie mit Hilfe der Geschwindigkeit (velocity, &amp;lt;code&amp;gt;vx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;vy&amp;lt;/code&amp;gt;). Doch auch die&lt;br /&gt;
Geschwindigkeig kann sich im Laufe der Zeit ändern. Dazu benötigt man die Beschleunigung (acceleration, &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie zu Ihrem Ball  zwei weitere Attribute &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt; (Beschleunigung in x-Richtung) und &lt;br /&gt;
&amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt; (Beschleunigung in y-Richtung) hinzu. Setzen Sie die Initialwerte auf&lt;br /&gt;
&amp;lt;code&amp;gt;400&amp;lt;/code&amp;gt; (Pixel pro Sekunde) bzw. &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt; (Pixel pro Sekunde). Das heißt, Sie möchten,&lt;br /&gt;
dass der Ball in jeder Sekunde um 400 bzw. 200 Pixel pro Sekunde mehr zurücklegt als zuvor.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie jetzt die Web-App starten, beschleunigt der Ball allerdings noch nicht.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Code wird die Position 60 mal pro Sekunde mit Hilfe des folgenden Codes aktualisiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.x += v_ball.vx * p_delta_s;&lt;br /&gt;
v_ball.y += v_ball.vy * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit wird zur Position hinzuaddiert. Allerdings ist die Geschwindigkeit&lt;br /&gt;
in Pixeln pro Sekunde angegeben. Die Modellaktualisierung passiert jedoch alle $0,0167$&lt;br /&gt;
Sekunden. In dieser Zeit bewegt sich der Ball nur um das $0,0167$-fache (= $1,67$%) der Sekundengeschwindigkeit weiter.&lt;br /&gt;
Dieser Faktor ist im Attribut &amp;lt;code&amp;gt;p_delta_s&amp;lt;/code&amp;gt; enthalten. Dieser wird mit &lt;br /&gt;
$1/60 = 0,0167$ initialisiert, sofern der Update-Methode kein anderer Wert übergeben wird.&lt;br /&gt;
&lt;br /&gt;
Auf genau dieselbe Weise wird die aktuelle Geschwindigkeit mit Hilfe der Beschleunigung&lt;br /&gt;
berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx += v_ball.ax * p_delta_s;&lt;br /&gt;
v_ball.vy += v_ball.ay * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie diesen Code in Ihre Model-Update-Funktion ein und starten Sie den Ball erneut.&lt;br /&gt;
Wenn Sie jetzt Ihre Web-App laufen lassen, stellen Sie fest, dass der Ball zunächst beschleunigt,&lt;br /&gt;
nach eine Kollision aber wieder abbremst. Nach der nächsten Kollision beschleunigt er wieder.&lt;br /&gt;
&lt;br /&gt;
Um diesen Effekt zu vermeiden, müssen Sie jedes mal, wenn Sie bei der Kollissionsbehandlung das Vorzeichen&lt;br /&gt;
der Geschwindigkeit ändern, das Vorzeichen der zugehörigen Beschleunigung analog ändern.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise muss der Code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
um&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.ax = -Math.abs(v_ball.ax);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 7===&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie die Kollissionsbehandlung so um, dass im Falle einer Kollission des Balls &lt;br /&gt;
mit dem unteren Fensterrand sowohl die Geschwindigkeit als auch die Beschleunigung&lt;br /&gt;
jeweils in x- und in y-Richtung auf Null gesetzt wird. Das heißt, der &lt;br /&gt;
Ball bleibt bei einer Kollision mit dem unteren Rand stehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 8===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie der Ball im linken oberen Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von 0 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 800. (Diese Zahlen sind gut für meinen Monitor geeignet,&lt;br /&gt;
der eine Auflösung von 1600x900 hat. Wenn Sie einen deutlich kleineren oder größeren&lt;br /&gt;
Monitor haben, müssen Sie die Zahlen evtl. anpassen.)&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 9===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie den Ball im linken unteren Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von -400 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 200.&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
Allerdings ist es nicht ganz sauber, die Erdanziehung mittels &amp;lt;code&amp;gt;v_ball.ax&amp;lt;/code&amp;gt; zu simulieren.&lt;br /&gt;
Diese Beschleunigung ist die Beschleunigung, die vom Ball selbst ausgeht (die also von der Eule&lt;br /&gt;
per Muskelkraft geleistet wird). Wenn der Ball seine Bewegungsrichtung ändert, ändert sich auch die Richtung der Beschleunigung (eine Eule beschleunigt immer in Flugrichtung, vgl. Aufgabe 6).&lt;br /&gt;
Die Richtung der Erbbeschleunigung ändert jedoch bei einer Kollision nicht.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie daher Ihre Anwendung vorlgendermaßen:&lt;br /&gt;
&lt;br /&gt;
* Fügen Sie eine Variable &amp;lt;code&amp;gt;v_g = 981&amp;lt;/code&amp;gt; in die &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;-Anweisung ein. (981 wurde in Anlehnung an die Gravitationskonstante der Erde gewählt.)&lt;br /&gt;
* Reduzieren Sie die Eigenbeschleunigung der Eule in $y$-Richtung auf &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. (Jetzt sollte sich die Eule wieder geradlinig bewegen.)&lt;br /&gt;
* Ersetzen Sie un der Update-Funktion &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += v_ball.ay * p_delta_s;&amp;lt;/source&amp;gt; durch &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += (v_ball.ay+v_g) * p_delta_s;&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Das heißt, berücksichtigen Sie bei der Berechnung der $y$-Geschwindigkeit des Balles zusätzlich die Erdanziehungskraft. Nun sollte die Eule wieder einen sauberen Parabelflug vollführen.&lt;br /&gt;
 &lt;br /&gt;
Alles, was jetzt noch fehlt, ist ein Gummiband, mit dem Sie die Eule beschleunigen können. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 10===&lt;br /&gt;
&lt;br /&gt;
Machen Sie eigene Experimente. Bringen Sie {{zB}} den Ball dazu, wie ein Flummi&lt;br /&gt;
zu springen, indem sie seine Geschwindigkeit in x- und y-Richtung bei einem Bodenkontakt&lt;br /&gt;
um einen gewissen Prozentsatz reduzieren, aber nicht gleich auf null setzen.&lt;br /&gt;
(Die Beschleunigung, die die Erdanziehung simuliert, bleibt die ganze Zeit über gleich).&lt;br /&gt;
Achtung: Bei einem Bodenkontakt, dreht sich das Vorzeichen der y-Geschwindigkeit um, &lt;br /&gt;
das der x-Geschwindigkeit ändert sich dagegen nicht.&lt;br /&gt;
&lt;br /&gt;
Nervig ist, dass der Ball zum Schluss immer noch ganz leicht hüpft und gar nicht&lt;br /&gt;
zur Ruhe kommt. Vielleicht können Sie auch dieses Problem beheben.&lt;br /&gt;
&lt;br /&gt;
Oder probieren Sie etwas ganz anderes aus.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Franzih</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46307</id>
		<title>MMProg: Praktikum: WiSe 2018/19: Ball01</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46307"/>
		<updated>2018-11-21T11:26:40Z</updated>

		<summary type="html">&lt;p&gt;Franzih: /* Aufgabe 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2018/19:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Ball01.git Git-Repository]) &lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Im Git-Repository finden Sie zwei WebStorm-Projekte zum Thema GameLoop:&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop01.git WK_GameLoop01]&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop02.git WK_GameLoop02]&lt;br /&gt;
&lt;br /&gt;
Machen Sie sich mit den Projekten vertraut. Die Web-Anwendung &amp;lt;code&amp;gt;src/js/app&amp;lt;/code&amp;gt; des zweiten Projektes dient als Ausgangsbasis für diese Praktikumsaufgabe.    &lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel finden Sie diverse Game-Loop-Varianten. Schrittweise werden potentielle&lt;br /&gt;
Probleme behoben. Dieses Projekt verfolgt das didaktische Ziel, Ihnen die Probleme und potentielle&lt;br /&gt;
Lösungen im Zusammenhang mit JavaScript-Animationen zu verdeutlichen.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel wurde eine Game-Loop-Klasse realisiert, die sie für dieses Praktikum&lt;br /&gt;
nutzen können und sollten. Diese Klasse basiert auf den Ergebnissen des ersten Projektes,&lt;br /&gt;
stellt aber – im Gegensatz zu einigen Web-Anwendungen des ersten Projekt – bislang keine Informationen &lt;br /&gt;
über die aktuelle Frame-Rate bereit. Dies ist aber für diese Praktikumsaufgabe nicht von Interesse.&lt;br /&gt;
&lt;br /&gt;
Importieren Sie das leere Git-Projekt [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/Ball01.git Ball01] in WebStorm.&lt;br /&gt;
Laden Sie annschließend mittels &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt; alle benötigten Node.js-Module in das Projekt.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig.&lt;br /&gt;
Falls Sie da machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
git remote remove origin&lt;br /&gt;
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Ball01.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie 10 Web-Anwendungen vor: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die JavaScript-Datei &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;ball01.js&amp;lt;/code&amp;gt; einbindet. &amp;lt;code&amp;gt;index02.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt; etc. sind analog aufgebaut.&lt;br /&gt;
Wenn Sie irgendeine dieser Anwendungen im Browser öffnen, sehen Sie eine Eule in der linken oberen Bildschirmecke. Diese sollen&lt;br /&gt;
sie auf unterschiedliche Art und Weise animieren. Beachten Sie, dass im Folgenden der Avatar nicht „Eule“, sondern „Ball“ genannt wird.&lt;br /&gt;
Die Eule ist lediglich eine View des ballartigen Objektes.&lt;br /&gt;
&lt;br /&gt;
Lösen Sie jede der folgenden Aufgaben in einer der vorgegebenen Apps.&lt;br /&gt;
Scheuen Sie sich nicht davor, eigene Experimente durchzuführen. Wenn die vorgegebenen Apps nicht ausreichen sollten, legen Sie einfach&lt;br /&gt;
noch ein paar an.&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;src/js/ball/ball&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
Passen Sie zur Lösung dieser Aufgabe die Datei &amp;lt;code&amp;gt;src/js/ball/ball01.js&amp;lt;/code&amp;gt; an.&lt;br /&gt;
Lassen Sie sich durch den Code der Datei &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt; aus dem Beispiel &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; inspirieren.&lt;br /&gt;
(Sie könnten auch &amp;lt;code&amp;gt;ball_interpolate.js&amp;lt;/code&amp;gt; verwenden, aber das verwirrt Sie vermutlich zurzeit deutlich mehr, als dass es &lt;br /&gt;
Ihnen nützt.) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lassen Sie den Ball horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tipp: http://ryanve.com/lab/dimensions/&lt;br /&gt;
&lt;br /&gt;
Berücksichtigen Sie, dass der Ball 150 Pixel breit ist, {{dh}} einen Radius von 75 Pixel hat, &lt;br /&gt;
und das der Ankerpunkt im linken oberen Eck des zugehörigen Bildes liegt. &lt;br /&gt;
Sie müssen im Ball-Objekt auch die Radius des Balls speichern und diesen Wert bei der Kollissionserkennung&lt;br /&gt;
und -behandlung berücksichtigen. Übrigens, wenn Sie &amp;lt;code&amp;gt;v_ball_view&amp;lt;/code&amp;gt; wie in &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt;&lt;br /&gt;
von &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; definieren, können Sie mittels &amp;lt;code&amp;gt;v_ball_view.offsetWidth/2;&amp;lt;/code&amp;gt;&lt;br /&gt;
die aktuelle Breite des Ballobjektes aus der View auslesen.&lt;br /&gt;
&lt;br /&gt;
Ein Tipp noch: Wenn Sie das Ball-Objekt zunächst als leeres Objekt definieren und danach in der&lt;br /&gt;
Reset-Funktion initialisieren, funktionieren Ihre Anwendungen auch noch, wenn Sie später einen&lt;br /&gt;
Start/Stopp- und einen Pause-Button einfügen (vgl. {{zB}} &amp;lt;code&amp;gt;index_start_stop_toggling.html&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt;). &lt;br /&gt;
Sollten Sie keine Buttons zur Steuerung einfügen wollen, können Sie die Objekte auch direkt bei &lt;br /&gt;
der Definition initialisieren.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, die Sourcen mittels &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; zu übersetzen. Und beachten Sie,&lt;br /&gt;
dass im Browser nur die Dateien &amp;lt;code&amp;gt;web/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; funktionieren. Wenn Sie versuchen,&lt;br /&gt;
&amp;lt;code&amp;gt;src/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; erhalten Sie im Browser einen leeren Screen und in der Browser-Konsole drei Fehlermeldungen, &lt;br /&gt;
dass gewissen Dateien nicht geladen werden können.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie den Ball nicht waagerecht, sondern in der horizontalen Mitte des Browserfensters senkrecht von Fensterrand zu Fensterrand fliegen.&lt;br /&gt;
&lt;br /&gt;
Um die Aufgabe zu lösen, müssen Sie für der Ball zusätzlich eine y-Position und eine y-Geschwindigkeit definieren. Die Berechnung der aktuellen y-Position funktioniert&lt;br /&gt;
analog zur Berechnung der aktuellen x-Position. &lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, auch die Kollissionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und Sie müssen natürlich die Render-Funktion anpassen, sodass die aktuelle y-Position beim Rendern auch berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball von der Browsermitte aus schräg über den Bildschirm fliegen. In x-Richtung soll er doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 4===&lt;br /&gt;
&lt;br /&gt;
Setzen Sie die x-Start-Position des Balls auf &amp;lt;code&amp;gt;-100&amp;lt;/code&amp;gt; und starten Sie die Web-App. Den Effekt, den Sie sehen, nennt&lt;br /&gt;
man [[Kollisionserkennung und -behandlung|Penetration]]. Die Eule hängt in der Wand fest, da sie nicht den Kollissionsbereich&lt;br /&gt;
(die linke Wand) in einem Schritt verlässt. Daher besteht die Kollission fort und im nächsten Schritt ändert sie wieder ihre Flugrichtung.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie das, indem Sie die Kollisionserkennung und -behandlung verbessern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung analog an. &lt;br /&gt;
&lt;br /&gt;
Sie können und sollten sogar noch einen Schritt weiter gehen und den Ball &lt;br /&gt;
wieder zurück auf die Bühne schieben, wenn er in die Wand eingedrungen ist.&lt;br /&gt;
In die Wand einzudringen ist zwar physikalisch nicht möglich, aber leider in&lt;br /&gt;
einer Simulation der physikalischen Welt nur schwer zu vermeiden, da die&lt;br /&gt;
Position nur alle 16,7 ms berechnet wird. War der Ball zu einem Zeitpunkt&lt;br /&gt;
noch vor der Mauer, kann er beim nächsten Schritt schon drinnen stecken.&lt;br /&gt;
Insbesondere bei sehr schnellen Objekten kann das dann zu den&lt;br /&gt;
beobachteten Penetrationseffekten führen.&lt;br /&gt;
&lt;br /&gt;
Also schieben Sie den Ball besser zurück auf die Bühne.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.x = v_stage.left;&lt;br /&gt;
  v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.x = v_stage.right - 2*v_ball.r;&lt;br /&gt;
  v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung wiederum analog an.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 5===&lt;br /&gt;
&lt;br /&gt;
Ändern Sie die Kollisionserkennung und -behandlung so ab, dass sich der Ball ausgehend von der linken oberen Fensterecke&lt;br /&gt;
im Uhrzeigersinn immer entlang des Fensterrandes bewegt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte: Hier ist es besonders wichtig, dass Sie den Ball wieder auf die Bühne zurückschieben, wenn er mit einer&lt;br /&gt;
Wand kollidiert. Ansonsten verschwindet der Ball schnell im Nirgendwo.&lt;br /&gt;
&lt;br /&gt;
(Anmerkung: Dies war einmal eine Aufgabe im Rahmen des Prüfungspraktikums, wobei die Lösung zur 3. Aufgabe vorgegeben war.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 6===&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie diesmal nicht die Lösung von Aufgabe 5, sondern die von Aufgabe 4. Im Folgenden arbeiten Sie&lt;br /&gt;
wieder mit der normalen Kollissionserkennung und -behandlung. Positionieren Sie den Ball allerdings wieder im linken oberen Eck&lt;br /&gt;
(in Aufgabe 4 hatten Sie sie außerhalb der Bühne platziert).&lt;br /&gt;
&lt;br /&gt;
Die neue Position des Balls berechnen Sie mit Hilfe der Geschwindigkeit (velocity, &amp;lt;code&amp;gt;vx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;vy&amp;lt;/code&amp;gt;). Doch auch die&lt;br /&gt;
Geschwindigkeig kann sich im Laufe der Zeit ändern. Dazu benötigt man die Beschleunigung (acceleration, &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie zu Ihrem Ball  zwei weitere Attribute &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt; (Beschleunigung in x-Richtung) und &lt;br /&gt;
&amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt; (Beschleunigung in y-Richtung) hinzu. Setzen Sie die Initialwerte auf&lt;br /&gt;
&amp;lt;code&amp;gt;400&amp;lt;/code&amp;gt; (Pixel pro Sekunde) bzw. &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt; (Pixel pro Sekunde). Das heißt, Sie möchten,&lt;br /&gt;
dass der Ball in jeder Sekunde um 400 bzw. 200 Pixel pro Sekunde mehr zurücklegt als zuvor.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie jetzt die Web-App starten, beschleunigt der Ball allerdings noch nicht.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Code wird die Position 60 mal pro Sekunde mit Hilfe des folgenden Codes aktualisiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.x += v_ball.vx * p_delta_s;&lt;br /&gt;
v_ball.y += v_ball.vy * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit wird zur Position hinzuaddiert. Allerdings ist die Geschwindigkeit&lt;br /&gt;
in Pixeln pro Sekunde angegeben. Die Modellaktualisierung passiert jedoch alle $0,0167$&lt;br /&gt;
Sekunden. In dieser Zeit bewegt sich der Ball nur um das $0,0167$-fache (= $1,67$%) der Sekundengeschwindigkeit weiter.&lt;br /&gt;
Dieser Faktor ist im Attribut &amp;lt;code&amp;gt;p_delta_s&amp;lt;/code&amp;gt; enthalten. Dieser wird mit &lt;br /&gt;
$1/60 = 0,0167$ initialisiert, sofern der Update-Methode kein anderer Wert übergeben wird.&lt;br /&gt;
&lt;br /&gt;
Auf genau dieselbe Weise wird die aktuelle Geschwindigkeit mit Hilfe der Beschleunigung&lt;br /&gt;
berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx += v_ball.ax * p_delta_s;&lt;br /&gt;
v_ball.vy += v_ball.ay * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie diesen Code in Ihre Model-Update-Funktion ein und starten Sie den Ball erneut.&lt;br /&gt;
Wenn Sie jetzt Ihre Web-App laufen lassen, stellen Sie fest, dass der Ball zunächst beschleunigt,&lt;br /&gt;
nach eine Kollision aber wieder abbremst. Nach der nächsten Kollision beschleunigt er wieder.&lt;br /&gt;
&lt;br /&gt;
Um diesen Effekt zu vermeiden, müssen Sie jedes mal, wenn Sie bei der Kollissionsbehandlung das Vorzeichen&lt;br /&gt;
der Geschwindigkeit ändern, das Vorzeichen der zugehörigen Beschleunigung analog ändern.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise muss der Code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
um&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.ax = -Math.abs(v_ball.ax);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 7===&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie die Kollissionsbehandlung so um, dass im Falle einer Kollission des Balls &lt;br /&gt;
mit dem unteren Fensterrand sowohl die Geschwindigkeit als auch die Beschleunigung&lt;br /&gt;
jeweils in x- und in y-Richtung auf Null gesetzt wird. Das heißt, der &lt;br /&gt;
Ball bleibt bei einer Kollision mit dem unteren Rand stehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 8===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie der Ball im linken oberen Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von 0 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 800. (Diese Zahlen sind gut für meinen Monitor geeignet,&lt;br /&gt;
der eine Auflösung von 1600x900 hat. Wenn Sie einen deutlich kleineren oder größeren&lt;br /&gt;
Monitor haben, müssen Sie die Zahlen evtl. anpassen.)&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 9===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie den Ball im linken unteren Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von -400 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 200.&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
Allerdings ist es nicht ganz sauber, die Erdanziehung mittels &amp;lt;code&amp;gt;v_ball.ax&amp;lt;/code&amp;gt; zu simulieren.&lt;br /&gt;
Diese Beschleunigung ist die Beschleunigung, die vom Ball selbst ausgeht (die also von der Eule&lt;br /&gt;
per Muskelkraft geleistet wird). Wenn der Ball seine Bewegungsrichtung ändert, ändert sich auch die Richtung der Beschleunigung (eine Eule beschleunigt immer in Flugrichtung, vgl. Aufgabe 6).&lt;br /&gt;
Die Richtung der Erbbeschleunigung ändert jedoch bei einer Kollision nicht.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie daher Ihre Anwendung vorlgendermaßen:&lt;br /&gt;
&lt;br /&gt;
* Fügen Sie eine Variable &amp;lt;code&amp;gt;v_g = 981&amp;lt;/code&amp;gt; in die &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;-Anweisung ein. (981 wurde in Anlehnung an die Gravitationskonstante der Erde gewählt.)&lt;br /&gt;
* Reduzieren Sie die Eigenbeschleunigung der Eule in $y$-Richtung auf &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. (Jetzt sollte sich die Eule wieder geradlinig bewegen.)&lt;br /&gt;
* Ersetzen Sie un der Update-Funktion &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += v_ball.ay * p_delta_s;&amp;lt;/source&amp;gt; durch &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += (v_ball.ay+v_g) * p_delta_s;&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Das heißt, berücksichtigen Sie bei der Berechnung der $y$-Geschwindigkeit des Balles zusätzlich die Erdanziehungskraft. Nun sollte die Eule wieder einen sauberen Parabelflug vollführen.&lt;br /&gt;
 &lt;br /&gt;
Alles, was jetzt noch fehlt, ist ein Gummiband, mit dem Sie die Eule beschleunigen können. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 10===&lt;br /&gt;
&lt;br /&gt;
Machen Sie eigene Experimente. Bringen Sie {{zB}} den Ball dazu, wie ein Flummi&lt;br /&gt;
zu springen, indem sie seine Geschwindigkeit in x- und y-Richtung bei einem Bodenkontakt&lt;br /&gt;
um einen gewissen Prozentsatz reduzieren, aber nicht gleich auf null setzen.&lt;br /&gt;
(Die Beschleunigung, die die Erdanziehung simuliert, bleibt die ganze Zeit über gleich).&lt;br /&gt;
Achtung: Bei einem Bodenkontakt, dreht sich das Vorzeichen der y-Geschwindigkeit um, &lt;br /&gt;
das der x-Geschwindigkeit ändert sich dagegen nicht.&lt;br /&gt;
&lt;br /&gt;
Nervig ist, dass der Ball zum Schluss immer noch ganz leicht hüpft und gar nicht&lt;br /&gt;
zur Ruhe kommt. Vielleicht können Sie auch dieses Problem beheben.&lt;br /&gt;
&lt;br /&gt;
Oder probieren Sie etwas ganz anderes aus.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Franzih</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46306</id>
		<title>MMProg: Praktikum: WiSe 2018/19: Ball01</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46306"/>
		<updated>2018-11-21T11:26:21Z</updated>

		<summary type="html">&lt;p&gt;Franzih: /* Aufgabe 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2018/19:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Ball01.git Git-Repository]) &lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Im Git-Repository finden Sie zwei WebStorm-Projekte zum Thema GameLoop:&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop01.git WK_GameLoop01]&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop02.git WK_GameLoop02]&lt;br /&gt;
&lt;br /&gt;
Machen Sie sich mit den Projekten vertraut. Die Web-Anwendung &amp;lt;code&amp;gt;src/js/app&amp;lt;/code&amp;gt; des zweiten Projektes dient als Ausgangsbasis für diese Praktikumsaufgabe.    &lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel finden Sie diverse Game-Loop-Varianten. Schrittweise werden potentielle&lt;br /&gt;
Probleme behoben. Dieses Projekt verfolgt das didaktische Ziel, Ihnen die Probleme und potentielle&lt;br /&gt;
Lösungen im Zusammenhang mit JavaScript-Animationen zu verdeutlichen.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel wurde eine Game-Loop-Klasse realisiert, die sie für dieses Praktikum&lt;br /&gt;
nutzen können und sollten. Diese Klasse basiert auf den Ergebnissen des ersten Projektes,&lt;br /&gt;
stellt aber – im Gegensatz zu einigen Web-Anwendungen des ersten Projekt – bislang keine Informationen &lt;br /&gt;
über die aktuelle Frame-Rate bereit. Dies ist aber für diese Praktikumsaufgabe nicht von Interesse.&lt;br /&gt;
&lt;br /&gt;
Importieren Sie das leere Git-Projekt [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/Ball01.git Ball01] in WebStorm.&lt;br /&gt;
Laden Sie annschließend mittels &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt; alle benötigten Node.js-Module in das Projekt.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig.&lt;br /&gt;
Falls Sie da machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
git remote remove origin&lt;br /&gt;
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Ball01.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie 10 Web-Anwendungen vor: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die JavaScript-Datei &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;ball01.js&amp;lt;/code&amp;gt; einbindet. &amp;lt;code&amp;gt;index02.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt; etc. sind analog aufgebaut.&lt;br /&gt;
Wenn Sie irgendeine dieser Anwendungen im Browser öffnen, sehen Sie eine Eule in der linken oberen Bildschirmecke. Diese sollen&lt;br /&gt;
sie auf unterschiedliche Art und Weise animieren. Beachten Sie, dass im Folgenden der Avatar nicht „Eule“, sondern „Ball“ genannt wird.&lt;br /&gt;
Die Eule ist lediglich eine View des ballartigen Objektes.&lt;br /&gt;
&lt;br /&gt;
Lösen Sie jede der folgenden Aufgaben in einer der vorgegebenen Apps.&lt;br /&gt;
Scheuen Sie sich nicht davor, eigene Experimente durchzuführen. Wenn die vorgegebenen Apps nicht ausreichen sollten, legen Sie einfach&lt;br /&gt;
noch ein paar an.&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;src/js/ball/ball&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
Passen Sie zur Lösung dieser Aufgabe die Datei &amp;lt;code&amp;gt;src/js/ball/ball01.js&amp;lt;/code&amp;gt; an.&lt;br /&gt;
Lassen Sie sich durch den Code der Datei &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt; aus dem Beispiel &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; inspirieren.&lt;br /&gt;
(Sie könnten auch &amp;lt;code&amp;gt;ball_interpolate.js&amp;lt;/code&amp;gt; verwenden, aber das verwirrt Sie vermutlich zurzeit deutlich mehr, als dass es &lt;br /&gt;
Ihnen nützt.) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lassen Sie den Ball horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tipp: http://ryanve.com/lab/dimensions/&lt;br /&gt;
&lt;br /&gt;
Berücksichtigen Sie, dass der Ball 150 Pixel breit ist, {{dh}} einen Radius von 75 Pixel hat, &lt;br /&gt;
und das der Ankerpunkt im linken oberen Eck des zugehörigen Bildes liegt. &lt;br /&gt;
Sie müssen im Ball-Objekt auch die Radius des Balls speichern und diesen Wert bei der Kollissionserkennung&lt;br /&gt;
und -behandlung berücksichtigen. Übrigens, wenn Sie &amp;lt;code&amp;gt;v_ball_view&amp;lt;/code&amp;gt; wie in &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt;&lt;br /&gt;
von &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; definieren, können Sie mittels &amp;lt;code&amp;gt;v_ball_view.offsetWidth/2;&amp;lt;/code&amp;gt;&lt;br /&gt;
die aktuelle Breite des Ballobjektes aus der View auslesen.&lt;br /&gt;
&lt;br /&gt;
Ein Tipp noch: Wenn Sie das Ball-Objekt zunächst als leeres Objekt definieren und danach in der&lt;br /&gt;
Reset-Funktion initialisieren, funktionieren Ihre Anwendungen auch noch, wenn Sie später einen&lt;br /&gt;
Start/Stopp- und einen Pause-Button einfügen (vgl. {{zB}} &amp;lt;code&amp;gt;index_start_stop_toggling.html&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt;). &lt;br /&gt;
Sollten Sie keine Buttons zur Steuerung einfügen wollen, können Sie die Objekte auch direkt bei &lt;br /&gt;
der Definition initialisieren.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, die Sourcen mittels &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; zu übersetzen. Und beachten Sie,&lt;br /&gt;
dass im Browser nur die Dateien &amp;lt;code&amp;gt;web/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; funktionieren. Wenn Sie versuchen,&lt;br /&gt;
&amp;lt;code&amp;gt;src/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; erhalten Sie im Browser einen leeren Screen und in der Browser-Konsole drei Fehlermeldungen, &lt;br /&gt;
dass gewissen Dateien nicht geladen werden können.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball nicht waagerecht, sondern in der horizontalen Mitte des Browserfensters senkrecht von Fensterrand zu Fensterrand fliegen.&lt;br /&gt;
&lt;br /&gt;
Um die Aufgabe zu lösen, müssen Sie für der Ball zusätzlich eine y-Position und eine y-Geschwindigkeit definieren. Die Berechnung der aktuellen y-Position funktioniert&lt;br /&gt;
analog zur Berechnung der aktuellen x-Position. &lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, auch die Kollissionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und Sie müssen natürlich die Render-Funktion anpassen, sodass die aktuelle y-Position beim Rendern auch berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball von der Browsermitte aus schräg über den Bildschirm fliegen. In x-Richtung soll er doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 4===&lt;br /&gt;
&lt;br /&gt;
Setzen Sie die x-Start-Position des Balls auf &amp;lt;code&amp;gt;-100&amp;lt;/code&amp;gt; und starten Sie die Web-App. Den Effekt, den Sie sehen, nennt&lt;br /&gt;
man [[Kollisionserkennung und -behandlung|Penetration]]. Die Eule hängt in der Wand fest, da sie nicht den Kollissionsbereich&lt;br /&gt;
(die linke Wand) in einem Schritt verlässt. Daher besteht die Kollission fort und im nächsten Schritt ändert sie wieder ihre Flugrichtung.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie das, indem Sie die Kollisionserkennung und -behandlung verbessern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung analog an. &lt;br /&gt;
&lt;br /&gt;
Sie können und sollten sogar noch einen Schritt weiter gehen und den Ball &lt;br /&gt;
wieder zurück auf die Bühne schieben, wenn er in die Wand eingedrungen ist.&lt;br /&gt;
In die Wand einzudringen ist zwar physikalisch nicht möglich, aber leider in&lt;br /&gt;
einer Simulation der physikalischen Welt nur schwer zu vermeiden, da die&lt;br /&gt;
Position nur alle 16,7 ms berechnet wird. War der Ball zu einem Zeitpunkt&lt;br /&gt;
noch vor der Mauer, kann er beim nächsten Schritt schon drinnen stecken.&lt;br /&gt;
Insbesondere bei sehr schnellen Objekten kann das dann zu den&lt;br /&gt;
beobachteten Penetrationseffekten führen.&lt;br /&gt;
&lt;br /&gt;
Also schieben Sie den Ball besser zurück auf die Bühne.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.x = v_stage.left;&lt;br /&gt;
  v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.x = v_stage.right - 2*v_ball.r;&lt;br /&gt;
  v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung wiederum analog an.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 5===&lt;br /&gt;
&lt;br /&gt;
Ändern Sie die Kollisionserkennung und -behandlung so ab, dass sich der Ball ausgehend von der linken oberen Fensterecke&lt;br /&gt;
im Uhrzeigersinn immer entlang des Fensterrandes bewegt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte: Hier ist es besonders wichtig, dass Sie den Ball wieder auf die Bühne zurückschieben, wenn er mit einer&lt;br /&gt;
Wand kollidiert. Ansonsten verschwindet der Ball schnell im Nirgendwo.&lt;br /&gt;
&lt;br /&gt;
(Anmerkung: Dies war einmal eine Aufgabe im Rahmen des Prüfungspraktikums, wobei die Lösung zur 3. Aufgabe vorgegeben war.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 6===&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie diesmal nicht die Lösung von Aufgabe 5, sondern die von Aufgabe 4. Im Folgenden arbeiten Sie&lt;br /&gt;
wieder mit der normalen Kollissionserkennung und -behandlung. Positionieren Sie den Ball allerdings wieder im linken oberen Eck&lt;br /&gt;
(in Aufgabe 4 hatten Sie sie außerhalb der Bühne platziert).&lt;br /&gt;
&lt;br /&gt;
Die neue Position des Balls berechnen Sie mit Hilfe der Geschwindigkeit (velocity, &amp;lt;code&amp;gt;vx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;vy&amp;lt;/code&amp;gt;). Doch auch die&lt;br /&gt;
Geschwindigkeig kann sich im Laufe der Zeit ändern. Dazu benötigt man die Beschleunigung (acceleration, &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie zu Ihrem Ball  zwei weitere Attribute &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt; (Beschleunigung in x-Richtung) und &lt;br /&gt;
&amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt; (Beschleunigung in y-Richtung) hinzu. Setzen Sie die Initialwerte auf&lt;br /&gt;
&amp;lt;code&amp;gt;400&amp;lt;/code&amp;gt; (Pixel pro Sekunde) bzw. &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt; (Pixel pro Sekunde). Das heißt, Sie möchten,&lt;br /&gt;
dass der Ball in jeder Sekunde um 400 bzw. 200 Pixel pro Sekunde mehr zurücklegt als zuvor.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie jetzt die Web-App starten, beschleunigt der Ball allerdings noch nicht.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Code wird die Position 60 mal pro Sekunde mit Hilfe des folgenden Codes aktualisiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.x += v_ball.vx * p_delta_s;&lt;br /&gt;
v_ball.y += v_ball.vy * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit wird zur Position hinzuaddiert. Allerdings ist die Geschwindigkeit&lt;br /&gt;
in Pixeln pro Sekunde angegeben. Die Modellaktualisierung passiert jedoch alle $0,0167$&lt;br /&gt;
Sekunden. In dieser Zeit bewegt sich der Ball nur um das $0,0167$-fache (= $1,67$%) der Sekundengeschwindigkeit weiter.&lt;br /&gt;
Dieser Faktor ist im Attribut &amp;lt;code&amp;gt;p_delta_s&amp;lt;/code&amp;gt; enthalten. Dieser wird mit &lt;br /&gt;
$1/60 = 0,0167$ initialisiert, sofern der Update-Methode kein anderer Wert übergeben wird.&lt;br /&gt;
&lt;br /&gt;
Auf genau dieselbe Weise wird die aktuelle Geschwindigkeit mit Hilfe der Beschleunigung&lt;br /&gt;
berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx += v_ball.ax * p_delta_s;&lt;br /&gt;
v_ball.vy += v_ball.ay * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie diesen Code in Ihre Model-Update-Funktion ein und starten Sie den Ball erneut.&lt;br /&gt;
Wenn Sie jetzt Ihre Web-App laufen lassen, stellen Sie fest, dass der Ball zunächst beschleunigt,&lt;br /&gt;
nach eine Kollision aber wieder abbremst. Nach der nächsten Kollision beschleunigt er wieder.&lt;br /&gt;
&lt;br /&gt;
Um diesen Effekt zu vermeiden, müssen Sie jedes mal, wenn Sie bei der Kollissionsbehandlung das Vorzeichen&lt;br /&gt;
der Geschwindigkeit ändern, das Vorzeichen der zugehörigen Beschleunigung analog ändern.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise muss der Code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
um&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.ax = -Math.abs(v_ball.ax);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 7===&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie die Kollissionsbehandlung so um, dass im Falle einer Kollission des Balls &lt;br /&gt;
mit dem unteren Fensterrand sowohl die Geschwindigkeit als auch die Beschleunigung&lt;br /&gt;
jeweils in x- und in y-Richtung auf Null gesetzt wird. Das heißt, der &lt;br /&gt;
Ball bleibt bei einer Kollision mit dem unteren Rand stehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 8===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie der Ball im linken oberen Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von 0 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 800. (Diese Zahlen sind gut für meinen Monitor geeignet,&lt;br /&gt;
der eine Auflösung von 1600x900 hat. Wenn Sie einen deutlich kleineren oder größeren&lt;br /&gt;
Monitor haben, müssen Sie die Zahlen evtl. anpassen.)&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 9===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie den Ball im linken unteren Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von -400 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 200.&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
Allerdings ist es nicht ganz sauber, die Erdanziehung mittels &amp;lt;code&amp;gt;v_ball.ax&amp;lt;/code&amp;gt; zu simulieren.&lt;br /&gt;
Diese Beschleunigung ist die Beschleunigung, die vom Ball selbst ausgeht (die also von der Eule&lt;br /&gt;
per Muskelkraft geleistet wird). Wenn der Ball seine Bewegungsrichtung ändert, ändert sich auch die Richtung der Beschleunigung (eine Eule beschleunigt immer in Flugrichtung, vgl. Aufgabe 6).&lt;br /&gt;
Die Richtung der Erbbeschleunigung ändert jedoch bei einer Kollision nicht.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie daher Ihre Anwendung vorlgendermaßen:&lt;br /&gt;
&lt;br /&gt;
* Fügen Sie eine Variable &amp;lt;code&amp;gt;v_g = 981&amp;lt;/code&amp;gt; in die &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;-Anweisung ein. (981 wurde in Anlehnung an die Gravitationskonstante der Erde gewählt.)&lt;br /&gt;
* Reduzieren Sie die Eigenbeschleunigung der Eule in $y$-Richtung auf &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. (Jetzt sollte sich die Eule wieder geradlinig bewegen.)&lt;br /&gt;
* Ersetzen Sie un der Update-Funktion &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += v_ball.ay * p_delta_s;&amp;lt;/source&amp;gt; durch &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += (v_ball.ay+v_g) * p_delta_s;&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Das heißt, berücksichtigen Sie bei der Berechnung der $y$-Geschwindigkeit des Balles zusätzlich die Erdanziehungskraft. Nun sollte die Eule wieder einen sauberen Parabelflug vollführen.&lt;br /&gt;
 &lt;br /&gt;
Alles, was jetzt noch fehlt, ist ein Gummiband, mit dem Sie die Eule beschleunigen können. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 10===&lt;br /&gt;
&lt;br /&gt;
Machen Sie eigene Experimente. Bringen Sie {{zB}} den Ball dazu, wie ein Flummi&lt;br /&gt;
zu springen, indem sie seine Geschwindigkeit in x- und y-Richtung bei einem Bodenkontakt&lt;br /&gt;
um einen gewissen Prozentsatz reduzieren, aber nicht gleich auf null setzen.&lt;br /&gt;
(Die Beschleunigung, die die Erdanziehung simuliert, bleibt die ganze Zeit über gleich).&lt;br /&gt;
Achtung: Bei einem Bodenkontakt, dreht sich das Vorzeichen der y-Geschwindigkeit um, &lt;br /&gt;
das der x-Geschwindigkeit ändert sich dagegen nicht.&lt;br /&gt;
&lt;br /&gt;
Nervig ist, dass der Ball zum Schluss immer noch ganz leicht hüpft und gar nicht&lt;br /&gt;
zur Ruhe kommt. Vielleicht können Sie auch dieses Problem beheben.&lt;br /&gt;
&lt;br /&gt;
Oder probieren Sie etwas ganz anderes aus.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Franzih</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46305</id>
		<title>MMProg: Praktikum: WiSe 2018/19: Ball01</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2018/19:_Ball01&amp;diff=46305"/>
		<updated>2018-11-21T11:25:57Z</updated>

		<summary type="html">&lt;p&gt;Franzih: /* Aufgaben */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2018/19:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Ball01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Ball01.git Git-Repository]) &lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Im Git-Repository finden Sie zwei WebStorm-Projekte zum Thema GameLoop:&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop01.git WK_GameLoop01]&lt;br /&gt;
* [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_GameLoop02.git WK_GameLoop02]&lt;br /&gt;
&lt;br /&gt;
Machen Sie sich mit den Projekten vertraut. Die Web-Anwendung &amp;lt;code&amp;gt;src/js/app&amp;lt;/code&amp;gt; des zweiten Projektes dient als Ausgangsbasis für diese Praktikumsaufgabe.    &lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel finden Sie diverse Game-Loop-Varianten. Schrittweise werden potentielle&lt;br /&gt;
Probleme behoben. Dieses Projekt verfolgt das didaktische Ziel, Ihnen die Probleme und potentielle&lt;br /&gt;
Lösungen im Zusammenhang mit JavaScript-Animationen zu verdeutlichen.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel wurde eine Game-Loop-Klasse realisiert, die sie für dieses Praktikum&lt;br /&gt;
nutzen können und sollten. Diese Klasse basiert auf den Ergebnissen des ersten Projektes,&lt;br /&gt;
stellt aber – im Gegensatz zu einigen Web-Anwendungen des ersten Projekt – bislang keine Informationen &lt;br /&gt;
über die aktuelle Frame-Rate bereit. Dies ist aber für diese Praktikumsaufgabe nicht von Interesse.&lt;br /&gt;
&lt;br /&gt;
Importieren Sie das leere Git-Projekt [https://gitlab.multimedia.hs-augsburg.de:8888/kowa/Ball01.git Ball01] in WebStorm.&lt;br /&gt;
Laden Sie annschließend mittels &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt; alle benötigten Node.js-Module in das Projekt.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig.&lt;br /&gt;
Falls Sie da machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
git remote remove origin&lt;br /&gt;
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Ball01.git&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie 10 Web-Anwendungen vor: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die JavaScript-Datei &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;ball01.js&amp;lt;/code&amp;gt; einbindet. &amp;lt;code&amp;gt;index02.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt; etc. sind analog aufgebaut.&lt;br /&gt;
Wenn Sie irgendeine dieser Anwendungen im Browser öffnen, sehen Sie eine Eule in der linken oberen Bildschirmecke. Diese sollen&lt;br /&gt;
sie auf unterschiedliche Art und Weise animieren. Beachten Sie, dass im Folgenden der Avatar nicht „Eule“, sondern „Ball“ genannt wird.&lt;br /&gt;
Die Eule ist lediglich eine View des ballartigen Objektes.&lt;br /&gt;
&lt;br /&gt;
Lösen Sie jede der folgenden Aufgaben in einer der vorgegebenen Apps.&lt;br /&gt;
Scheuen Sie sich nicht davor, eigene Experimente durchzuführen. Wenn die vorgegebenen Apps nicht ausreichen sollten, legen Sie einfach&lt;br /&gt;
noch ein paar an.&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;src/js/ball/ball&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
Passen Sie zur Lösung dieser Aufgabe die Datei &amp;lt;code&amp;gt;src/js/ball/ball01.js&amp;lt;/code&amp;gt; an.&lt;br /&gt;
Lassen Sie sich durch den Code der Datei &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt; aus dem Beispiel &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; inspirieren.&lt;br /&gt;
(Sie könnten auch &amp;lt;code&amp;gt;ball_interpolate.js&amp;lt;/code&amp;gt; verwenden, aber das verwirrt Sie vermutlich zurzeit deutlich mehr, als dass es &lt;br /&gt;
Ihnen nützt.) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Lassen Sie der Ball horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tipp: http://ryanve.com/lab/dimensions/&lt;br /&gt;
&lt;br /&gt;
Berücksichtigen Sie, dass der Ball 150 Pixel breit ist, {{dh}} einen Radius von 75 Pixel hat, &lt;br /&gt;
und das der Ankerpunkt im linken oberen Eck des zugehörigen Bildes liegt. &lt;br /&gt;
Sie müssen im Ball-Objekt auch die Radius des Balls speichern und diesen Wert bei der Kollissionserkennung&lt;br /&gt;
und -behandlung berücksichtigen. Übrigens, wenn Sie &amp;lt;code&amp;gt;v_ball_view&amp;lt;/code&amp;gt; wie in &amp;lt;code&amp;gt;ball.js&amp;lt;/code&amp;gt;&lt;br /&gt;
von &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; definieren, können Sie mittels &amp;lt;code&amp;gt;v_ball_view.offsetWidth/2;&amp;lt;/code&amp;gt;&lt;br /&gt;
die aktuelle Breite des Ballobjektes aus der View auslesen.&lt;br /&gt;
&lt;br /&gt;
Ein Tipp noch: Wenn Sie das Ball-Objekt zunächst als leeres Objekt definieren und danach in der&lt;br /&gt;
Reset-Funktion initialisieren, funktionieren Ihre Anwendungen auch noch, wenn Sie später einen&lt;br /&gt;
Start/Stopp- und einen Pause-Button einfügen (vgl. {{zB}} &amp;lt;code&amp;gt;index_start_stop_toggling.html&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt;). &lt;br /&gt;
Sollten Sie keine Buttons zur Steuerung einfügen wollen, können Sie die Objekte auch direkt bei &lt;br /&gt;
der Definition initialisieren.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, die Sourcen mittels &amp;lt;code&amp;gt;npm run watch&amp;lt;/code&amp;gt; zu übersetzen. Und beachten Sie,&lt;br /&gt;
dass im Browser nur die Dateien &amp;lt;code&amp;gt;web/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; funktionieren. Wenn Sie versuchen,&lt;br /&gt;
&amp;lt;code&amp;gt;src/index&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.html&amp;lt;/code&amp;gt; erhalten Sie im Browser einen leeren Screen und in der Browser-Konsole drei Fehlermeldungen, &lt;br /&gt;
dass gewissen Dateien nicht geladen werden können.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball nicht waagerecht, sondern in der horizontalen Mitte des Browserfensters senkrecht von Fensterrand zu Fensterrand fliegen.&lt;br /&gt;
&lt;br /&gt;
Um die Aufgabe zu lösen, müssen Sie für der Ball zusätzlich eine y-Position und eine y-Geschwindigkeit definieren. Die Berechnung der aktuellen y-Position funktioniert&lt;br /&gt;
analog zur Berechnung der aktuellen x-Position. &lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht, auch die Kollissionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und Sie müssen natürlich die Render-Funktion anpassen, sodass die aktuelle y-Position beim Rendern auch berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie der Ball von der Browsermitte aus schräg über den Bildschirm fliegen. In x-Richtung soll er doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 4===&lt;br /&gt;
&lt;br /&gt;
Setzen Sie die x-Start-Position des Balls auf &amp;lt;code&amp;gt;-100&amp;lt;/code&amp;gt; und starten Sie die Web-App. Den Effekt, den Sie sehen, nennt&lt;br /&gt;
man [[Kollisionserkennung und -behandlung|Penetration]]. Die Eule hängt in der Wand fest, da sie nicht den Kollissionsbereich&lt;br /&gt;
(die linke Wand) in einem Schritt verlässt. Daher besteht die Kollission fort und im nächsten Schritt ändert sie wieder ihre Flugrichtung.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie das, indem Sie die Kollisionserkennung und -behandlung verbessern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung analog an. &lt;br /&gt;
&lt;br /&gt;
Sie können und sollten sogar noch einen Schritt weiter gehen und den Ball &lt;br /&gt;
wieder zurück auf die Bühne schieben, wenn er in die Wand eingedrungen ist.&lt;br /&gt;
In die Wand einzudringen ist zwar physikalisch nicht möglich, aber leider in&lt;br /&gt;
einer Simulation der physikalischen Welt nur schwer zu vermeiden, da die&lt;br /&gt;
Position nur alle 16,7 ms berechnet wird. War der Ball zu einem Zeitpunkt&lt;br /&gt;
noch vor der Mauer, kann er beim nächsten Schritt schon drinnen stecken.&lt;br /&gt;
Insbesondere bei sehr schnellen Objekten kann das dann zu den&lt;br /&gt;
beobachteten Penetrationseffekten führen.&lt;br /&gt;
&lt;br /&gt;
Also schieben Sie den Ball besser zurück auf die Bühne.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_ball.x &amp;lt;= v_stage.left)&lt;br /&gt;
{ v_ball.x = v_stage.left;&lt;br /&gt;
  v_ball.vx = Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_ball.x &amp;gt;= v_stage.right - 2*v_ball.r)&lt;br /&gt;
{ v_ball.x = v_stage.right - 2*v_ball.r;&lt;br /&gt;
  v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung wiederum analog an.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 5===&lt;br /&gt;
&lt;br /&gt;
Ändern Sie die Kollisionserkennung und -behandlung so ab, dass sich der Ball ausgehend von der linken oberen Fensterecke&lt;br /&gt;
im Uhrzeigersinn immer entlang des Fensterrandes bewegt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte: Hier ist es besonders wichtig, dass Sie den Ball wieder auf die Bühne zurückschieben, wenn er mit einer&lt;br /&gt;
Wand kollidiert. Ansonsten verschwindet der Ball schnell im Nirgendwo.&lt;br /&gt;
&lt;br /&gt;
(Anmerkung: Dies war einmal eine Aufgabe im Rahmen des Prüfungspraktikums, wobei die Lösung zur 3. Aufgabe vorgegeben war.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 6===&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie diesmal nicht die Lösung von Aufgabe 5, sondern die von Aufgabe 4. Im Folgenden arbeiten Sie&lt;br /&gt;
wieder mit der normalen Kollissionserkennung und -behandlung. Positionieren Sie den Ball allerdings wieder im linken oberen Eck&lt;br /&gt;
(in Aufgabe 4 hatten Sie sie außerhalb der Bühne platziert).&lt;br /&gt;
&lt;br /&gt;
Die neue Position des Balls berechnen Sie mit Hilfe der Geschwindigkeit (velocity, &amp;lt;code&amp;gt;vx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;vy&amp;lt;/code&amp;gt;). Doch auch die&lt;br /&gt;
Geschwindigkeig kann sich im Laufe der Zeit ändern. Dazu benötigt man die Beschleunigung (acceleration, &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie zu Ihrem Ball  zwei weitere Attribute &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt; (Beschleunigung in x-Richtung) und &lt;br /&gt;
&amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt; (Beschleunigung in y-Richtung) hinzu. Setzen Sie die Initialwerte auf&lt;br /&gt;
&amp;lt;code&amp;gt;400&amp;lt;/code&amp;gt; (Pixel pro Sekunde) bzw. &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt; (Pixel pro Sekunde). Das heißt, Sie möchten,&lt;br /&gt;
dass der Ball in jeder Sekunde um 400 bzw. 200 Pixel pro Sekunde mehr zurücklegt als zuvor.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie jetzt die Web-App starten, beschleunigt der Ball allerdings noch nicht.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Code wird die Position 60 mal pro Sekunde mit Hilfe des folgenden Codes aktualisiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.x += v_ball.vx * p_delta_s;&lt;br /&gt;
v_ball.y += v_ball.vy * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit wird zur Position hinzuaddiert. Allerdings ist die Geschwindigkeit&lt;br /&gt;
in Pixeln pro Sekunde angegeben. Die Modellaktualisierung passiert jedoch alle $0,0167$&lt;br /&gt;
Sekunden. In dieser Zeit bewegt sich der Ball nur um das $0,0167$-fache (= $1,67$%) der Sekundengeschwindigkeit weiter.&lt;br /&gt;
Dieser Faktor ist im Attribut &amp;lt;code&amp;gt;p_delta_s&amp;lt;/code&amp;gt; enthalten. Dieser wird mit &lt;br /&gt;
$1/60 = 0,0167$ initialisiert, sofern der Update-Methode kein anderer Wert übergeben wird.&lt;br /&gt;
&lt;br /&gt;
Auf genau dieselbe Weise wird die aktuelle Geschwindigkeit mit Hilfe der Beschleunigung&lt;br /&gt;
berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx += v_ball.ax * p_delta_s;&lt;br /&gt;
v_ball.vy += v_ball.ay * p_delta_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie diesen Code in Ihre Model-Update-Funktion ein und starten Sie den Ball erneut.&lt;br /&gt;
Wenn Sie jetzt Ihre Web-App laufen lassen, stellen Sie fest, dass der Ball zunächst beschleunigt,&lt;br /&gt;
nach eine Kollision aber wieder abbremst. Nach der nächsten Kollision beschleunigt er wieder.&lt;br /&gt;
&lt;br /&gt;
Um diesen Effekt zu vermeiden, müssen Sie jedes mal, wenn Sie bei der Kollissionsbehandlung das Vorzeichen&lt;br /&gt;
der Geschwindigkeit ändern, das Vorzeichen der zugehörigen Beschleunigung analog ändern.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise muss der Code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.vx = -Math.abs(v_ball.vx);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
um&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_ball.ax = -Math.abs(v_ball.ax);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 7===&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie die Kollissionsbehandlung so um, dass im Falle einer Kollission des Balls &lt;br /&gt;
mit dem unteren Fensterrand sowohl die Geschwindigkeit als auch die Beschleunigung&lt;br /&gt;
jeweils in x- und in y-Richtung auf Null gesetzt wird. Das heißt, der &lt;br /&gt;
Ball bleibt bei einer Kollision mit dem unteren Rand stehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 8===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie der Ball im linken oberen Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von 0 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 800. (Diese Zahlen sind gut für meinen Monitor geeignet,&lt;br /&gt;
der eine Auflösung von 1600x900 hat. Wenn Sie einen deutlich kleineren oder größeren&lt;br /&gt;
Monitor haben, müssen Sie die Zahlen evtl. anpassen.)&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 9===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie den Ball im linken unteren Eck, geben Sie ihm eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von -400 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 200.&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt der Ball, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
Allerdings ist es nicht ganz sauber, die Erdanziehung mittels &amp;lt;code&amp;gt;v_ball.ax&amp;lt;/code&amp;gt; zu simulieren.&lt;br /&gt;
Diese Beschleunigung ist die Beschleunigung, die vom Ball selbst ausgeht (die also von der Eule&lt;br /&gt;
per Muskelkraft geleistet wird). Wenn der Ball seine Bewegungsrichtung ändert, ändert sich auch die Richtung der Beschleunigung (eine Eule beschleunigt immer in Flugrichtung, vgl. Aufgabe 6).&lt;br /&gt;
Die Richtung der Erbbeschleunigung ändert jedoch bei einer Kollision nicht.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie daher Ihre Anwendung vorlgendermaßen:&lt;br /&gt;
&lt;br /&gt;
* Fügen Sie eine Variable &amp;lt;code&amp;gt;v_g = 981&amp;lt;/code&amp;gt; in die &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt;-Anweisung ein. (981 wurde in Anlehnung an die Gravitationskonstante der Erde gewählt.)&lt;br /&gt;
* Reduzieren Sie die Eigenbeschleunigung der Eule in $y$-Richtung auf &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. (Jetzt sollte sich die Eule wieder geradlinig bewegen.)&lt;br /&gt;
* Ersetzen Sie un der Update-Funktion &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += v_ball.ay * p_delta_s;&amp;lt;/source&amp;gt; durch &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;v_ball.vy += (v_ball.ay+v_g) * p_delta_s;&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Das heißt, berücksichtigen Sie bei der Berechnung der $y$-Geschwindigkeit des Balles zusätzlich die Erdanziehungskraft. Nun sollte die Eule wieder einen sauberen Parabelflug vollführen.&lt;br /&gt;
 &lt;br /&gt;
Alles, was jetzt noch fehlt, ist ein Gummiband, mit dem Sie die Eule beschleunigen können. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 10===&lt;br /&gt;
&lt;br /&gt;
Machen Sie eigene Experimente. Bringen Sie {{zB}} den Ball dazu, wie ein Flummi&lt;br /&gt;
zu springen, indem sie seine Geschwindigkeit in x- und y-Richtung bei einem Bodenkontakt&lt;br /&gt;
um einen gewissen Prozentsatz reduzieren, aber nicht gleich auf null setzen.&lt;br /&gt;
(Die Beschleunigung, die die Erdanziehung simuliert, bleibt die ganze Zeit über gleich).&lt;br /&gt;
Achtung: Bei einem Bodenkontakt, dreht sich das Vorzeichen der y-Geschwindigkeit um, &lt;br /&gt;
das der x-Geschwindigkeit ändert sich dagegen nicht.&lt;br /&gt;
&lt;br /&gt;
Nervig ist, dass der Ball zum Schluss immer noch ganz leicht hüpft und gar nicht&lt;br /&gt;
zur Ruhe kommt. Vielleicht können Sie auch dieses Problem beheben.&lt;br /&gt;
&lt;br /&gt;
Oder probieren Sie etwas ganz anderes aus.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Franzih</name></author>
	</entry>
</feed>