MMProg: Praktikum: WiSe 2018/19: Pong01: Unterschied zwischen den Versionen
Kowa (Diskussion | Beiträge) |
Kowa (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
{MMProg:Praktikum:WiSe 2018/19:Menü}} | {{MMProg:Praktikum:WiSe 2018/19:Menü}} | ||
'''Musterlösung''': [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Pong01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Pong01.git Git-Repository]) | '''Musterlösung''': [https://glossar.hs-augsburg.de/beispiel/tutorium/2018/ball/WK_Pong01/web/ Web-Auftritt] ([https://gitlab.multimedia.hs-augsburg.de:8888/kowa/WK_Pong01.git Git-Repository]) | ||
Version vom 6. Dezember 2018, 18:25 Uhr
Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:
| Korrektheit: 3 (zu größeren Teilen überprüft) |
Umfang: 4 (unwichtige Fakten fehlen) |
Quellenangaben: 3 (wichtige Quellen vorhanden) |
Quellenarten: 5 (ausgezeichnet) |
Konformität: 3 (gut) |
Inhalt | EcmaScript01 | EcmaScript02 | EcmaScript03 | Ball 01| Ball 02 | Ball 03 | Pong 01
Musterlösung: Web-Auftritt (Git-Repository)
Ziel
Ziel dieser Praktikumsaufgabe ist es, das Spiel Pong zu implementieren.
Vorbereitung
Importieren Sie das leere Git-Projekt Pong01 in WebStorm.
Laden Sie anschließend mittels npm i alle benötigten Node.js-Module in das Projekt.
Sie können Ihr Projekt zur Übung auch in Ihrem Git-Repository speichern. Das ist aber nicht so wichtig. Falls Sie das machen möchten, müssen Sie es zuvor von meinem (schreibgeschützten) Repository lösen:
git remote remove origin
git remote add origin https://gitlab.multimedia.hs-augsburg.de:8888/BENUTZER/Pong01.git
In Ihrem Projekt finden Sie eine Web-Anwendung: src/index00.html
Diese entspricht im Wesentlichen der Musterlösung der
Aufgabe 3 des Tutoriums Ball03. Allerdings wurde für die Spielbühne eine feste Größe gewählt,
das Bild des Balls sowie das CSS wurden verändert und ein Splashscreen wurde eingeführt. Dieser wird mittels CSS-Transitionen und
JavaScript await-Befehlen in der Initfunktion der Datei app00/app.js implementiert. Die await-Befehle
sowie die zugehörigen Splaschscreen-Befehle ändern sich im Laufe des Tutoriums nicht. Sie sollten sie aber trotzdem studieren,
wenn Sie daran interessiert sind, wie sie funktionieren.
Beachten Sie, dass die Klasse ModelCircle vier Methoden left, right, top und bottom enthält. Mit diesen Methoden werden
die Ränder des Kreises ermittelt. Damit kann man Kollisionsberechnungen etwas einfacher formulieren.
Bei den Methoden left, right,
top und bottom handelt es sich nicht um normale Methoden, sondern um so
genannte Getter-Methoden (MDN web docs: Getter). Getter-Methoden sind Methoden ohne Parameter, vor die das Schlusselwort
get geschrieben wird. Sie werden zur Berechnung von Attributwerten verwendet werden.
get left() { return this.x - this.r; }
// Der linke Rand eines Kreise ist gleich
// seiner Position x abzüglich seines Radius r.
Eine normale Methode würde man mittels console.log(myCircle.left()); aufrufen. Beim Zugriff auf eine Getter-Methode verwendet man dagegen die klammerfreie Attributzugriff-Syntax:
console.log(myCircle.left);
Neben den Getter-Methoden gibt es auch noch Setter-Methoden, die dazu dienen, berechnet Attribute zu verändern (MDN web docs: Setter). Diese haben genau einen Parameter, der den Wert enthält, der gespeichert werden soll:
set left(p_x) { this.x = p_x + this.r; }
// Anstelle des linken Randes wird die Position des Kreises geändert,
// und zwar so, dass der linke Rand an der gewünschten Position zu
// liegen kommt.
Zum Aufruf der Setter-Methoden kommt ebenfalls die Attributzugriff-Syntax zum Einsatz:
myCircle.left = 100;
console.log(myCircle.left) → 100
Use Cases

PongDer Aufgabe liegt das Modell Pong/Modellierung zugrunde. Allerdings wurden bei der Umsetzung einige Änderungen vorgenommen. Am Use-Case-Diagramm fällt auf, dass der Use Case „Spiel abbrechen“ fehlt. Es wurde darauf verzichtet, da nicht – wie ursprünglich geplant – ein Start-/Stopp-Knopf (als HTML-Button) außerhalb der Bühne platziert wird, sondern nun ein Start-Knopf innerhalb der Bühne. Dieser wird ausgeblendet, solange das Spiel läuft.
Ich habe das implementierte Modell ganz bewusst gegenüber der ursprünglichen Planung abgeändert, um den dynamischen Prozess zu verdeutlichen, den ein Modell durchläuft. Es ändert sich ständig: Elemente werden ergänzt, verfeinert, ersetzt oder auch ersazlos gestrichen. Ich kenne niemanden, der zu Beginn eines Projektes ein perfektes Modell aufstellt, dass nicht ein paar Dutzend mal geändert werden muss.
Klassendiagramm (Moduldiagramm)
[Klassendiagramm von Pong01 (zweite Version) |
[Klassendiagramm von Pong01 (erste Version) |
Dieses Klassendiagramm ist ebenfalls gegenüber dem Klassendiagramm von Pong/Modellierung weiterentwickelt worden.
Anstelle eines HTML-Elements, gibt es jetzt einen kreisförmigen Start-Button. Die Klassen ModelCircle und
ViewCircle werden auch für den Ball verwendet (Wiederverwendung). Die Klasse ModelPaddle
wurde als Unterklasse einer (wiederverwendbaren) Klasse ModelRectangle definiert. Für die Punkteanzeige
wurde eine eigene Klasse ModelScore definiert, dan in der Klasse ModelText keine Zahlen,
sondern nur Text geespiechert werden können. Das ist für die Rechnung mit Punkten, die jeweils mittels ++
erhöht können werden müssen, etwas unpraktisch. Zu guter Letzt wurde noch ein Textfeld eingeführt, das dazu genutzt
werden kann, bei Spielende die Spieler über den Sieger zu informieren.
Aufgabe
Implementieren Sie Pong gemäß obigem Klassen Diagramm.
Aufgabe 1
(Musterlösung: Gitlab: WK_Pong01, app01, index01.html)
Sie sollten zunächst eine Kopie Ihrer Web-App erstellen:
- Erstellen Sie eine Kopie des Ordners
src/js/app00unter dem Namensrc/js/app01. - Erstellen Sie eine Kopie der Datei
src/index00.htmlunter dem Namensrc/index01.htmlund ändern Sie den Titel in dieser Datei entsprechend. - Starten Sie gegebenenfalls
npm run watchneu (Abbruch des Watschers:Strg-cbzw.Crtl-c).
In der Musterlösung app00 aus Ball 03 gibt es schon einige Module, die Sie wiederverwenden können:
model/ModelStagemodel/ModelCirclemodel/collisionCircleStagemodel/updateview/ViewCircleGraphicsview/ViewCircleSpriteview/renderapp
Implementieren Sie als nächstes folgende Module, um die beiden Schläger darstellen zu könnnen:
model/ModelRectangle(ModelPaddlefolgt später)view/ViewRectangleGraphics
ModelRectangle
Die Klasse ModelRectangle hat folgende Attribute:
width(anstelle vonrinModelCircle)height(anstelle vonrinModelCircle)x(wieModelCircle)y(wieModelCircle)vx(wieModelCircle)vy(wieModelCircle)ax(vgl. Praktikum Ball01, Aufgabe 6)ay(vgl. Praktikum Ball01, Aufgabe 6)left(analog zuModelCircleohnethis.r)right(analog zuModelCircle, aber mitthis.width)top(analog zuModelCircleohnethis.r)bottom(analog zuModelCircle, aber mitthis.width)
Die zugehörigen Setter-Methoden werden später noch benötigt. Sie können sie theoretisch auch schon jetzt implementieren.
Darüber hinaus enthält diese Klasse zwei Methoden
reset(analog zuModelCircle)update(analog zuModelCircle, allerdings muss auch die Geschwindigkeit abhängig von der Beschleunigung angepasst werden; vgl. Praktikum Ball01, Aufgabe 6)
Beachten Sie bei der Berechnung der der Begrenzungen left, right,
top und bottom eines Rechtecks, dass der Ankerpunkt üblicherweise
in der linken oberen Ecke des Rechtecks liegt. Beim Kreis liegt er dagegen im Mittelpunkt.
ViewRectangleGraphics
Die Klasse ViewRectangleGraphics wird analog zu
ViewCircleGraphics implementiert. Der wesentliche Unterschied ist, dass
das grafische Objekt nicht mit drawCircle, sondern mittels drawRect
gezeichnet wird (PIXI.Graphics).
config.json und app.js
Jetzt können Sie zwei Schläger in Ihre Anwendung einbinden. Erweitern Sie zunächst
die Kondifurationsdatei config/config.json. Fügen Sie in dieser Datei in das
Model-Objekt die Model-Konfigurationen der beiden Paddle ein:
"paddles":
[ { "x": 5,
"y": 170,
"vy": 150,
"ay": 1000,
"width": 10,
"height": 60
},
{ "x": 585,
"y": 170,
"vy": 150,
"ay": 1000,
"width": 10,
"height": 60
}
]
Und in das View-Objekt fügen Sie eine View-Konfiguration ein, die für beide Paddle verwendet werden kann.
"paddle":
{ "border": 0,
"color": { "color": "#999999" }
}
Wenn Sie keinen Syntaxfehler gemacht haben, lässt sich die app01 immer noch fehlerfrei übersetzen.
Nun ist es an der Zeit die Datei app.js anzupassen:
- Importieren Sie die beiden neu erstellten Klassen
ModelRectangleundViewRectangleGraphicsanalog zuModelCircleundViewCircleGraphics. Auch hier gilt: Wenn Sie in beiden Dateien keine Syntaxfehler gemacht haben, lässt sich die App immer noch fehlerfrei übersetzen. - Fügen Sie nach der Konstanten
c_config_view_ballzwei Konstanten ein, mit denen Sie auf die beiden Konfigurationsobjekte zugreifen können, die Sie zuvor in die Dateiconfig.jsoneingefügt haben:
c_config_model_paddles = c_config_model.paddles,
c_config_view_paddle = c_config_view.paddle,
- Nun müssen Sie im Anschluss an die Erzeugung von
c_model_balldie Models der beiden Schläger erzeugen (wären es mehr als zwei Objekte, würde man das Array natürlich mit Hilfe einer Schleife füllen):
c_model_paddles =
[ new ModelRectangle(c_config_model_paddles[0]),
new ModelRectangle(c_config_model_paddles[1])
]
- Als Nächstes müssen Sie das soeben erzeugte Array ins Konfigurationsobjekt vom Funktionsaufruf der Funktion
initUpdatereinfügen, da der Updater natürlich auch die Positionen der Schläger regelmäßig neu berechnen muss:
initUpdater({stage: c_model_stage,
ball: c_model_ball,
paddles: c_model_paddles
});
- Jetzt fehlen noch die Views. Diese müssen im Rumpf der Initfunktion im Anschluss an die Ball-View erzeugt werden (auch hier gilt: das Array würde mit Hilfe eine Schleife befüllt werden, wenn es sich um mehr als zwei Schläger handeln würde):
c_views_paddle =
[ new ViewRectangleGraphics
(c_pixi_app, c_model_paddles[0],c_config_view_paddle),
new ViewRectangleGraphics
(c_pixi_app, c_model_paddles[1], c_config_view_paddle)
]
- Diese Views müssen vom Renderer regelmäßig neu gezeichnet werden (hier kommt wieder ES-6-Destructiring-Syntax zum Einsatz, um den Inhalt des Arraya
c_views_paddlein ein anderes Array einzugügen; in ES 5initRenderer([c_view_ball].concat(c_views_paddle));geschrieben)
initRenderer([c_view_ball, ...c_views_paddle]);
- Jetzt sollte die Anwendung wieder laufen und die beiden Schläger sollten zu sehen sein:
https://glossar.hs-augsburg.de/beispiel/tutorium/2018/pong/WK_Pong01/web/index01.html
Aufgabe 2
(Musterlösung: Gitlab: WK_Pong01, app02, index02.html)
Fortsetzung folgt!
Aufgabe 3
(Musterlösung: Gitlab: WK_Pong01, app03, index03.html)
Aufgabe 4
(Musterlösung: Gitlab: WK_Pong01, app04, index04.html)
Aufgabe 5
(Musterlösung: Gitlab: WK_Pong01, app05, index05.html)
Aufgabe 6
(Musterlösung: Gitlab: WK_Pong01, app06, index06.html)
Quellen
- Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)


