240 likes | 330 Views
Breakanoid – Bälle & Blöcke. Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation und 3D Programmierung Prof. Dr. Manfred Thaller Referentin: Bianca Batel. Bälle hinzufügen Klasse CBall. Variablen :
E N D
Breakanoid – Bälle & Blöcke Universität zu Köln Historisch Kulturwissenschaftliche Informationsverarbeitung WS 12/13 Übung: Visuelle Programmierung I – Simulation und 3D Programmierung Prof. Dr. Manfred Thaller Referentin: Bianca Batel
Bälle hinzufügenKlasse CBall Variablen : • BOOL m_bExists • tbVector3 m_vPosition • tbVector3 m_vVelocity • BOOL m_bgrabbed • CGame* m_pGame Methoden: • tbResult Move(floatfTime) • tbResult Render(floatfTime) • tbVector3 GetAbsPosition() Ball.h
Bälle hinzufügen Bewegung - CBall::Move • Bewegung des Balls m_vPosition += m_vVelocity * fTime; • Ball trifft Wand 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 >= 9.25f) {bWall = TRUE; m_vVelocity.z *= -1.0f; m_vPosition.z = 4.0f;} //Obere Wand Ball.cpp
Bälle hinzufügen Bewegung - CBall::Move • Ball trifft Schläger • if(m_vPosition.x >= m_pGame->m_vPaddlePos.x - 1.25f && • m_vPosition.x <= m_pGame->m_vPaddlePos.x + 1.25f && • m_vPosition.z <= m_pGame->m_vPaddlePos.z + 0.25f && • m_vPosition.z - m_vVelocity.z * fTime >= m_pGame->m_vPaddlePos.z + 0.25f) Ball.h
Bälle hinzufügen Bewegung - CBall::Move // Es gibt eine Kollision! Wir kehren die z-Komponente des //Bewegungsvektors um. m_vVelocity.z *= -1.0f; // Die z-Koordinate des Balls korrigieren m_vPosition.z = m_pGame->m_vPaddlePos.z + 0.25f; // Die x-Komponente des Bewegungsvektors wird entgegengesetzt zum // Bewegungsvektor des Schlägers verändert. m_vVelocity.x -= m_pGame->m_vPaddleVel.x * 0.5f; Ball.cpp
Bälle hinzufügen Bewegung - CBall::Move • Fliegt am Schläger vorbei // Wenn er am Schläger vorbei fliegt, ist er //verloren. if(m_vPosition.z< -12.0f) { // … m_bExists = FALSE; } • Ball „klebt“ noch tbResultCBall::Move(floatfTime) { // Wenn der Ball klebt: abbrechen! if(m_bGrabbed) return TB_OK; //.. } Ball.cpp
Bälle hinzufügenRendern –CBall::Render, CBall::GetAbsPosition // Rendert einen Ball tbResultCBall::Render(floatfTime) { tbMatrixmWorld; // Ball rendern mWorld = tbMatrixTranslation(GetAbsPosition()); tbDirect3D::Instance().SetTransform(D3DTS_WORLD, mWorld); m_pGame->m_pBallModel->Render(); return TB_OK; } // Liefert die absolute Ballposition tbVector3 CBall::GetAbsPosition() { // Wenn der Ball klebt, dann müssen wir zu seiner Position // noch die Schlägerposition addieren. if(m_bGrabbed) return m_vPosition + m_pGame->m_vPaddlePos; elsereturnm_vPosition; } Ball.cpp
Bälle hinzufügenBall Array - CGame::CreateBall // Erstellt einen neuen Ball intCGame::CreateBall(tbVector3 vPosition, tbVector3 vVelocity, BOOL bGrabbed) { // Freien Ball suchen for(intiBall = 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; returniBall;// Index des neuen Balls liefern } } return -1; // Kein Platz mehr! } Game.cpp
Bälle hinzufügenDer erste Ball – CGame::InitLevel // Initialisiert einen Level tbResultCGame::InitLevel(intiLevel) { // ... // Bälle zurücksetzen ZeroMemory(m_aBall, 16 * sizeof(CBall)); // Einen Ball erstellen CreateBall(tbVector3(0.0f, 0.0f, 0.25f), tbVector3(0.0f), TRUE); // ... } Game.cpp
Bälle hinzufügenAbfeuern mit der Leertaste – CGame::Move // 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) { // 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; // 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; } Game.cpp
Eine neue Kamera – CGame::Render DWORD dwNumVectors; // Anzahl der Vektoren, die zum Mittelwert beitragen tbMatrixmCamera; // Die Kamera steht hinter und über dem Schläger. tbVector3 vCameraPos = m_vPaddlePos + tbVector3(0.0f, 10.0f, -5.0f); // Der Blickpunkt der Kamera ist der Mittelwert aus allen Ballpositionen // und der Schlägerposition. dwNumVectors = 1; tbVector3 vCameraLookAt = m_vPaddlePos; for(DWORD dwBall = 0; dwBall < 16; dwBall++) { if(m_aBall[dwBall].m_bExists) { dwNumVectors++; vCameraLookAt += m_aBall[dwBall].GetAbsPosition(); } } // Mittelwert bilden vCameraLookAt /= (float)(dwNumVectors); // Der Blickpunkt soll zur Mitte (0, 0, 0) hin tendieren. vCameraLookAt *= 0.5f; // Kameramatrix erstellen und aktivieren mCamera = tbMatrixCamera(vCameraPos, vCameraLookAt); tbDirect3D::Instance().SetTransform(D3DTS_VIEW, mCamera); Game.cpp
Blöcke hinzufügenKlasse CBlock Variablen : • intm_iEnergy; • intm_iType; • tbVector3m_vPosition; • CGame*m_pGame; Methoden: • tbResult Render(floatfTime); Block.h
Blöcke hinzufügenRendern – CBlock::Render // Rendert einen Block tbResultCBlock::Render(floatfTime) { tbMatrixmWorld; // Block rendern tbDirect3D::Instance().SetTransform(D3DTS_WORLD, tbMatrixTranslation(m_vPosition)); m_pGame->m_apBlockModel[m_iType - 1]->Render(); return TB_OK; } Ball.h
Blöcke hinzufügen - mehrere Blöcke CGame::CreateBlockRow(char* pcBlocks, tbVector3 vStartPos) Game.cpp • Blöcke hinzufügen • mehrere Blöcke - Levels von Breakanoid • CGame::InitLevel(intiLevel) Game.cpp
Kollision zwischen Ball und Block Ball.cpp • Multiball // Bei einem von fünfzehn Blöcken gibt es einen Extraball! if(tbIntRandom(0, 14) == 7) { // Neuen Ball erstellen, zufällige Flugrichtung nach unten m_pGame->CreateBall(m_vPosition, tbVector3(tbFloatRandom(-4.0f, 4.0f), 0.0f, -tbFloatRandom(8.0f, 10.0f)), FALSE); }
Level UpCGame::Move(floatfTime) DWORD dwNumBlocks; // Verbleibende Blöcke zählen dwNumBlocks = 0; for(DWORD dwBlock = 0; dwBlock < 64; dwBlock++) { if(m_aBlock[dwBlock].m_iEnergy > 0) dwNumBlocks++; } // Keine Blöcke mehr: neuer Level! if(dwNumBlocks == 0) { // Nächster Level! m_iLevel++; // Das Spiel hat kein Ende: Nach Level 8 geht's wieder bei 1 los. if(m_iLevel > 8) m_iLevel = 1; InitLevel(m_iLevel); tbDelay(100); } Game.cpp
VersucheBallverlust CGame::Move DWORD dwNumBalls; // Die Bälle bewegen und zählen dwNumBalls = 0; for(DWORD dwBall = 0; dwBall < 16; dwBall++) { // Den Ball bewegen und zählen, wenn er existiert if(m_aBall[dwBall].m_bExists) m_aBall[dwBall].Move(fTime), dwNumBalls++; } // Wenn kein Ball mehr im Spiel ist ... if(dwNumBalls == 0) { // Einen Versuch abziehen und wieder einen Ball ins Spiel bringen m_iTriesLeft--; CreateBall(tbVector3(0.0f, 0.0f, 0.25f), tbVector3(0.0f), TRUE); } Game.cpp
VersucheAnzeige CGame::Render characText[256]; g_pBreakanoid->m_pFont2->Begin(); // Levelnummer sprintf(acText, "Level %d", m_iLevel); g_pBreakanoid->m_pFont2->DrawText(tbVector2(0.05f, 0.05f), acText, TB_FF_RELATIVE | TB_FF_RELATIVESCALING, -1, tbColor(1.0f), tbColor(1.0f, 0.25f, 0.25f)); // Restliche Versuche sprintf(acText, "Versuche: %d", m_iTriesLeft); g_pBreakanoid->m_pFont2->DrawText(tbVector2(0.05f, 0.1f), acText, TB_FF_RELATIVE | TB_FF_RELATIVESCALING, -1, tbColor(1.0f), tbColor(0.25f, 1.0f, 0.25f)); g_pBreakanoid->m_pFont2->End(); Game.cpp
VersucheGame Over BOOL m_bGameOver // Wenn kein Ball mehr im Spiel ist ... if(dwNumBalls == 0) { // Wenn keine Versuche mehr übrig sind ... if(m_iTriesLeft == 0) { // Game Over! m_bGameOver = TRUE; } else { // Einen Versuch abziehen m_iTriesLeft--; // Wieder einen Ball ins Spiel bringen CreateBall(tbVector3(0.0f, 0.0f, 0.25f), tbVector3(0.0f), TRUE); } } Game.cpp
PunkteCGame::Move(floatfTime) // Keine Blöcke mehr: Extrapunkte und neuer Level! if(dwNumBlocks == 0) { // 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)); // Nächster Level! m_iLevel++; // Das Spiel hat kein Ende: Nach Level 8 geht's wieder bei 1 los. if(m_iLevel > 8) m_iLevel = 1; InitLevel(m_iLevel); tbDelay(100); } Game.cpp
Sound - Aktionen • CBreakanoid::m_apSound[2]: neuen Level betreten • CBreakanoid::m_apSound[3]: Ball abfeuern (mit Leertaste) • CBreakanoid::m_apSound[4]: Ball geht verloren • CBreakanoid::m_apSound[5]: Ball trifft den Schläger • CBreakanoid::m_apSound[6]: Extraball-Sound • CBreakanoid::m_apSound[7]: Ball prallt an der Wand ab • CBreakanoid::m_apSound[8 bis 11]: verschiedene glockenspielartige Musikinstrumente, von denen zufällig ein Sound abgespielt wird, wenn der Ball einen Block trifft Game.cpp
Musik – HintergrundCBreakanoid::Load() //… // Musik laden und gleich abspielen m_pMusic = newtbMusic; if(m_pMusic->Init("Data\\Music.mp3")) { // Fehler! TB_ERROR("Fehler beim Laden der Musik!", TB_ERROR); } m_pMusic->Play(); //… Breakanoid.cpp
Minimieren im VollbildmodusCBreakanoid::Render(floatfTime) Breakanoid.cpp MotionBlurringCBall::Render(floatfTime) Ball.cpp Erweiterungsvorschläge…