Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS...

44
Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation und 3D Programmierung Prof. Dr. Manfred Thaller Referentin: Marietta Steinhöfel

Transcript of Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS...

Page 1: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das erste SpielUniversität zu Köln

Historisch Kulturwissenschaftliche Informationsverarbeitung

WS 12/13Übung: Visuelle Programmierung I – Simulation und 3D

ProgrammierungProf. Dr. Manfred Thaller

Referentin: Marietta Steinhöfel

Page 2: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Gliederung1. Das Spielprinzip2. Das Spielgerüst3. Der Code

Die Grundklasse CBreakanoid Das Titelbild Das Hauptmenü Sound

Page 3: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

1. Das Spielprinzip Name: „Breakanoid“ (Arkanoid +

Breakout) „2.5D-Grafik“:

Grafik: 3D Bewegung: 2D (xz-Ebene)

Kamera synchron zu Schläger

Page 4: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

2. Das Spielgerüst Die Spielzustände enum-Aufzählung verwaltet Spielzustände:

EGameState (speichert Wert für Spielzustand)

1. Intro = Titelbild, über das man zum Hauptmenü gelangt GS_INTRO

2. Hauptmenü = Hintergrundbild & Vordergrund (Auswahl Menüeintrag) GS_MAIN_MENU

3. Spiel GS_GAME

4. Kein Spielzustand GS_NONE

Page 5: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

2. Das Spielgerüst Die Breakanoid-Klasse Grundklasse, die das ganze Spiel verwaltet:

CBreakanoid1. Instanz der Klasse wird in WinMain-Funktion erzeugt 2. Methode wird aufrufen, um Spiel zu starten3. Am Ende wird Instanz wieder gelöscht

Page 6: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

2. Das Spielgerüst Die Spielzustandklassen Zusätzlich Klassen für Spielzustände:

CIntro CMainMenu CGame

Zeiger auf Instanzen d. Klassen in CBreakanoid gespeichert & erstellt

Page 7: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

2. Das Spielgerüst Methoden CBreakanoid- und Spielzustandklassen haben folgende Methoden:

1. Load lädt Daten für ganzes Spiel (CBreakanoid::Load) oder

bestimmte Zustände (CIntro::Load)2. Unload

Herunterfahren3. Init

Initialisierung des kompletten Spiels bzw. Spielzuständen Aufruf der Load -Methode

4. Exit Macht Schritte rückgängig Aufruf der Unload-Methode

Page 8: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

2. Das Spielgerüst Verwaltung der Spielzustände Spielzustand ändern mit Methode CBreakanoid::SetGameState

bekommt gewünschten Wert übergeben (GameState)1. Aktuellen Zustand verlassen

z.B.: CIntro::Exit Methode aufrufen2. Neuen Zustand initialisieren

z.B.: CMainMenu::Init3. Beginn & Ende = kein Spielzustand

GS_NONE

Page 9: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

3. Der Code

Page 10: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

3. 1 Die Grundklasse Breakanoid Breakanoid.cpp Breakanoid.h

Page 11: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Variablen I// CBreakanoid-Klasseclass CBreakanoid{public:// VariablentbConfigm_Config; // Konfiguration TriBase-EnginePDIRECT3DSTATEBLOCK9m_pStateBlock; // Statusblock für Direct3D

// Instanzen der Spielzustände – ihre Zeiger werden in Klasse gespeichert

CIntro* m_pIntro; // Intro CMainMenu* m_pMainMenu; // Hauptmenü CGame* m_pGame; // Spiel EGameState m_GameState; // Speichern des Aktuellen

Spielzustands floatm_fTime; // Stoppuhr = zählt wie viele

Sek. Zustand schon aktiv ist

[...]

Page 12: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Variablen II// Globale Variablenextern CBreakanoid*g_pBreakanoid; // Breakanoid-Zeigerextern float*g_pfButtons; // Array mit float-Werten zur

Abfrage der Eingabegeräte speichert Zustand analoger Knöpfeextern BOOL*g_pbButtons; // Array für digitale Werte d.

Knöpfe

Page 13: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden SetGameState I// Setzt einen neuen SpielzustandtbResult CBreakanoid::SetGameState(EGameState NewGameState)

//erwartet EGameState-Wert

{tbResult r = TB_OK;

// 1. Alten Spielzustand entladenSwitch (m_GameState) // GameState: speichert aktuellen/alten

Zustand{ case GS_INTRO: m_pIntro->Exit(); break; // Alten Zustand

herunterfahren case GS_MAIN_MENU :m_pMainMenu->Exit(); break; //durch Aufruf der Exit-

Methodecase GS_GAME :m_pGame->Exit(); break;}

// Zeit zurücksetzenm_fTime = 0.0f; // Stoppuhr auf null zurück, weil Zustand nicht mehr

aktiv

Page 14: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden SetGameState II// 2. Neuen Spielzustand ladenm_GameState = NewGameState; // Neuen Spielzustand initialisierenswitch (m_GameState) // Init-Methoden Aufruf für

entsprechenden Spielzustand{case GS_INTRO: r = m_pIntro->Init(); break;case GS_MAIN_MENU: r = m_pMainMenu->Init(); break;case GS_GAME: r = m_pGame->Init(); break;}

// Eventuelle Fehler abfangenif(r) TB_ERROR("Fehler beim Laden des Spielzustands!", TB_ERROR);

return TB_OK;}

Page 15: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Load I// Lädt das SpieltbResult CBreakanoid::Load() // lädt relevante Spiel-Daten{char acFilename[256];

// Direct3D initialisieren - Aufruf DirectX-Klassen der TriBase-Engine:

// Einstellungen des Konfig.Dialog liegen schon in m_Config (Header)

// IDI_ICON1 =Ressource, die Icon des Spiels enthält (zB. Spielszene)

if(tbDirect3D::Instance().Init(&m_Config, "Breakanoid", NULL, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)))){// Fehler!TB_ERROR("Fehler beim Initialisieren von Direct3D!", TB_ERROR);}

Page 16: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Load II[…]// DirectInput initialisierenif(tbDirectInput::Instance().Init())

// Speicher für die analogen Knöpfe reserviereng_pfButtons = new float

[tbDirectInput::Instance().GetNumButtons()]; // So viel Speicher für Array reserviert - wie analoge Knöpfe

g_pbButtons = new BOOL [tbDirectInput::Instance().GetNumButtons()];

// Und nun noch DirectSound...if(tbDirectSound::Instance().Init(&m_Config, NULL, DSSCL_PRIORITY,

FALSE))// FALSE, weil in dem Spiel kein 3D-Sound ist

{// Fehler!TB_ERROR("DirectSound konnte nicht initialisiert werden!",

TB_ERROR);}

Page 17: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Init I// Initialisiert das Spiel kompletttbResult CBreakanoid::Init(){tbResult r;

// TriBase-Engine initialisieren und den Konfigurationsdialog aufrufen:

if (tbInit()) return TB_ERROR;r = tbDoConfigDialog(&m_Config); //Konfigurationsdialog Aufruf &

abspeichern in m_Conig

//TB_CANCELED = wird von tbDoConfigDialog zurück geliefert, wenn Benutzer im Dialog auf ABRECHEN klickt

if(r == TB_CANCELED) return TB_CANCELED;else if(r) TB_ERROR("Engine konnte nicht initialisiert werden!",

r);

// Laden...if(Load()) TB_ERROR("Fehler beim Laden des Spiels!", TB_ERROR);

//Spieldaten laden durch LOAD Methoden Aufruf

Page 18: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Init II// Klassen für alle Spielzustände erstellen als Instanzen durch

NEWm_pIntro = new CIntro;m_pMainMenu = new CMainMenu;m_pGame = new CGame;

// Wir beginnen beim Intro!SetGameState(GS_INTRO); // SetGameState setzt Spielzustand aufs

Titelbild (Intro)

return TB_OK;}

Page 19: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Move I// Bewegt das SpieltbResult CBreakanoid::Move(float fTime) // liefert seit letztem Frame

vergangene Zeit in Sek.{tbResult r = TB_OK;

// Eingabegeräte abfragen. Wertet Eingabe des Benutzers aus + speichert

tbDirectInput::Instance().GetState(g_pfButtons, g_pbButtons);

[…]

// Aktuellen Spielzustand bewegenswitch(m_GameState) //ruft Move-Funktion für jeweilige Klasse auf{case GS_INTRO: r = m_pIntro->Move(fTime); break;case GS_MAIN_MENU: r = m_pMainMenu->Move(fTime); break;case GS_GAME: r = m_pGame->Move(fTime); break;}

Page 20: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Move II// Eventuelle Fehler abfangenif(r) TB_ERROR("Fehler beim Bewegen des Spielzustands!",

TB_ERROR);

// Frame-Zeit-Wert zu Zustand-Laufzeit-Stopuhr addierenm_fTime += fTime;

return TB_OK;}

Page 21: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Render// Rendert das SpieltbResult CBreakanoid::Render(float fTime){ […]// Aktuellen Spielzustand rendernswitch(m_GameState){case GS_INTRO: r = m_pIntro->Render(fTime); break;case GS_MAIN_MENU: r = m_pMainMenu->Render(fTime);

break;case GS_GAME: r = m_pGame->Render(fTime); break;}

// Eventuelle Fehler abfangenif(r) TB_ERROR("Fehler beim Rendern des Spielzustands!",

TB_ERROR);

return TB_OK;}

Page 22: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Methoden Run// Move- und Render-Funktion (Kapselung)tbResult Move(float fTime) {return g_pBreakanoid->Move(fTime);}tbResult Render(float fTime) {return g_pBreakanoid-

>Render(fTime);}

// Lässt das Spiel laufen tbResult CBreakanoid::Run(){// Nachrichtenschleife betreten. Ruft in jedem Frame Move und

Render aufif(tbDoMessageLoop(::Move, ::Render)){// Fehler!TB_ERROR("Fehler in der Nachrichtenschleife!", TB_ERROR);}

return TB_OK;}

Page 23: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

HauptfunktionWinMain I// Windows-Hauptfunktion int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char*

pcCommandLine, int iShowCommand){tbResult r;

// Spiel initialisiereng_pBreakanoid = new CBreakanoid;r = g_pBreakanoid->Init(); // Init-Funktionsaufruf

// Wenn Benutzer "ABBRECHEN" drückt = Programm beendenif(r == TB_CANCELED){

TB_SAFE_DELETE(g_pBreakanoid);return 0;

}// Wenn es nicht die Benutzereingabe war, handelt es sich um ein Fehlerelse if(r){

g_pBreakanoid->Exit();TB_SAFE_DELETE(g_pBreakanoid);MessageBox(NULL, "Fehler beim Initialisieren des Spiels!",

"Fehler", MB_OK | MB_ICONEXCLAMATION);return 1;}

Page 24: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

HauptfunktionWinMain II// Spiel laufen lassenif(g_pBreakanoid->Run()){g_pBreakanoid->Exit(); // Abfangen von Fehlern TB_SAFE_DELETE(g_pBreakanoid);MessageBox(NULL, "Fehler im Spiel!", "Fehler", MB_OK | MB_ICONEXCLAMATION);return 1;}

// Spiel verlasseng_pBreakanoid->Exit();TB_SAFE_DELETE(g_pBreakanoid);

return 0;}

Page 25: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

3.2 Das Titelbild

Page 26: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildCIntro// Intro.h// Klasse für das Introclass CIntro{public:// VariablenPDIRECT3DTEXTURE9 m_pTitle; // Titelbild-Textur

// Konstruktorinline CIntro(): m_pTitle(NULL){}

// MethodentbResult Init(); // Initialisierung = Betreten des SpielzustandstbResult Exit(); // Herunterfahren = Verlassen d. S. tbResult Load(); // Laden aller DatentbResult Unload(); // EntladentbResult Move(float fTime); // BewegentbResult Render(float fTime); // Rendern};

Page 27: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildDie Schrift// Load-Methode in Breakanoid.cpp// Schriftarten laden

m_pFont1 = new tbFont; // Schriftart 1

// Schrift besteht immer aus zwei Dateien -> liegen im Data-Ordner:

if(m_pFont1->Init("Data\\Font1.tga", "Data\\Font1.tbf")) {// Fehler!TB_ERROR("Fehler beim Laden der Schriftart Data\\Font1!",

TB_ERROR);}

[analog zu Schriftart 2]

Page 28: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildInitialisieren, Laden, Entladen //Intro.cpptbResult CIntro::Load() // Init ruft Load auf{// Titelbild laden (als Textur)m_pTitle = tbTextureManager::Instance().GetTexture("Data\\Title.jpg");if(m_pTitle == NULL)

TB_ERROR("Fehler beim Laden von Data\\Title.jpg!", TB_ERROR);

return TB_OK;}// __________________________________________________________________

tbResult CIntro::Unload() // Exit ruft Unload auf{// Die Textur löschentbTextureManager::Instance().ReleaseTexture(m_pTitle);

return TB_OK;}

Page 29: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildRendern I

//Intro.cpp// Vertizes für das Titelbildstruct STitleVertex{tbVector 3vPosition;float fRHW;D3DCOLOR Color;tbVector2 vTex0;static const DWORD dwFVF;};

const DWORD STitleVertex::dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;

Rendern erfolgt durch ein Rechteck, das mit der Textur des Bildes überzogen wird ‚Transformierte Vertizes‘

Page 30: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildRendern II// Rendert den SpielzustandtbResult CIntro::Render(float fTime){STitleVertex aVertex[4]; // 4 Vertizes, für jede Bildschirmecke ein

Vertex

// Puffer leeren und Szene beginnentbDirect3D& D3D = tbDirect3D::Instance();D3D->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, tbColor(0.0f,

0.0f, 0.0f), 1.0f, 0); D3D->BeginScene();

// ------------------------------------------------------------------

// Vertexformat und Titelbildtextur setzen, Z-Buffer ausD3D.SetFVF(STitleVertex::dwFVF);D3D.SetTexture(0, m_pTitle);D3D.SetRS(D3DRS_ZENABLE, D3DZB_FALSE);

Page 31: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildRendern III// Die vier Vertizes des Titelbilds erstellen (Rechteck)// Links untenaVertex[0].vPosition = tbVector3(0.0f, D3D.GetScreenSize().y,

0.5f); // Position der Pixelkoordinate

aVertex[0].fRHW = 1.0f; // Kehrwert der w-Koordinate

aVertex[0].Color = tbColor(1.0f, 0.8f, 0.8f);aVertex[0].vTex0 = tbVector2(0.0f, 1.0f); //

Texturkoordinate

// Links oben aVertex[1].vPosition = tbVector3(0.0f, 0.0f, 0.0f); aVertex[1].fRHW = 1.0f;aVertex[1].Color = tbColor(0.8f, 1.0f, 0.8f);aVertex[1].vTex0 = tbVector2(0.0f, 0.0f);

// ...andere genauso […]

Page 32: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildRendern IIII// Texturkoordinaten sinusförmig verschieben ("wabbeln")// Texturkoordinaten werden für jedes Vertex, in jedem frame

geändert:for(DWORD dwVertex = 0; dwVertex < 4; dwVertex++){

aVertex[dwVertex].vTex0.x += sinf(g_pBreakanoid->m_fTime + (float)(dwVertex)) * 0.01f;

aVertex[dwVertex].vTex0.y += cosf(g_pBreakanoid->m_fTime + (float)(dwVertex)) * 0.01f;

}

// Als Dreiecksfolge zeichnenD3D->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, aVertex,

sizeof(STitleVertex)); // Bild mit Trainlges-Trip zeichnen

[…]

Page 33: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das TitelbildMove// Bewegt den SpielzustandtbResult CIntro::Move(float fTime){// Wenn eine der typischen Tasten gedrückt wurde: zum Hauptmenü!// Prüft, ob Eingabe getätigt wurde. Akzeptierte Eingaben:if( g_pbButtons[TB_KEY_NUMPADENTER] || // ENTER g_pbButtons[TB_KEY_RETURN] || g_pbButtons[TB_KEY_SPACE] || // LEERTASTE g_pbButtons[TB_MOUSE_BUTTON(0)] || // MAUSTASTEN

g_pbButtons[TB_MOUSE_BUTTON(1)])

// gehe mit Verzögerung von 100 Millisek. zum Hauptmenü {

tbDelay(100);G_pBreakanoid->SetGameState(GS_MAIN_MENU);

}return TB_OK;}

Page 34: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

3.3 Das Hauptmenü

Page 35: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüVariablen// MainMenu.hclass CMainMenu{public:// VariablenLPDIRECT3DTEXTURE9 m_pBackground; // speichert HintergrundbildInt m_iCursor; // Menücursor = merkt

sichAusgewählten der 3 Einträge. [0]=erster.

BOOL m_bShowingHelp;// Wird Hilfetext angezeigt?

// Konstruktorinline CMainMenu(): m_pBackground(NULL), m_iCursor(0), m_bShowingHelp(FALSE) // bei TRUE (Cursor auf ‚Hilfe anzeigen‘):

// Menueinträge verschwindet + Hilfekasten wird angezeigt{}

Page 36: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüMethoden I CMainMenu::Init()

Betreten des Hauptmenüs ruft Load-Methode auf lädt nur die Textur des Hintergrundbildes Cursor auf null setzen damit zu Beginn erster Menüeintrag

ausgewählt ist CMainMenu::Exit()

Verlassen des Hauptmenüs ruft Unload auf löscht Textur aus Speicher

Page 37: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüRender I Rendern des Bildes wie bei Intro (‚wabbeln‘) Texte für 3 Menüeinträge zeichnen. Dafür gibt es ein Array mit drei

Einträgen:

tbResult CMainMenu::Render(float fTime){SBackgroundVertex aVertex[4];char* apcMenuEntry[3] = {"Spiel starten",

"Hilfe anzeigen", "Spiel beenden"};tbVector2 vPosition;tbColor Color;

[…]

Page 38: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüRender II If-Abfrage prüft, ob Hilfetext oder Menüeinträge gezeichnet werden

sollen

1. Position:if(!m_bShowingHelp)

{//jeden Text mit Schrifart 'g_pBreakanoid->m_pFont1' renderng_pBreakanoid->m_pFont1->Begin();

// Die Menüeinträge zeichnen. Jeder der 3 Einträg durchläuft Schleife

for(int iEntry = 0; iEntry < 3; iEntry++){// Die Position für den Text dieses Eintrags berechnenvPosition.x = 0.5f; // erster Menüeintrag liegt bei (0.5,

0.4) //jeden weiteren um 0.125 Einheiten nach unten

verschieben:vPosition.y = 0.4f + (float)(iEntry) * 0.125f;…

Page 39: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüRender III2. Bewegung:// Wenn der Cursor auf diesem Eintrag liegt, dann schwingt der Text// Wenn render-Eintrag = ausgewählter Eintrag -> dann schwingenif(m_iCursor == iEntry) vPosition.x += 0.05f * sinf(g_pBreakanoid->m_fTime);

3. Farbe berechnen:// Normalerweise ist Eintrag COLOR dunkelblau.// Wenn der Cursor aber darauf liegt, dann ist er heller.if(m_iCursor != iEntry) Color = tbColor(0.3f, 0.3f, 0.9f, 0.75f); //

Standardfarbe Blau...else Color = tbColor(0.5f, 0.5f, 1.0f, 1.0f); //... heller & transparenter

3. Text zeichnen:g_pBreakanoid->m_pFont1->DrawText(vPosition, apcMenuEntry[iEntry],

// es werden relative und zentrierte Koordinaten/Größen verwendet: TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_HCENTER | TB_FF_RELATIVE |

TB_FF_RELATIVESCALING, // Text wird mit 1,5 skaliert-1, Color, Color + tbColor(-0.3f, 0.4f, 0.0f), tbVector2(1.5f, 1.5f));

Page 40: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüMove I// Bewegt den SpielzustandtbResult CMainMenu::Move(float fTime){

if(!m_bShowingHelp) // Wenn showing Help = FALSE Pfeiltasten werden bewegt{// Wird Taste nach unten/oben gedrückt, wird Cursor durchs Hauptmenüs bewegt

if(g_pbButtons[TB_KEY_UP]) // Cursor nach unten bewegen{

m_iCursor--;tbDelay(80); // … mit Verzögerung

}if(g_pbButtons[TB_KEY_DOWN]) // Cursor nach oben bewegen

{m_iCursor++;tbDelay(80);

}// Cursor in die Grenzen weisen es gibt ja nur drei Menüpunkt zum Wählen [0,1,2]if(m_iCursor < 0) m_iCursor = 2;if(m_iCursor > 2) m_iCursor = 0; […]

Page 41: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüMove II// Wenn die Enter-, Leer- oder Return-Taste gedrückt wurde, // dann möchte der Benutzer einen Eintrag auswählen oder den Hilfetext wieder ausblenden.if(g_pbButtons[TB_KEY_RETURN] || g_pbButtons[TB_KEY_NUMPADENTER] || g_pbButtons[TB_KEY_SPACE]){

if(!m_bShowingHelp){// Nun kommt es darauf an, was gerade ausgewählt ist! // -> Wenn Hilfetext = FALSE, Cursor navigieren!

switch(m_iCursor){

case 0: // Spiel starteng_pBreakanoid->SetGameState(GS_GAME); // Spielzustand auf GS_GAME

setzenbreak;

case 1: // Hilfe anzeigenm_bShowingHelp = TRUE;tbDelay(100);break;

case 2: // Spiel beendenPostQuitMessage(0);break;

}}

Page 42: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüMove IIIelse // Ist Hilfetext = TRUE, dann abschalten

{// Die Hilfe wieder deaktivierenm_bShowingHelp = FALSE;tbDelay(100);

}[…]

Page 43: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüSound I Sorgt für Töne beim Bewegen u. Betätigen des Cursors tbDirectSound-Klasse in Breakanoid initialisert!

Breakanoid.h: Sound Array [12] es gibt 12 unterschiedliche Sounds

Breakanoid.cpp: Sounds werden in CBreakanoid::Load() geladen:

// Sounds ladenfor(DWORD s = 0; s < 12; s++){

sprintf(acFilename, "Data\\Sound%d.wav", s + 1);m_apSound[s] = new tbSound;if(m_apSound[s]->Init(acFilename, DSBCAPS_STATIC | DSBCAPS_LOCDEFER | DSBCAPS_CTRLFREQUENCY)){

// Fehler!TB_ERROR("Fehler beim Laden eines Sounds!", TB_ERROR);

}}

Page 44: Das erste Spiel Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation.

Das HauptmenüSound II MainMenu.cpp:

CMainMenu::Move spielt den Sound ab If-Abfrage: Verschieden Töne für versch. Eingaben:

// Sound Nr.1 beim Drücken UP/DOWN if(g_pbButtons[TB_KEY_UP]){

g_pBreakanoid->m_apSound[0]->PlayNextBuffer();m_iCursor--;tbDelay(80);

}if(g_pbButtons[TB_KEY_DOWN]) {

g_pBreakanoid->m_apSound[0]->PlayNextBuffer();m_iCursor++;tbDelay(80);

}