Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung Medienwiss./Medieninformatik AM3 Visuelle Programmierung I Referent: Janek Rudolf.

Ähnliche Präsentationen


Präsentation zum Thema: "Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung Medienwiss./Medieninformatik AM3 Visuelle Programmierung I Referent: Janek Rudolf."—  Präsentation transkript:

1 Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung Medienwiss./Medieninformatik AM3 Visuelle Programmierung I Referent: Janek Rudolf

2 Schritt 5: Bälle hinzufügen Schritt 6: Die Blöcke Schritt 7: Versuche Schritt8: Punkte Schritt 9: Sound für das Spiel Schritt10: Hier spielt die Musik

3 Erstellung von Klasse CBall CGame werden 16 CBall-Variablen in einem Array hinzugefügt U.a. BOOL m_bExists, BOOL m_bGrabbed, tbVector3 m_vPosition, tbVector3 m_vVelocity

4 Bewegung durch Methode CBall:Move Fortbewegung des Balls: m_vVelocity x vergangene Zeit seit letztem Frame(CBall:Move) + m_vPosition

5 Ball kann mit Wand und Schläger kollidieren Radius des Ballmodells = 0.25 Kollision mit der Wand tritt ein wenn: x-Koordinate des Positionsvektor +/- 0.25 in oder hinter der Wand liegt. Rechts: x=9.25, Links: x=-9.25, z=4.25 Kollision mit dem Schläger tritt ein wenn: xBall >xSchläger-1.25 ^xBall<xSchläger +1.25^ zBall>zSchläger -0.25^zBall<zSchläger+0.25

6 Indem die z-Komponente des Geschwindigkeitsvektors umgekehrt wird, prallt der Ball ab

7 Ist m_vPosition <= -12, geht der Ball verloren Die Variable m_bExists wird auf FALSE gesetzt Im günstigsten Fall klebt danach ein neuer Ball auf dem Schläger Ist das der Fall, wird m_bGrabbed == TRUE und die move-Methode verlassen

8 // Bewegt einen Ball tbResult CBall::Move(float fTime) { // Wenn der Ball klebt: abbrechen! if(m_bGrabbed) return TB_OK; // Position verändern m_vPosition += m_vVelocity * fTime; // Wenn der Ball eine Wand berührt, prallt er ab. if(m_vPosition.x - 0.25f <= -9.25f) {bWall = TRUE; m_vVelocity.x *= -1.0f; m_vPosition.x = -9.0f;} // Linke Wand if(m_vPosition.x + 0.25f >= 9.25f) {bWall = TRUE; m_vVelocity.x *= -1.0f; m_vPosition.x = 9.0f;} // Rechte Wand if(m_vPosition.z + 0.25f >= 4.25f) {bWall = TRUE; m_vVelocity.z *= -1.0f; m_vPosition.z = 4.0f;} // Obere Wand // Auch am Schläger prallt er ab (Natürlich!). if(m_vPosition.x >= m_pGame->m_vPaddlePos.x - 1.25f && m_vPosition.x m_vPaddlePos.x + 1.25f && m_vPosition.z m_vPaddlePos.z + 0.25f && m_vPosition.z - m_vVelocity.z * fTime >= m_pGame->m_vPaddlePos.z + 0.25f) // Es gibt eine Kollision! Wir kehren die z-Komponente des Bewegungsvektors um. m_vVelocity.z *= -1.0f; if(m_vPosition.z < -12.0f) { m_bExists = FALSE; } }

9 Implementieren der Methode Cball::Render tbMatrixTranslation(GetAbsPosition()) verschiebt Ballmodell an richtige Stelle Absolute Position des Balls wird gebraucht in Translationsmatrix, sonst ist sie relativ zum Schläger CGame::m_pBallModel->Render rendert danach den Ball

10 Erster Ball bei Eintritt ins Level, Zero Memory leert Array m_aBall Erstellung eines Balls durch Methode CGame::CreateBall mit Parametern der Position, des Geschwindigkeitsvektors und dem Zustand, ob angeklebt oder nicht Erster Ball: Relative Position zum Schläger(0,0, 0,25), Geschwindigkeitsvektor (0,0,0) und Zustand = Angeklebt

11 Erstellung einer Liste in Form des Arrays CGame::m_aBall mit 16 Elementen Mit m_bExists prüfen ob/wie viele Bälle existieren CGame::Move geht die 16 Elemente durch, wenn die Elemente existieren, Aufruf seiner Move-Funktion und Aufruf von CBall::Render

12 // Erstellt einen neuen Ball int CGame::CreateBall(tbVector3 vPosition, tbVector3 vVelocity, BOOL bGrabbed) { // Freien Ball suchen for(int iBall = 0; iBall < 16; iBall++) { if(!m_aBall[iBall].m_bExists) { // Freier Ball gefunden! Ausfüllen! m_aBall[iBall].m_bExists = TRUE; m_aBall[iBall].m_pGame = this; m_aBall[iBall].m_bGrabbed = bGrabbed; m_aBall[iBall].m_vPosition = vPosition; m_aBall[iBall].m_vVelocity = vVelocity; // Index des neuen Balls liefern return iBall; } // Kein Platz mehr! return -1; }

13 // Wenn die Leertaste gedrückt wurde, wird der klebende Ball // abgeworfen. if(g_pbButtons[TB_KEY_SPACE] && m_aBall[0].m_bExists && m_aBall[0].m_bGrabbed) { // Sound abspielen g_pBreakanoid->m_apSound[3]->PlayNextBuffer(); // Ball abfeuern! m_aBall[0].m_bGrabbed = FALSE; // Die Position eines klebenden Balls ist immer relativ // zum Schläger. Wir wandeln sie nun in eine absolute Position um. m_aBall[0].m_vPosition += m_vPaddlePos;

14 // Den Bewegungsvektor des Balls berechnen wir zufällig. m_aBall[0].m_vVelocity.x = tbFloatRandom(-4.0f, 4.0f); m_aBall[0].m_vVelocity.y = 0.0f; m_aBall[0].m_vVelocity.z = tbFloatRandom(8.0f, 10.0f); // Den Bewegungsvektor des Schlägers addieren m_aBall[0].m_vVelocity += m_vPaddleVel; // Dem Ball einen kleinen "Schubs" nach vorne geben m_aBall[0].m_vPosition.z += 0.1f; }

15 Erstellen der Klasse CBlock mit der einzigen Methode Render Variablen : m_iEnergy: Anzahl Energiepunkte M_itype: Typ des Blocks (1 blau, 2 orange, 3 grün, 4 gelb) type= Anzahl Energiepunkte tbVector3 m_vPosition: Position des Blocks auf dem Spielfeld CGame* m_pGame: Kopie des CGame-Zeigers

16 Erstellen eines Arrays mit 64 CBlock-Elementen (wie bei den Bällen) ZeroMemory setzt bei betreten des Levels alle Blöcke zurück Level wird in Zeilen bzw. Strings unterteilt – Jedes Zeichen im String = ein Block 1 Zeile = 9 Zeichen/Blöcke - Mehrere Zeilen = Level Funktion CGame::CreateBlockRow um die Blockreihe zu erstellen

17 // Erstellt eine Reihe von Blöcken tbResult CGame::CreateBlockRow(char* pcBlocks, tbVector3 vStartPos) { int iType; // Alle Zeichen im String durchgehen for(DWORD dwChar = 0; dwChar < strlen(pcBlocks); dwChar++) { // Wenn das Zeichen kein Leerzeichen ist... if(pcBlocks[dwChar] != ' ') { // Freien Block suchen for(DWORD dwBlock = 0; dwBlock < 64; dwBlock++) { if(m_aBlock[dwBlock].m_iEnergy <= 0) { // Freier Block gefunden - ausfüllen! // Zeichen im String in einen Blocktyp umwandeln. iType = 0; if(pcBlocks[dwChar] == '1') iType = 1; else if(pcBlocks[dwChar] == '2') iType = 2; else if(pcBlocks[dwChar] == '3') iType = 3; else if(pcBlocks[dwChar] == '4') iType = 4;

18 // Je nach Level die Blöcke erstellen switch(iLevel) { case 1: CreateBlockRow(" 1 1 1 ", tbVector3(-8.0f, 0.0f, 2.0f)); CreateBlockRow("12 111 21", tbVector3(-8.0f, 0.0f, 1.0f)); CreateBlockRow("12 21", tbVector3(-8.0f, 0.0f, 0.0f)); CreateBlockRow(" 112 211 ", tbVector3(-8.0f, 0.0f, -1.0f)); break; case 2: CreateBlockRow(" 222 ", tbVector3(-8.0f, 0.0f, 1.0f)); CreateBlockRow(" 2 3 2 ", tbVector3(-8.0f, 0.0f, 0.0f)); CreateBlockRow(" 2 333 2 ", tbVector3(-8.0f, 0.0f, -1.0f)); CreateBlockRow("111111111", tbVector3(-8.0f, 0.0f, -2.0f)); break;

19 Prüfung in CBall::Move, ob Ball und Block kollidieren Ist das der Fall, wird dem Block ein EP abgezogen, der Ball prallt ab Problem: Welcher Block und welche Seite des Blocks wird getroffen x-oder z-Komponente des Geschwindigkeitsvektors umkehren

20 Zuerst Bedingung setzen, ob der Ball überhaupt mit dem Block kollidieren kann Danach berechnen, wo der Ball den Block trifft, dazu die Minimalste Distanz von den 4 Blöcken zum Ball berechnen

21 Bei links oder rechts vom Block, Vorzeichenveränderung der x-Komponente, Bei oben oder unten vom Block, Vorzeichenveränderung der z-Komponente nach Kollision, dem Ball einen Schub in die richtige Richtung geben

22 // Kollision mit den Blöcken berechnen for(DWORD dwBlock = 0; dwBlock < 64; dwBlock++) { if(m_pGame->m_aBlock[dwBlock].m_iEnergy > 0) { vBlock = m_pGame->m_aBlock[dwBlock].m_vPosition; // Befindet sich der Ball im Kollisionsbereich? if(m_vPosition.x + 0.25f >= vBlock.x - 1.0f && m_vPosition.x - 0.25f <= vBlock.x + 1.0f && m_vPosition.z + 0.25f >= vBlock.z - 0.5f && m_vPosition.z - 0.25f <= vBlock.z + 0.5f) // Entfernung des Balls von allen Blockseiten berechnen fDistLeft = fabsf(m_vPosition.x + 0.25f - (vBlock.x - 1.0f)); fDistRight = fabsf(m_vPosition.x - 0.25f - (vBlock.x + 1.0f)); fDistTop = fabsf(m_vPosition.z - 0.25f - (vBlock.z + 0.5f)); fDistBottom = fabsf(m_vPosition.z + 0.25f - (vBlock.z - 0.5f));

23 // Minimale Distanz berechnen fMinDist = TB_MIN(fDistLeft, TB_MIN(fDistRight, TB_MIN(fDistTop, fDistBottom))); // Wenn die Distanz zur linken oder rechten Seite am kleinsten ist... if(fMinDist == fDistLeft || fMinDist == fDistRight) { // Ball an der z-Achse abprallen lassen m_vVelocity.x *= -1.0f; // Dem Ball einen kleinen "Schubs" geben if(fMinDist == fDistLeft) m_vPosition.x -= 0.1f; else m_vPosition.x += 0.1f; } else { // Ball an der x-Achse abprallen lassen m_vVelocity.z *= -1.0f; // Dem Ball einen kleinen "Schubs" geben if(fMinDist == fDistTop) m_vPosition.z += 0.1f; else m_vPosition.z -= 0.1f; } // Dem Block einen Energiepunkt abziehen und Punkte addieren m_pGame->m_aBlock[dwBlock].m_iEnergy--; // Kollision ist immer nur mit einem einzigen Block möglich! break;

24 Wird ein Block zerstört (Energie =0), ermittelt tbIntRandom eine Zahl zwischen 1 und 14 Ist es eine 7, wird ein neuer Ball mit zufälliger Flugrichtung nach unten erstellt

25 Das Level ist geschafft, wenn alle Blöcke zerstört sind Dazu wird im m_aBlock-Array die Anzahl der Blöcke mit vorhandener Energie gezählt Sind alle Level geschafft, fängt der Spieler wieder bei Level 1 an

26 Variable CGame::m_iNumTries wird zu Beginn des Spiels auf 5 gesetzt In der Methode CGame:Move werden mit Hilfe einer for- Schleife die Bälle gezählt Ist die Anzahl der Bälle 0, so wird dem Spieler mit m_iTriesLeft- - ein Versuch abgezogen und ein neuer Ball auf den Schläger geklebt

27 Um das Spiel bei m_iTries == 0 zu beenden, hinzufügen der Variable BOOL m_bGameOver Bei TRUE wird in CGame::Render mit grüner und roter Schrift Game Over! ausgegeben

28 Um eine Punktzahl zu speichern, wurde bereits die Variable CGame::m_iScore erstellt Die vergangene Zeit eine Levels wird in der Variable CGame::m_fLevelTime gespeichert Umso weniger Zeit, desto mehr Punkte und pro Level 10000 Punkte extra Zudem 100 Punkte bei Treffen eines Blocks, 1000-4000 bei Zerstörung

29 // Level 1 bringt 10000 Punkte, Level 2 20000 Punkte usw.. m_iScore += m_iLevel * 10000; // Je weniger Zeit man gebraucht hat, desto mehr Extrapunkte gibt's. // Bei x benötigten Sekunden gibt es den x-ten Teil von 1000000 Punkten. m_iScore += (DWORD)(1000000.0f * (1.0f / m_fLevelTime)); // Dem Block einen Energiepunkt abziehen und Punkte addieren m_pGame->m_aBlock[dwBlock].m_iEnergy--; m_pGame->m_iScore += 100; // Wenn der Block zerstört wurde, gibt es Extrapunkte if(m_pGame->m_aBlock[dwBlock].m_iEnergy <= 0) { m_pGame->m_iScore += m_pGame- >m_aBlock[dwBlock].m_iType * 1000;

30 Da alle Sounds schon geladen wurden, geht es nur noch um das abspielen Die Sounds, die im Array CBreakanoid::m_apSound[11] gespeichert sind, werden gebraucht für: CBreakanoid::m_apSound[2]: neuen Level betreten CBreakanoid::m_apSound[3]: Ball abfeuern CBreakanoid::m_apSound[4]: Ball geht verloren CBreakanoid::m_apSound[5]: Ball trifft Schläger CBreakanoid::m_apSound[6]: Extraball-Sound CBreakanoid::m_apSound[7]: Ball prallt an Wand ab CBreakanoid::m_apSound[8-11]: Ball trifft Block, 4 verschiedene Sounds

31 Das Abspielen des Sounds funktioniert, indem man PlayNextBuffer auf der tbSound_klasse aufruft Wenn der Ball einen Block berührt, wird durch Zufallsgenerator einer von 4 Tönen abgespielt: // Zufälligen "Pling"-Sound abspielen iSound = tbIntRandom(8, 11); iBuffer = g_pBreakanoid->m_apSound[iSound]- >PlayNextBuffer(); if(iBuffer != -1)

32 Die Musik ist als MP3(MUSIC.MP3) gespeichert Musik wird die komplette Zeit unverändert abgespielt Dafür muss die Variable tbMusic* m_pMusic in der CBreakanoid –Klasse abgelegt werden

33 Geladen und abgespielt wird sie in CBreakanoid::Load // Musik laden und gleich abspielen m_pMusic = new tbMusic; if(m_pMusic->Init("Data\\Music.mp3")) { // Fehler! TB_ERROR("Fehler beim Laden der Musik!", TB_ERROR); } m_pMusic->Play(); return TB_OK;

34 Danke für eure Aufmerksamkeit!!!


Herunterladen ppt "Softwaretechnologie II (Teil 1): Simulation und 3D Programmierung Medienwiss./Medieninformatik AM3 Visuelle Programmierung I Referent: Janek Rudolf."

Ähnliche Präsentationen


Google-Anzeigen