25
Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris GL Dozent: Prof. Dr. math. Bunse Dipl.-Ing. (FH) Christian Benjamin Ries [email protected] 1

Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Grafische DatenverarbeitungSommersemester 2008

Wii Tetris GL

Dozent: Prof. Dr. math. Bunse

Dipl.-Ing. (FH) Christian Benjamin [email protected]

1

Page 2: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Eidesstattliche Erklärung

Ich erkläre hiermit an Eides Statt, dass ich die vorliegende Arbeit selbständig und ohneBenutzung anderer als der angegebenen Hilfsmittel angefertigt habe; die aus fremden Quel-len (einschließlich elektronischer Quellen) direkt oder indirekt übernommenen Gedankensind ausnahmslos als solche kenntlich gemacht.

Die Arbeit wurde bisher weder im In- noch im Ausland in gleicher oder ähnlicher Formeiner anderen Prüfungsbehörde vorgelegt.

Ich versichere an Eides Statt, dass ich nach bestem Wissen die reine Wahrheit gesagt undnichts verschwiegen habe.

Vor Aufnahme der obigen Versicherung an Eides Statt wurde ich über die Bedeutung dereidesstattlichen Versicherung und die strafrechtlichen Folgen einer unrichtigen oder unvoll-ständigen eidesstattlichen Versicherung belehrt.

______________________(Ort, Datum)

______________________(Unterschrift)

2

Page 3: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Inhaltsverzeichnis

1 Einleitung 4

2 Idee 4

3 Tetris, das Spiel 5

3.1 Spielregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3.2 Punktevergabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.3 Die Spielwiese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.4 Spielstart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3.5 Steuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

4 Architektur 8

5 Programmablauf 10

6 Konzept 11

7 Implementierungen 14

7.1 Bewegungsfunktionen / Kollisionserkennung . . . . . . . . . . . . . . . . 15

7.1.1 check_xyz(...) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

7.1.2 move_x(...) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

7.1.3 calculate_objects(...) . . . . . . . . . . . . . . . . . . . . . . . . . 20

7.2 Logische Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

7.2.1 remove_line(...) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

7.3 Hauptschleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

7.3.1 main -> Loop-Game . . . . . . . . . . . . . . . . . . . . . . . . . 23

8 Verbesserungswürdig 24

9 Probleme bei der Entwicklung 25

3

Page 4: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Abbildungsverzeichnis

1 Steuerungselemente der Nintendo Wii (Nunchuck und Wiimote v.L.) . . . . 5

2 Kubus, Größe 1x1x1, 1 Stein . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 Linie, Größe 4x1x1, 4 Steine . . . . . . . . . . . . . . . . . . . . . . . . . 6

4 Pyramide, Größe 3x2x1, 4 Steine . . . . . . . . . . . . . . . . . . . . . . . 6

5 Rechtwinkel, Größe 3x2x1, 4 Steine . . . . . . . . . . . . . . . . . . . . . 6

6 Schlange, Größe 3x2x1, 4 Steine . . . . . . . . . . . . . . . . . . . . . . . 6

7 Spielansicht von Tetris GL . . . . . . . . . . . . . . . . . . . . . . . . . . 7

8 Koordinatensystem und Tasten des Wiimote . . . . . . . . . . . . . . . . . 9

9 Tasten des Nunchuck. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

10 Vereinfachter Programmablaufplan . . . . . . . . . . . . . . . . . . . . . . 11

11 Klassenabhängigkeit von Tetris GL. (UML Konvention) . . . . . . . . . . . 12

12 Aufteilung des Spielraumes in eine Gitterbox, examplarische Darstellung . 14

13 Kollisionsgrafik für den aktuellen Baustein . . . . . . . . . . . . . . . . . . 19

Tabellenverzeichnis

1 Verwendbare Parameter beim Start des Spiels . . . . . . . . . . . . . . . . 7

2 Zuordnung der Steuerungsmöglichkeiten des Wiimote und des Nunchucks . 8

3 Zuordnung der Steuerungsmöglichkeiten des Wiimote und des Nunchucks . 9

1 Einleitung

An der Fachhochschule Bielefeld wird von Prof. Dr. math. Wolfgang Bunse die Lehr-veranstaltung „Grafische Datenverarbeitung” angeboten. In dieser Vorlesung werden Grund-lagen und das Verständniss für Methoden der interaktiven grafikerzeugenden und grafik-verändernden Datenverarbeitung vermittelt.

Für das Bestehen dieser Vorlesung wird ein durchgeführtes Projekt abverlangt. In dieserArbeit geht es um dieses Projekt.

2 Idee

In den letzten Jahrzehnten existierte eine Fülle von verschiedenen Spielekonsolen. An-gefangen im Jahre 1972 als Ralph Baer die erste Spielekonsole entwickelte, gefolgt vonzahlreichen Varianten und Arten. Doch erst ab 1985 setzten sich die Konsolen durch und

4

Page 5: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

eroberten den Multimediamarkt. Die bekanntesten Konsolen dieser Zeit sind wohl das NES(Nintendo Entertainment System), das Sega Master System und der Atari 7800.

Die heutigen Spielekonsolen haben nur noch eines mit den damaligen Geräten gemeinsam:den Spieler, der diese bedient. Namen wie Xbox 360 (Microsoft), Playstation 3 (Sony)und Wii (Nintendo) sind heutzutage in aller Munde. Angetrieben durch geballte Rechen-power und Speicherkapazität, berechnen diese Megamaschinen die realistischsten Szenenund Effekte und zaubern wahrliche Kunst auf die heutigen Plasma-Fernseher.

Somit kam ich zu der Idee, die Technologien und Konzepte dieser Spielekonsolen für mei-ne Zwecke zu verwenden! Mit der von Nintendo entwickelten Spielekonsole „Wii” wirdein neuer Weg der Benutzer-Maschinen-Interaktion bestriten. Die Wii Konsole liefert zweiSteuereinheiten mit, zum einem die Wii-Fernbedienung (im folgenden „Wiimote” genannt)und den sogenannten Nunchuk (Abbildung 1).

Abbildung 1: Steuerungselemente der Nintendo Wii (Nunchuck und Wiimote v.L.)

Der Wiimote funktioniert kabellos und reagiert durch einen eingebauten Beschleunigungs-sensor auf die Bewegungen des Trägers, die in Translationen und Rotationen im Spiel um-gesetzt werden. Zusätzlich enthält der Wiimote Steuerungsknöpfe, die für weitere Funk-tionen verwendet werden. Der Nunchuck wird über ein Kabel an die Wiimote angeschlos-sen und besitzt auch einen Beschleunigungssensor und zudem ein sehr empfindliches Steuer-ungskreuz mit zwei weiteren Steuerungsknöpfen.

In dieser Arbeit geht es um ein Modernisieren des Spieleklassikers „Tetris”, in Art derDarstellung, sowie der Steuerung. Für die Darstellung wird die plattform- und progra-mmiersprachen-unabhängige API1 OpenGL und als Steuerung die oben genannten Steu-erungselemente verwendet. Auf die Festlegung der Steuerung in diesem Tetris wird imnachfolgenden Abschnitt eingegangen.

3 Tetris, das Spiel

3.1 Spielregeln

Tetris ist eine Art Echtzeitpuzzle. Nacheinander erscheinen Figuren aus vier Blöcken odereinem Block und sinken zum Boden einer Grube. Der Spieler muß diese freihalten, indemer die Figuren bewegt und rotiert. Jedesmal, wenn eine Blockzeile vollständig gefüllt ist,

1Application Programming Interface, Eine Programmierschnittstelle, die von einem Softwaresystem anderenProgrammen zur Anbindung an das System zur Verfügung gestellt wird.

5

Page 6: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

verschwindet sie und alle Blöcke oberhalb fallen herab. Nach jeweils 20 gelöschten Zeilenwird das Spiel ein wenig schneller. Das Spiel ist vorbei, wenn die Grube zu voll für dienächste Figur ist.

Abbildung 2: Kubus, Größe 1x1x1, 1 Stein

Abbildung 3: Linie, Größe 4x1x1, 4 Steine

Abbildung 4: Pyramide, Größe 3x2x1, 4Steine

Abbildung 5: Rechtwinkel, Größe 3x2x1,4 Steine

Abbildung 6: Schlange, Größe 3x2x1, 4Steine

3.2 Punktevergabe

Alle Bausteine haben einen festzugeordneten Punktewert, der beim erfolgreichen Setzender Gesamtpunktzahl hinzuaddiert wird. Der Kubus bringt 10 Punkte, die Linie 30 Punkte,mit der Pyramide werden 100 Punkte addiert, der Rechtwinkel zählt 50 und die Schlange90 Punkte.

3.3 Die Spielwiese

In Abbildung 7 wird das Spiel im pausierten Modus abgebildet. Die schachbrettartige Flä-che ist der Bereich, auf dem die Bausteine gesetzt werden. Diese Fläche ist 10x10 Einheitengroß. Die roten Linien, zwischen aktuellem Baustein und der Spielfläche, dient als Hilfezum Setzen der Bausteine.

6

Page 7: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Abbildung 7: Spielansicht von Tetris GL

Oben links werden die erspielten Punkte dargestellt, oben rechts der nächste Baustein an-gezeigt, der nach dem Setzen des Aktuellen gespielt werden muss. Unten rechts befindensich statistische Werte, die aktuelle Spielzeit, die erspielten Linien und das erreichte Level.In der Titelleiste wird der aktuelle Batteriestand des Wiimote angezeigt, im Bild sind es70%.

3.4 Spielstart

Das Spiel wird normal in einer Konsole gestartet. Zwei Startparameter stehen zur Verfü-gung, die das Verhalten des Spiels beinflussen. Tabelle 1 listet diese auf. Im Listing 1 wirdein exemplarisches Beispiel zum Starten von Tetris GL aufgezeigt.

1 $ . / t e t r i s −−w i i −−a u d i o

Listing 1: Textzeile zum Starten von Tetris GL in einem Konsoleneingabefenster.

Spielparameter beim Programmstart

–wii Es wird eine Verbindung zum Wiimote hergestellt.–audio Die Soundunterstützung wird geladen.

Tabelle 1: Verwendbare Parameter beim Start des Spiels

7

Page 8: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

3.5 Steuerung

Die Hauptsteuerung geschieht mit denen in Kapitel 2 erwähnten Steuerungselementen, Wi-imote und Nunchuck. Die Steuerung ist von vornherein auf die in Tabelle 2 definiertenKombinationen festgelegt und bezieht sich zudem auf die Tasten, die in Abbildung 8 und 9dargestellt sind.

Steuerungsmöglichkeiten mit dem Wiimote und des Nunchuck

Kippung des Wiimote auf derY-Achse “Yaw” (siehe Abbil-dung 8)

Der aktuelle Baustein bewegt sich auf der Z-Achse.

Kippung des Wiimote auf derX-Achse “Roll” (siehe Abbil-dung 8)

Der aktuelle Baustein bewegt sich auf der X-Achse.

Control, Klick auf links/rechts Drehung des Bausteins auf der Z-Achse im Spiel.Control, Klick nach oben/unten Drehung des Bausteins auf der X-Achse in Spiel.1 Schaltet die Ansicht in den Wireframemodus, alle

Bausteine werden als Gittergeflecht angezeigt.2 Pausiert das Spiel oder startet das Spiel neu, wenn es

beendet worden ist.A Drehung des Bausteins auf der Y-Achse im Spiel.B keine ZuordnungC Beschleunigter Fall des aktuellen Bausteins in die Gru-

be.Z Drehung des Bausteins auf der Y-Achse im Spiel.Control, Klick nach oben/unten+ gedrückter B Taste

Heraus-/Hineinzoomen des Beobachters.

Control, Klick auf links/rechts+ gedrückter B Taste

Beobachtungspunkt des Spielers nach rechts und linksverändern.

Stick Drehung des Beobachterpunktes um die X- und Y-Achse im Spiel.

Home Beendet das Spiel und Programm.

Tabelle 2: Zuordnung der Steuerungsmöglichkeiten des Wiimote und des Nunchucks

Sollten dem Spieler keine Steuerelemente des Nintendo Wii zur Verfügung stehen, kann alsErsatz die Standardtastatur verwendet werden. Die Tastenkombinationen sind in Tabelle3 aufgelistet. Diese sind festzugeordnet und können im laufenden Spiel nicht verändertwerden.

4 Architektur

Als Basis für die Entwicklung von Tetris GL kommt SDL2, mit zusätzlichen Bibliotheken,zum Einsatz. Diese Bibliotheken sind:

2Simple Directmedia Layer, www.libsdl.org

8

Page 9: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Steuerungsmöglichkeiten mit der Tastatur

Pfeiltaste links/rechts Drehung des Bausteins um die Z-Achse.Pfeiltaste oben/unten Drehung des Bausteins um die X-Achse.Entfernen Drehung des Bausteins auf der Y-Achse.Seite runter Drehung des Bausteins auf der Y-Achse.D/A Translation des Bausteins auf der X-Achse.Q/E Translation des Bausteins auf der Z-Achse.P Pausiert das Spiel oder startet das Spiel neu, wenn es

beendet worden ist.Enter Beschleunigter Fall des aktuellen Bausteins in die Gru-

be.W/S Heraus-/Hineinzoomen des Beobachters.R/T/F/G Drehung des Beobachterpunktes um die X- und Y-

Achse im Spiel.Esc Beendet das Spiel und Programm.

Tabelle 3: Zuordnung der Steuerungsmöglichkeiten des Wiimote und des Nunchucks

Abbildung 8: Koordinatensystem und Tas-ten des Wiimote Abbildung 9: Tasten des Nunchuck.

• SDL_mixer, zur Ausgabe von Sound.

• SDL_ttf, zur Darstellung von TrueType-Fonts.

Zum Laden von Texturen, jeglichen Dateiformates kommt die Grafikbibliothek Image-Magick3 zum Einsatz. Als Unterstützung dieser Funktionalitäten in der Programmier-sprache C++ wird Magick++4 genutzt. Dies ist die objektorientierte C++ API5.

Zur Visualisierung der grafischen Elemente kommt der Industriestandard OpenGL zumZuge.

3www.imagemagick.org4www.imagemagick.org/Magick%2B%2B/5Application Programming Interface, Eine Programmierschnittstelle ist eine Schnittstelle, die von einem Soft-

waresystem anderen Programmen zur Anbindung an das System zur Verfügung gestellt wird.

9

Page 10: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Die Ansteuerung der Wii Steuerungselemente geschieht mit der noch jungen BibiliothekCWiid6. Diese Bibilothek bietet Möglichkeiten, die Steuerungselemente über Bluetooth zusteuern und im Spiel damit die Interaktion aufzubauen.

Zur Zeit läuft das Spiel nur unter Linux mit folgender Konfiguration (Testumgebung):

• Grafikkarte: GeForce 7900 GS/PCI/SSE2

• OpenGL Version: 2.1.2 NVIDIA 169.12

• SDL Version: 1.2.12

• SDL TTF Version: 2.0.9

• SDL Mixer Version: 1.2

• CWiid Version: 0.6.0

5 Programmablauf

Abbildung 10 verdeutlicht den grundsätzlichen Ablauf eines Spiels. Beim Start des Pro-gramms, werden alle wichtigen Daten und Grundstrukturen initialisiert, u.a. wird die Verbin-dung zur Wiimote hergestellt, wenn dies beim Programmstart angegeben wurde (siehe dazuKapitel 3.4). Als Basis für das Programm muss mindestens das SDL Framework erfolgreichgeladen sein. SDL übernimmt die Verwaltung aller Ausgaben unter dem X11 Windowma-nager. Zudem muss die OpenGL Schnittstelle erfolgreich eingerichtet sein, ohne die keine3D Darstellungen/Ausgaben stattfinden.

Sollten bis hier keine Fehler aufgetreten sein, springt das Programm in die Hauptschleife. Inder Hauptschleife werden alle spielrelevanten Berechnungen durchgeführt. Im Kapitel 7.3wird auf die einzelenen Komponenten, die für die Hauptschleife relevant sind, eingegangen.

Alle Aktionen, die mit der Wiimote ausgeführt werden, ändern intern eine Menge an Va-riablen, die für die Berechnung der Positionen der Bausteine genutzt werden. Die Berech-nungen werden bei jedem Durchlauf der Schleife neu aufgerufen. Die Berechnungen liefernals Ergebniss verschiedene Werte, z.B. ob das aktuelle Objekt mit bestehenden Objektenkollidiert, oder ob die Grube zu voll ist und somit das Spiel beendet ist. Ob das Spiel be-endet ist, wird mit der Variablen gameover überprüft und bei Erfolg wird das Programmpausiert und auf Reaktivierung durch den Benutzer gewartet. Wenn das Spiel noch nicht be-endet ist, wird geprüft ob der gesetzte Stein eine Linie füllt und diese dann aus dem Spielentfernt. Alle Steine die oberhalb dieser Linie sind, werden dann die Anzahl an Linien dieentfernt wurden, nach unten geschoben. Danach wird die komplette Szene neu gezeichnet.

6http://abstrakraft.org/cwiid, CWiid ist eine Sammlung von Linux Werkzeugen die in C geschrieben sind, umeine Verbindung zur Wiimote zu verwalten. Sie enthält eine Event basierende API.

10

Page 11: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Programmablaufplan von Tetris GL

Abbildung 10: Vereinfachter Programmablaufplan

6 Konzept

Im folgenden wird das Umsetzungskonzept von Tetris GL erläutert.

In Abbildung 11 wird die Abhängigkeit von den Klassen die für die Bausteine verwendetwerden, verdeutlicht. Die Basis aller Bausteine bildet die Klasse glObject, die zahlreicheStandardinformationen enthält. Dies sind u.a. die Position der Bausteine im 3D Raum,

11

Page 12: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Abbildung 11: Klassenabhängigkeit von Tetris GL. (UML Konvention)

die Werte der BoundingBox7, die Bewegungsrichtung, die aktuelle Rotation, die Farbe,die Punktkoordinaten der Ecken eines Objektes und die eindeutige Identifikationsnummereiner Textur im Grafikspeicher, die auf die Bausteine gemapped wird.

Die Klasse glCube ist für die ordentliche Darstellung und Berechnung der Koordinaten im3D Raum zuständig. Alle Koordinaten, die an diese Klasse übergeben werden, müssen alsrelative Werte zum Nullpunkt im Raum bei der Koordinate 0, 0, 0 für x, y und z angegebensein. Bei jedem Zeichnen der einzelnen Cubes werden die Koordinaten neu berechnet, egalob es eine Änderung gab. Im Kapitel 8 wird darauf eingegangen. Diese Klasse beinhaltetalle OpenGL-Aufrufe.

glCubeList: Diese Klasse kann eine beliebige Anzahl an glCube-Objekten aufnehmen underbt alle Methoden der Template Container Klasse vector aus der libstdc++ Bibliothek, diebei jedem Linux System automatisch mitgeliefert wird. Der Zugriff benötigt eine lineareZeit, in Abhängigkeit mit der Anzahl der Elemente, die sich in dem Container befinden.

Die Klasse glObjectMatrix beinhaltet ein raffiniertes Konzept, das es dem Entwickler er-möglicht, auf dem schnellsten Wege neue Bausteine in das Spiel zu integrieren. Listing 2liefert ein Beispiel, wie neue Bausteine hinzugefügt werden.

1 # i n c l u d e " forms . h "2 # i n c l u d e " c Co lo r . h "3 # i n c l u d e " glCube . h "4 # i n c l u d e " g l O b j e c t M a t r i x . h "5 . . .67 /∗ ∗ Die E in se n geben an , an w e l c h e r P o s i t i o n , s i c h e i n Kubus ( Cube )

b e f i n d e t .8 ∗ /9 s t a t i c i n t _ _ r e c h t e c k [ ] = {

10 0 , 0 , 1 ,11 1 , 1 , 112 } ;1314 enum FORMSID { FRM_RECT } ;1516 /∗ ∗ S t r u k t u r , d i e a l l e B a u s t e i n e b e i n h a l t e t .

7Eine/Ein Bounding Box/Bounding Volume ist in der algorithmischen Geometrie ein einfacher geometrischerKörper, der ein komplexes dreidimensionales Objekt oder einen komplexen Körper umschließt.

12

Page 13: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

17 ∗ /18 s t a t i c s t r u c t forms {19 i n t ∗ frm ;20 i n t c o l s ;21 i n t rows ;22 i n t d e p t h ;23 c Co lo r c o l o r ;24 FORMSID i d ;25 i n t p o i n t s ;26 } forms [ 1 ] = {27 { _ _ r e c h t e c k , 3 , 2 , 1 , cCo lo r (COLOR_RED) , FRM_RECT, 50 }28 } ;2930 . . .31 /∗ ∗ H i n z u f u e g e n des oben d e f i n i e r t e n B a u s t e i n e s .32 ∗ /33 T e t r i s : : g l O b j e c t M a t r i x b a u s t e i n ;3435 s t r u c t forms ∗ f = &forms [ 0 ] ;3637 b a u s t e i n . p o s i t i o n ( ) = cVec < f l o a t > ( 0 . 0 f , 2 0 . 0 f , 0 . 0 f ) ;3839 b a u s t e i n . s e t M a t r i x ( f−>frm , f−>c o l s , f−>rows ,40 f−>depth , f−>c o l o r , f−>id , 0 ) ;4142 b a u s t e i n . r o t a t e X ( 9 0 . 0 f ) ;43 b a u s t e i n . r o t a t e Y ( 9 0 . 0 f ) ;44 b a u s t e i n . r o t a t e Z ( 9 0 . 0 f ) ;4546 b a u s t e i n , s e t C u b e S e c t o r A r e a (47 cVec < f l o a t >( PLAYGROUND_STARTX, PLAYGROUND_STARTY, PLAYGROUND_STARTZ ) ,48 cVec < f l o a t >( PLAYGROUND_STARTX, PLAYGROUND_STARTY, PLAYGROUND_STARTZ ) ,49 1 . 0 f ) ;5051 . . .

Listing 2: Beispiel für das Hinzufügen von Bausteinen in das Spiel

Zeilen 1-4 inkludieren alle für dieses Beispiel, wichtigen Headerdateien. Diese enthaltendie Definitionen der Klassen und Bausteinelemente.

In Zeile 9 wird ein einfaches Bausteinelement definiert, das dem Rechtwinkel Objekt, Ab-bildung 5 in Kapitel 3, entspricht. Zeile 14 definiert eine eindeutige Identifikations-nummerfür das Element. Zwischen den Zeilen 18 und 28 wird die forms Struktur definiert, die alleBausteinelemente erhält.

Zeile 33 erstellt ein Objekt, welches das Rechteckelement aufnimmt, was die Zeilen 39und 40 beschreiben. Die Methode setMatrix des baustein Objektes erwartet als Parameterdie beschreibenden Daten der forms Struktur. Der letzte Parameter ist die Identifikations-nummer einer Textur, die schon zuvor in den Grafikspeicher geladen wurde. Sollte eineNull übergeben werden, wird keine Struktur auf die Bausteine gemapped, sondern nur eineFarbe die zufällig erstellt wird.

In Zeile 37 wird die Startposition des Bausteins im 3D Raum angegeben. Die Koordinatenwerden für die X-, Y- und Z-Achse angegeben.

Die Methoden zum rotieren sind in diesem Listing nur als exemplarisches Beispiel einge-fügt und müssen an dieser Stelle nicht verwendet werden.

In Zeile 46 bis 49 wird der Kollisionsbereich angegeben. Dies sind die minimalen undmaximalen Koordinaten des Bereiches in dem sich die Benutzerinteraktion ereignet. AlleBewegungen und Änderungen der Bausteinpositionen befinden sich in diesem Bereich.

13

Page 14: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Der erste Parameter ist der minimale Wert, der zweite Parameter ist der maximale Wert,der letzte Parameter ist die Schrittweite, diese teilt den Raum in eine m mal n Matrix.

glObjectMatrixList: Diese Klasse kann eine beliebige Anzahl an glObjectMatrix Ob-jekten aufnehmen und erbt alle Methoden der Template Container Klasse vector aus derlibstdc++ Bibliothek, die bei jedem Linux System automatisch mitgeliefert wird.

cVec<class T>: Eine Klasse zum Berechnen von mathamtischen Vektoren, die mehrereOperatoren überlädt um auf einfachste Weise mit Berechnungen umgehen zu können.

cVecList<class T>: Siehe dazu glCubeList und glObjectMatrixList.

cColor: Diese Klasse repräsentiert eine Farbe in RGB Darstellung.

7 Implementierungen

In diesem Kapitel wird auf verschiedene Funktionen eingegangen, die Einblick in die Funk-tionalität des Spiels bringen.

Grundidee: Alle Bausteine bestehen aus einer Anzahl von glCube Objekten, wie in Ab-bildung 11 zu sehen. Der gesamte Spielraum ist in Sektoren unterteilt, siehe Listing 2 inKapitel 6 und Abbildung 12.

Abbildung 12: Aufteilung des Spielraumes in eine Gitterbox, examplarische Darstellung

Beim Setzen eines Bausteins werden alle glCube Objekte dieses Bausteins auf die aktu-ellen Sektoren aktualisiert, in denen sich der Baustein befindet. Wenn das Spielfeld eine

14

Page 15: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Größe von 10x10 (X- mal Z-Achse) hat, dann sind die Sektorenwerte von eins bis zehn.Der erste Sektor ist dann X=1 und Z=1 und der letzte Sektor ist X=10 und Z=10. Bei derKollisionserkennung werden die Werte der BoundingBox jedes einzelnen glCube Objektesmit den glCube Objekten des aktuellen Bausteins verglichen. Sollte keine Kollision vor-handen sein, wird der Stein in die Richtung, in die er sich bewegen soll, weiter berechnet.Siehe dazu Kapitel 7.1.

Beim Berechnen von komplett gesetzten Linien und der Berechnung von den neuen Po-sitionen von evtl. oberhalb befindlichen glCube Objekten der Bausteien werden die Sek-toren verwendet. Alle Steine oberhalb eines entfernten glCube Objektes werden um einenSektor nach unten verschoben. Siehe dazu Kapitel 7.2.

7.1 Bewegungsfunktionen / Kollisionserkennung

In den Dateien movement.h und movement.cpp sind fünf Funktionen definiert und implemen-tiert, die eine sehr wichtige Funktion erfüllen. Diese Funktionen dienen der Bewegungs-berechnung der Bausteine und überprüfen ob Kollisionen im 3D Raum stattfinden. Es wirdim folgenden auf vier von diesen Funktionen eingegangen, es werden nur vier beschrieben,da sich die fünfte sehr mit einer vorhandenen ähnelt.

• void move_x(- float step,- Tetris::glObjectMatrix & current_object,- Tetris::glObjectMatrixList & cube_list);

Siehe dazu Listing 6. Bewegt das Objekt in negative/positive Richtung auf der X-Achse.

step: Dieser Parameter ist die Schrittweite des Objektes, um die es sich bewegensoll.

current_object: Ist das aktuelle Objekt, welches sich im Interaktionsbereich desBenutzers befindet. Alle Aktionen werden auf dieses Objekt angewendet.

cube_list: Beinhaltet alle Bausteine, die bisher im Spiel gespielt wurden bzw. dieschon gesetzt wurden.

• void move_z(- float step,- Tetris::glObjectMatrix & current_object,- Tetris::glObjectMatrixList & cube_list);

Funktion: Diese Funktion ähnelt der move_x Funktion.

• int check_xyz(- CHKMODE m,- Tetris::glObjectMatrix & current,- Tetris::glObjectMatrixList & cube_list,- float ystep = 0.0f);

check_xyz(...) (siehe dazu Kapitel 7.1.1) übernimmt die Prüfung für die einzelnenAchsen im 3D Raum.

15

Page 16: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

m Dies ist ein enum Wert, dieser gibt an auf welcher Achse die Kollision überprüftwerden soll. Die möglichen Werte stehen in der Datei „movement.h”.

current: Aktuelles Objekt, das überprüft werden soll.

cube_list: Die Liste alle Objekte, die mit current verglichen werden.

ystep: Dieser Wert bestimmt, wie weit das Objekt auf der Y-Achse nach unten ge-setzt wird, wenn keine Kollision aufgetreten ist.

• bool check_gameover(- Tetris::glObjectMatrix & current,- float maxy);

Diese Funktion überprüft, ob ein Stein nicht weiter nach unten auf der Y-Achse ge-setzt werden kann. Wenn dies der Fall ist, wird TRUE zurück geliefert und das Spielist beendet.

current_object: Ist das aktuelle Objekt, welches sich im Interaktionsbereich desBenutzers befindet. Die Überprüfung wird auf dieses Objekt angewendet.

maxy: Die maximale Koordinate auf der Y-Achse. Wenn ein Stein diese Grenzeüberschreitet, dann ist das Spiel beendet, da dieser nicht weiter nach unten ge-setzt werden kann.

• MUSICTRACK calculate_objects(- float ss,- Tetris::glObjectMatrix & current_object,- Tetris::glObjectMatrix & next_object,- Tetris::glObjectMatrixList & cube_list);

calculate_objects (siehe Listing 7) enthält die Logik, die mit den oben genanntenFunktionen die neuen Positionen der Bausteinobjekten berechnet und für die Objek-te setzt.

ss Die Schrittweite, die im passenden Verhältnis zur Framerate für das aktuelle Bau-steinobjekt verwendet werden soll.

current_object: Ist das aktuelle Objekt, welches sich im Interaktionsbereich desBenutzers befindet. Die Berechnung wird auf dieses Objekt angewendet.

next_object: Das Objekt, welches beim Setzen des aktuellen Objektes („current-_object”) zum neuen aktuellen wird.

cube_list: Die Liste aller Objekte, die mit current_object verglichen werden.

7.1.1 check_xyz(...)

Im folgenden wird auf diese Funktion näher eingegangen. Die Beschreibungen stehen alsKommentare im Quelltext.

enum-Werte von CHKMODE

1 enum CHKMODE { CHK_NONE=0x00 ,2 CHK_X=0x01 ,3 CHK_Y=0x02 ,4 CHK_XY=CHK_X | CHK_Y,5 CHK_Z=0x04 ,

16

Page 17: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

6 CHK_XZ=CHK_X | CHK_Z,7 CHK_YZ=CHK_Y | CHK_Z,8 CHK_ALL = CHK_X | CHK_Y | CHK_Z9 } ;

Listing 3: C++ enumerate Werte von CHKMODE.

Die Funktion check_xyz(...) im Detail

1 i n t check_xyz ( CHKMODE m,2 T e t r i s : : g l O b j e c t M a t r i x & c u r r e n t ,3 T e t r i s : : g l O b j e c t M a t r i x L i s t & c u b e _ l i s t ,4 f l o a t y s t e p )5 {6 / / Der Rueckgabewer t der F u n k t i o n .7 i n t r e t = CHK_NONE;89 /∗ D i e s e r Wert i s t e i n Abs tandsmass f u e r d i e Ueberprue fung der K o l l i s i o n

10 ∗ z w i s c h e n dem a k t u e l l e n B a u s t e i n und den schon im S p i e l vorhandenen .11 ∗ Die u n t e r e S k i z z e s o l l d i e s v e r d e u t l i c h e n .12 ∗ /13 # d e f i n e V 0 . 0 2 f1415 /∗ A l l e glCube O b j e k t e e i n e s B a u s t e i n s durchgehen und16 ∗ a u f K o l l i s i o n m i t dem a k t u e l l e n B a u s t e i n o b j e k t u e b e r p r u e f e n .17 ∗ /18 f o r ( i n t i = 0 ; i < c u r r e n t . cubeCount ( ) ; i ++ )19 {20 # d e f i n e CURRENT c u r r e n t . cubes ( )−>a t ( i )2122 f l o a t x_c_low = CURRENT. l o w P o s i t i o n ( ) . x ( ) ;23 f l o a t y_c_low = CURRENT. l o w P o s i t i o n ( ) . y ( ) ;24 f l o a t z_c_low = CURRENT. l o w P o s i t i o n ( ) . z ( ) ;2526 f l o a t x_c_h igh = CURRENT. h i g h P o s i t i o n ( ) . x ( ) ;27 f l o a t y_c_h igh = CURRENT. h i g h P o s i t i o n ( ) . y ( ) ;28 f l o a t z _ c _ h i g h = CURRENT. h i g h P o s i t i o n ( ) . z ( ) ;2930 / / S o l l t e der S t e i n t i e f e r s e i n , a l s d i e S p i e l f l a e c h e ,31 / / dann muss k e i n e w e i t e r e Berechnung d u r c h g e f u e h r t werden .32 i f ( y_c_low <= 0 . 0 f ) {33 re turn CHK_ALL;34 }3536 x_c_low += V; x_c_h igh −= V;37 y_c_low += V; y_c_h igh −= V;38 z_c_low += V; z _ c _ h i g h −= V;3940 v e c t o r < T e t r i s : : g l O b j e c t M a t r i x > : : i t e r a t o r i t = c u b e _ l i s t . b e g i n ( ) ;41 f o r ( ; i t != c u b e _ l i s t . end ( ) ; i t ++ )42 {43 f o r ( i n t j = 0 ; j < i t −>cubeCount ( ) ; j ++ ) {44 # d e f i n e CHECK i t −>cubes ( )−>a t ( j )4546 i f ( m & CHK_X ) {47 f l o a t x_low = CHECK. l o w P o s i t i o n ( ) . x ( ) ;48 f l o a t x_h igh = CHECK. h i g h P o s i t i o n ( ) . x ( ) ;4950 / / U e b e r p r u e f t ob d i e BoundingBox−Werte der X−Achse51 / / im B e r e i c h e i n e r anderen BoundingBox k o l l i d i e r e n .52 i f ( x_c_low >= x_low && x_c_low <= x_high )53 r e t | = CHK_X;54 }5556 i f ( m & CHK_Z ) {57 f l o a t z_low = CHECK. l o w P o s i t i o n ( ) . z ( ) ;58 f l o a t z_ h i gh = CHECK. h i g h P o s i t i o n ( ) . z ( ) ;

17

Page 18: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

5960 / / U e b e r p r u e f t ob d i e BoundingBox−Werte der Z−Achse61 / / im B e r e i c h e i n e r anderen BoundingBox k o l l i d i e r e n .62 i f ( z_c_low >= z_low && z_c_low <= z _h i gh )63 r e t | = CHK_Z;64 }6566 / / Nach e i n e r K o l l i s i o n i s t das a k t u e l l e O b j e k t e t i e f e r a l s das67 / / Ob jek t , m i t dem es k o l l i d i e r t i s t , drum muss es v e r s c h o b e n68 / / werden . D i e s e s D e l t a i s t der Wert , um das es v e r s c h o b e n wird .69 f l o a t dy = 0 . 0 f ;7071 i f ( m & CHK_Y ) {72 f l o a t y_low = CHECK. l o w P o s i t i o n ( ) . y ( ) ;73 f l o a t y_h igh = CHECK. h i g h P o s i t i o n ( ) . y ( ) ;7475 dy = y_c_low − y_h igh ;7677 f l o a t dd = y_low − y_c_h igh ;7879 i f ( dy < f a b s ( y s t e p ) && dd < 0 . 0 f )80 r e t | = CHK_Y;81 }82 # undef CHECK83 i f ( r e t == m )84 {85 f o r ( i n t i n d e x = 0 ; i n d e x < c u r r e n t . cubeCount ( ) ; i n d e x ++ )86 {87 # d e f i n e L c u r r e n t . cubes ( )−>a t ( i n d e x ) . l o w P o s i t i o n ( )88 # d e f i n e H c u r r e n t . cubes ( )−>a t ( i n d e x ) . h i g h P o s i t i o n ( )89 # d e f i n e P c u r r e n t . cubes ( )−>a t ( i n d e x ) . p o s i t i o n ( )90 L . y ( ) += dy − 1 . 0 f ;91 H. y ( ) += dy − 1 . 0 f ;92 P . y ( ) += dy ;93 # undef P94 # undef H95 # undef L96 }97 re turn r e t ;98 } e l s e99 r e t = CHK_NONE;

100 }101 }102 # undef CURRENT103 }104 # undef V105 re turn r e t ;106 }

Listing 4: Detailbeschreibung von der Funktion check_xyz(...).

Kollisionerkennung des aktuellen Bausteins

In Abbildung 13 ist die Kollisionerkennung des aktuellen Bausteins mit anderen schon ge-setzten Bausteinen verdeutlicht. Der BoundingBox Werte des aktuellen Bausteins werdenmanuell um einen Wert (siehe Listing 4) geschrumpft. Nun wird überprüft, ob sich dieseWerte im Bereich eines anderen Bausteines befinden. Diese Überprüfung ist ohne Problemeim 3D Raum, für drei Achsen möglich und verhindert auch, dass es bei dieser Überprüfungzu Rundungsfehlern kommt.

Es hat sich im Verlauf der Entwicklung dieses Spiels gezeigt, dass es bei der Subtraktioneines Wertes auf der Y-Achse, um den Stein nach unten zu verschieben, zu Rundungsfeh-lern kommt. Dies hat mit der Darstellung von Fließkommazahlen im Hauptspeicher zu tun.Da die Genauigkeit in der Abspeicherung auf eine bestimmte Speichergröße beschränkt ist.

18

Page 19: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

Abbildung 13: Kollisionsgrafik für den aktuellen Baustein

Siehe dazu Listing 5. In der Ausgabe ist unschwer zu erkennen, dass nicht der erwarteteWert aus-gegeben wird. Um diesen Fehler zu entgehen, bietet es sich an, die oben genannteTechnik zu verwenden.

1 # i n c l u d e < i o s t r e a m >2 # i n c l u d e <iomanip >3 us ing namespace s t d ;45 i n t main ( i n t argc , char ∗∗ a rgv ) {6 f l o a t f z = 0 . 5 f − 0 . 1 f ; / / S o l l t e 0 . 4 f a l s E r g e b n i s s l i e f e r n !7 c o u t << " f z : " << s e t p r e c i s i o n ( 3 2 ) << f z << e n d l ;8 }9

10 / / Ausgabe :11 f z : 0 .4000000059604644775390625

Listing 5: Rundungsfehler bei Fließkommazahlen

7.1.2 move_x(...)

Im folgenden wird auf diese Funktion näher eingegangen. Die Beschreibungen stehen alsKommentare im Quelltext.

1 void move_x ( f l o a t s t e p ,2 T e t r i s : : g l O b j e c t M a t r i x & c u r r e n t _ o b j e c t ,3 T e t r i s : : g l O b j e c t M a t r i x L i s t & c u b e _ l i s t )4 {5 / / Das a k t u e l l e O b j e k t wird i e i n t e m p o r a e r e s O b j e k t k o p i e r t , das s6 / / d i e K o o r d i n a t e n der neuen P o s i t i o n e n t h a e l t . Auf d i e s e s O b j e k t7 / / w ird d i e K o l l i s i o n s e r k e n n u n g angewandt . S o l l t e k e i n e K o l l i s i o n8 / / vorhanden s e i n , wird d i e neue P o s i t i o n uebernommen .9 T e t r i s : : g l O b j e c t M a t r i x objTmp ( c u r r e n t _ o b j e c t ) ;

1011 T e t r i s : : g l C u b e L i s t ∗ c = objTmp . cubes ( ) ;1213 f o r ( i n t i =0 ; i <objTmp . cubeCount ( ) ; i ++ )14 {15 # d e f i n e C c u r r e n t _ o b j e c t . cubes ( )−>a t ( i )16 c−>a t ( i ) . l o w P o s i t i o n ( ) . x ( ) = C . l o w P o s i t i o n ( ) . x ( ) + s t e p ;17 c−>a t ( i ) . h i g h P o s i t i o n ( ) . x ( ) = C . h i g h P o s i t i o n ( ) . x ( ) + s t e p ;1819 c−>a t ( i ) . l o w P o s i t i o n ( ) . y ( ) = C . l o w P o s i t i o n ( ) . y ( ) ;20 c−>a t ( i ) . h i g h P o s i t i o n ( ) . y ( ) = C . h i g h P o s i t i o n ( ) . y ( ) ;21

19

Page 20: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

22 c−>a t ( i ) . l o w P o s i t i o n ( ) . z ( ) = C . l o w P o s i t i o n ( ) . z ( ) ;23 c−>a t ( i ) . h i g h P o s i t i o n ( ) . z ( ) = C . h i g h P o s i t i o n ( ) . z ( ) ;24 # undef C25 }2627 / / U e b e r p r u e f t a u f a l l e n d r e i Achsen ob e i n e K o l l i s i o n vorhanden i s t .28 i n t r e t = check_xyz ( CHK_ALL, objTmp , c u b e _ l i s t ) ;2930 / / S o l l t e s t e p e i n n e g a t i v e r Wert s e i n , dann s o l l das O b j e k t i n n e g a t i v e31 / / R i c h t u n g a u f der X−Achse v e r s c h o b e n werden . S o l l t e das S p i e l f e l d e n d e32 / / e r r e i c h t s e i n , wird e i n e K o l l i s i o n v o r g e t a e u s c h t .33 / / S e l b e s g i l t f u e r p o s i t i v e R i c h t u n g .34 i f ( s t e p < 0 )35 {36 i f ( c u r r e n t _ o b j e c t . l o w P o s i t i o n ( ) . x ( ) + s t e p < PLAYGROUND_STARTX | |37 r e t == CHK_ALL )38 re turn ;39 } e l s e40 {41 i f ( c u r r e n t _ o b j e c t . h i g h P o s i t i o n ( ) . x ( ) + s t e p > PLAYGROUND_ENDX | |42 r e t == CHK_ALL )43 re turn ;44 }4546 / / Die neue P o s i t i o n des B a u s t e i n o b j e k t e s wird b e r e c h n e t .47 c u r r e n t _ o b j e c t . l o w P o s i t i o n ( ) . x ( ) += s t e p ;48 c u r r e n t _ o b j e c t . h i g h P o s i t i o n ( ) . x ( ) += s t e p ;49 c u r r e n t _ o b j e c t . p o s i t i o n ( ) . x ( ) += s t e p ;50 }

Listing 6: Detailbeschreibung von der Funktion move_x(...)

7.1.3 calculate_objects(...)

Im folgenden wird auf diese Funktion näher eingegangen. Die Beschreibungen stehen alsKommentare im Quelltext.

1 MUSICTRACK c a l c u l a t e _ o b j e c t s ( f l o a t ss ,2 T e t r i s : : g l O b j e c t M a t r i x & c u r r e n t _ o b j e c t ,3 T e t r i s : : g l O b j e c t M a t r i x & n e x t _ o b j e c t ,4 T e t r i s : : g l O b j e c t M a t r i x L i s t & c u b e _ l i s t )5 {6 / / Auf a l l e n d r e i Achsen , a u f K o l l i s i o n e n , u e b e r p r u e f e n .7 i n t r e t = check_xyz ( CHK_ALL, c u r r e n t _ o b j e c t , c u b e _ l i s t , s s ) ;89 i f ( r e t == CHK_ALL ) {

10 f l o a t dy = c u r r e n t _ o b j e c t . l o w P o s i t i o n ( ) . y ( ) ;11 i f ( dy < 0 . 0 f )12 {13 T e t r i s : : g l C u b e L i s t : : i t e r a t o r s i t = c u r r e n t _ o b j e c t . cubes ( )−>b e g i n ( ) ;14 T e t r i s : : g l C u b e L i s t : : i t e r a t o r e i t = c u r r e n t _ o b j e c t . cubes ( )−>end ( ) ;1516 f o r ( ; s i t != e i t ; s i t ++ ) {17 s i t −>l o w P o s i t i o n ( ) . y ( ) += dy ;18 s i t −>h i g h P o s i t i o n ( ) . y ( ) += dy ;19 s i t −> p o s i t i o n ( ) . y ( ) += dy ;20 }21 }22 / / Fo lgende Anweisung s i n d f u e r d i e Mus ikwiedergabe z u s t a e n d i g .23 / / Beim S e t z e n e i n e s S t e i n e s wird e i n Wert z u r u e c k g e l i e f e r t , der

a u s s a g t ,24 / / das e i n e zu d i e s e r A k t i o n p a s s e n d e M u s i k d a t e i a b g e s p i e l t werden s o l l

.25 i f ( p l a y _ m u s i c _ s e t == f a l s e )

20

Page 21: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

26 re turn SET ;27 e l s e28 re turn NONE;29 } e l s e {30 / / P o s i t i o n des O b j e k t e s a u f der Y−Achse neu s e t z e n .31 c u r r e n t _ o b j e c t . p o s i t i o n ( ) . y ( ) += s s ;32 }3334 re turn NONE;35 }

Listing 7: Dateilbeschreibung von der Funktion calculate_objects(...)

7.2 Logische Funktionen

In den Dateien logic.h und logic.cpp sind zwei Funktionen definiert und implementiert, diedie logische Verarbeitung der gesetzten Bausteine übernehmen. Die Aufgaben sind unteranderem das Erkennen und Entfernen von kompletten Zeilen und Entfernen von glObject-Matrix Objekten aus der Liste aller gesetzten Bausteine, im Grunde eine Speicher-freigabevon nicht genutzen Speicher.

• void remove_empty_objects(- Tetris::glObjectMatrixList & cube_list); Diese Funktion entfernt nicht genutzte glObjectMatrix Objekte aus der Liste allerbisher gesetzten glObjectMatrix Objekte. Dies sind alle, die keine glCube Objektemehr besitzen.

cube_list: Liste aller gesetzten Bausteinobjekte.

• void remove_line(- Tetris::glObjectMatrix & current_object,- Tetris::glObjectMatrixList & cube_list,- cVecList<int> * x_list, cVecList<int> * z_list); Diese Funktion entfernt alle vervollständigten Linien auf der X- und Z-Achse. DieSektoren der glCube Objekte, die entfernt werden, werden in den Listen x_list undz_list abgespeichert.

current_object: Aktuelles Bausteinobjekt.

cube_list: Liste aller bisher gesetzten Bausteinobjekte.

x_list: Die Sektorenwerte aller glCube Objekte, die entfernt wurden.

z_list: Siehe x_list!

7.2.1 remove_line(...)

Im folgenden wird auf diese Funktion näher eingegangen. Die Beschreibungen stehen alsKommentare im Quelltext.

1 void r e m o v e _ l i n e ( T e t r i s : : g l O b j e c t M a t r i x & c u r r e n t _ o b j e c t ,2 T e t r i s : : g l O b j e c t M a t r i x L i s t & c u b e _ l i s t ,3 cVecLis t < i n t > ∗ x _ r e t _ l i s t , cVecLis t < i n t > ∗ z _ r e t _ l i s t4 )5 {6 / / / L e t z t e n g e s e t z t e n Cube durchgehen .7 T e t r i s : : g l C u b e L i s t : : i t e r a t o r c c _ i t = c u r r e n t _ o b j e c t . cubes ( )−>b e g i n ( ) ;

21

Page 22: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

8 f o r ( ; c c _ i t != c u r r e n t _ o b j e c t . cubes ( )−>end ( ) ; c c _ i t ++ )9 {

10 # d e f i n e CCSEC c c _ i t −> s e c t o r ( )1112 / / L i s t e der S e k t o r e n von glCube Objek ten , d i e e n t f e r n t werden .13 cVecLis t < i n t > x _ l i s t ;14 cVecLis t < i n t > z _ l i s t ;1516 / / A l l e b i s h e r g e s e t z t e n Cubes durchgehen und deren . . .17 T e t r i s : : g l O b j e c t M a t r i x L i s t : : i t e r a t o r c l _ i t = c u b e _ l i s t . b e g i n ( ) ;18 f o r ( ; c l _ i t != c u b e _ l i s t . end ( ) ; c l _ i t ++ )19 {20 / / . . . e i n z e l e n e Cubes a u f A c h s e n g l e i c h h e i t u e b e r p r u e f e n .21 f o r ( i n t i = 0 ; i < c l _ i t −>cubeCount ( ) ; i ++ )22 {23 # d e f i n e CLSEC c l _ i t −>cubes ( )−>a t ( i ) . s e c t o r ( )24 / / Auf der X−Achse u e b e r p r u e f e n .25 i f ( CLSEC . y ( ) == CCSEC . y ( ) &&26 CLSEC . z ( ) == CCSEC . z ( )27 )28 x _ l i s t . push_back (CLSEC) ;2930 / / Auf der Z−Achse u e b e r p r u e f e n .31 i f ( CLSEC . y ( ) == CCSEC . y ( ) &&32 CLSEC . x ( ) == CCSEC . x ( )33 )34 z _ l i s t . push_back (CLSEC) ;35 # undef CLSEC36 }37 }3839 / / U e b e r p r u e f e n ob e i n e Z e i l e a u f der X−Achse v o l l e n d e t wurde .40 / / Das S p i e l f e l d h a t e i n e B r e i t e von 10 S e k t o r e n .41 i f ( x _ l i s t . s i z e ( ) == 10 )42 {43 x _ r e t _ l i s t −>a s s i g n ( x _ l i s t . b e g i n ( ) , x _ l i s t . end ( ) ) ;4445 c l _ i t = c u b e _ l i s t . b e g i n ( ) ;46 T e t r i s : : g l O b j e c t M a t r i x L i s t : : i t e r a t o r c l _ i t _ e n d = c u b e _ l i s t . end ( ) ;47 f o r ( ; c l _ i t != c l _ i t _ e n d ; c l _ i t ++ )48 {49 f o r ( i n t i i = 0 ; i i < x _ l i s t . s i z e ( ) ; i i ++ )50 {51 c l _ i t −>removeCubeX ( x _ l i s t . a t ( i i ) ) ;52 }53 }5455 i f ( c u r r e n t _ o b j e c t . cubeCount ( ) <= 0 )56 re turn ;57 }5859 / / U e b e r p r u e f e n ob e i n e Z e i l e a u f der Z−Achse v o l l e n d e t wurde .60 / / Das S p i e l f e l d h a t e i n e B r e i t e von 10 S e k t o r e n .61 i f ( z _ l i s t . s i z e ( ) == 10 )62 {63 z _ r e t _ l i s t −>a s s i g n ( z _ l i s t . b e g i n ( ) , z _ l i s t . end ( ) ) ;6465 c l _ i t = c u b e _ l i s t . b e g i n ( ) ;66 T e t r i s : : g l O b j e c t M a t r i x L i s t : : i t e r a t o r c l _ i t _ e n d = c u b e _ l i s t . end ( ) ;67 f o r ( ; c l _ i t != c l _ i t _ e n d ; c l _ i t ++ )68 {69 f o r ( i n t i i = 0 ; i i < z _ l i s t . s i z e ( ) ; i i ++ )70 {71 c l _ i t −>removeCubeZ ( z _ l i s t . a t ( i i ) ) ;72 }73 }74 }

22

Page 23: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

75 # undef CCSEC76 }77 }

Listing 8: Detailbeschreibung von der Funktion remove_line(...)

7.3 Hauptschleife

Dieses Kapitel beschreibt die Hauptschleife des Spiels, in der alle oben genannten Funk-tionen aufgerufen werden und in der bestimmt wird, ob u.a. das Spiel pausiert ist oderbeendet und wie die Musik abgespielt wird.

7.3.1 main -> Loop-Game

1 whi le ( run ) {2 / / Ein boolean−Wert , der a n g i b t ob H i n t e g r u n d m u s i k g e s p i e l t werden s o l l .3 i f ( p l a y _ m u s i c )4 Mix_Play ing ( channe l_ theme ) ;56 / / Frames per Second ( FPS ) Berechnung , w i c h t i g um a u f v e r s c h i e d e n e n7 / / Rechnern , d i e u n t e r s c h i e d l i c h e R e s s o u r c e n haben , e i n e n z e i t l i c h8 / / i d e n t i s c h e n S p i e l v e r l a u f zu haben .9 i d l e _ f u n c ( ) ;

1011 / / B e a r b e i t e t d i e Eingaben des B e n u t z e r s ( T a s t a t u r e i n g a b e n ) .12 p r o c e s s _ e v e n t s ( ) ;1314 / / Das S p i e l w e i t e r l a u f e n l a s s e n , wenn es n i c h t zu ende oder15 / / p a u s i e r t i s t .16 i f ( ! gameover | | ! paused )17 {18 / / P o s i t i o n e n der B a u s t e i n o b j e k t e berechnen .19 i n t r = c a l c u l a t e _ o b j e c t s ( s t e p _ f p s ( ) ,20 c u r r e n t _ o b j e c t ,21 n e x t _ o b j e c t ,22 c u b e _ l i s t ) ;2324 / / Der Rueckgabewer t r g i b t an was zu t u n i s t , ob e i n S t e i n25 / / g e s e t z t wurde oder ob d i e s e r nur bewegt wurde .26 sw i t ch ( r )27 {28 case SET : {29 / / I s t das S p i e l beende t , nach dem n a e c h s t e n Zug?30 gameover = check_gameover ( c u r r e n t _ o b j e c t , w u e r f e l _ s t a r t . y ( ) ) ;31 / / S e k t o r e n neu s e t z e n .32 c u r r e n t _ o b j e c t . u p d a t e S e c t o r s ( ) ;3334 T e t r i s : : g l O b j e c t M a t r i x co = c u r r e n t _ o b j e c t ;3536 / / Neues B a u s t e i n o b j e k t e r z e u g e n .37 c u r r e n t _ n e x t _ c u b e ( c u r r e n t _ o b j e c t , n e x t _ o b j e c t , c u b e _ l i s t ) ;3839 cVecLis t < i n t > x _ l i s t , z _ l i s t ;4041 / / Die L i s t e der S e k t o r e n e r m i t t e l n d i e e n t f e r n t wurde .42 r e m o v e _ l i n e ( co , c u b e _ l i s t , &x _ l i s t , &z _ l i s t ) ;4344 / / N i c h t mehr b e n o e t i g t e B a u s t e i n o b j e k t e aus der B a u s t e i n l i s t e

e n t f e r n e n .45 r e m o v e _ e m p t y _ o b j e c t s ( c u b e _ l i s t ) ;46

23

Page 24: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

47 / / Die S t e i n e o b e r h a l b der e n t f e r n t e n S e k t o r e n um e i n e n S e k t o r nachu n t e n v e r s c h i e b e n .

48 T e t r i s : : g l O b j e c t M a t r i x L i s t : : i t e r a t o r s i t = c u b e _ l i s t . b e g i n ( ) ;49 T e t r i s : : g l O b j e c t M a t r i x L i s t : : i t e r a t o r e i t = c u b e _ l i s t . end ( ) ;50 f o r ( ; s i t != e i t ; s i t ++ )51 {52 f o r ( i n t i =0 ; i < x _ l i s t . s i z e ( ) ; i ++ )53 {54 s i t −>updateCubeY ( x _ l i s t . a t ( i ) , 0 ) ;55 }5657 f o r ( i n t i =0 ; i < z _ l i s t . s i z e ( ) ; i ++ )58 {59 s i t −>updateCubeY ( z _ l i s t . a t ( i ) , 1 ) ;60 }61 }6263 / / Je nachdem ob e i n S t e i n g e s e t z t wurde , e i n e b e s t i m m t e S o u n d d a t e i

a b s p i e l e n .64 i f ( p l a y _ m u s i c )65 {66 p l a y _ m u s i c _ s e t = t rue ;67 Mix_Channe lF in i shed ( m y _ a u d i o _ f i n i s h e d ) ;68 Mix_Chunk ∗ sound =69 Mix_LoadWAV ( " d a t a / music / b lock−s e t 1 . wav " ) ;70 i f ( sound == NULL) {71 f p r i n t f ( s t d e r r , " Unable t o l o a d WAV f i l e : %s \ n " ,72 Mix_GetEr ror ( ) ) ;73 }74 c h a n n e l _ s e t = Mix_PlayChannel (−1 , sound , 0 ) ;75 i f ( c h a n n e l _ s e t == −1) {76 f p r i n t f ( s t d e r r , " Unable t o p l a y WAV f i l e : %s \ n " ,77 Mix_GetEr ror ( ) ) ;78 }79 }8081 } break ;82 case NONE:83 d e f a u l t :84 ;85 }86 } / / gameover8788 / / Die k o m p l e t t e S z e n e r i e neu z e i c h n e n .89 d r a w _ s c r e e n ( ) ;90 } / / w h i l e ( run )

8 Verbesserungswürdig

• Die Steuerung der Nintendo Wii Fernbedienung könnte durch eine Skalierung, dievom Spieler durchgeführt wird, an seine Bedürfnisse angepasst werden.

• Die Performance kann stark verbessert werden, u.a. besitzt die Kollisionserkennungeinen erheblichen Aufwand an Rechenzeit. Je mehr Steine in der Liste der gesetztenBausteine vorhanden sind, je höher ist der zeitliche Aufwand um alle Steine auf eineKollision zu überprüfen.

• Das Entfernen von komplettierten Linien könnte animiert werden.

24

Page 25: Grafische Datenverarbeitung Sommersemester 2008 Wii Tetris

9 Probleme bei der Entwicklung

• Das größte Problem bei der Entwicklung dieses Spiels, war das nicht Erkennen vonden massiven Rundungsfehlern bei Fließkommazahlen. Es wurde davon ausgegan-gen, dass Subtraktionen und Addition zu keinen Fehlern führen. In der ersten Ver-sion wurde die Kollisionerkennung sehr fehleranfällig, es wurde da noch auf einenäquivalenten Wert der BoundingBoxen überprüft. Diesem Thema sollte besondereAufmerksamkeit zugesprochen werden.

• Ein weiteres Problem lag an der Programmiersprache C++. Es sollte die Regel dergroßen 3 beachtet werden. Diese Regel lautet:

Ist eine der Memberfunktionen- - Kopierkonstruktor- - Destruktor- - Überladener Zuweisungsoperatornotwendig, so sind in der Regel auch diebeiden anderen Memberfunktionen erfor-derlich.

Sollte diese Regel nicht Beachtung finden, kann es sein, dass beim Zuweisen oder Er-stellen von Objekten nicht alle Daten des schon erstellten Objektes rüberkopiert wer-den. Der Programmierer ist dafür verantwortlich, dass der Kopierkonstruktor oderder überladene Zuweisungsoperator definiert wird. Wer sich keine Sorgen machenwill, sollte einfach alle oben genannten Methoden implementieren!

Literaturverzeichnis

[1] Wright, Richard S. and Lipchak, Benjamin: OpenGL Superbible, 3. Edition, SamsPublishing, 2005

[2] GPU Gems 2 / Edited by Matt Pharr: Programming Techniques for High-PerformanceGraphics and General-Purpose Computation, Addison-Wesley, 2005

[3] Prinz, Peter; Kirch-Prinz, Ulla: C++ Lernen und professionell anwenden, 1. Auflage,Bonn: MITP-Verlag GmbH, 1999

[4] Papula, Lothar; Mathematische Formelsammlung, 8. Auflage, Wiesbaden: Friedr.Vieweg & Sohn Verlag/GWV Fachverlag GmbH

[5] http://nehe.gamedev.net, Neon Helium, Articles and Tutorials about OpenGL

25