diff --git a/src/main.cpp b/src/main.cpp index 62d0e34..72b4830 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include "gamematrix.h" #include #include +#include // Für ceil // ----------------------------------------------------------- // 3D Memory Game – Hauptprogramm @@ -9,7 +10,7 @@ int main() { // ===================================================================== - // 1) KLEINES MENÜFENSTER + // 1) KLEINES MENÜFENSTER (UNVERÄNDERT) // ===================================================================== InitWindow(400, 200, "Wuerfelspiel - Menu"); @@ -64,11 +65,6 @@ int main() CloseWindow(); // Menüfenster schließen - - - - - // ===================================================================== // 2) HAUPTSPIELFENSTER // ===================================================================== @@ -77,23 +73,31 @@ int main() InitWindow(800, 600, "3D Memory Game with Matrix3D Library"); SetTargetFPS(60); + // NEU: GameState Definition + enum class GameState + { + Idle, // kein Würfel offen, Eingabe erlaubt + OneFlipped, // ein Würfel offen + CheckingMatch, // zwei Würfel vollständig aufgeklappt, Vergleich läuft + LockInput // Würfel drehen gerade – Eingabe kurz blockiert + }; + + // NEU: GameState Initialisierung + GameState state = GameState::Idle; + // Anzahl Spielzüge -> wie oft wurde ein Wuerfel geklickt int turnCount = 0; // Startzeit für timer berechnung -> aktueller Zeitpunkt in Sekunden - time_t startTime = time(nullptr); + time_t startTime = time(nullptr); // gespielte Zeit - int playTime = 0; - - // anzahl an wuerfeln -> immer gerade anzahl und groeßer null -> jetzt nutzlos, weil menu window - //int numberOfCubes = 12; + int playTime = 0; // Zufall initialisieren srand(time(NULL)); Camera3D camera{}; - //camera.position = {6.0f, 6.0f, 6.0f}; // changed camera position to show all cubes if number very high camera.position = {12.0f, 9.0f, 12.0f}; camera.target = {0.0f, 0.0f, 0.0f}; camera.up = {0.0f, 1.0f, 0.0f}; @@ -103,15 +107,9 @@ int main() // Nur 3 Farben für 3 Paare Color colors[] = { RED, GREEN, BLUE }; - //==================================================================================== (alter comment) - // 6 Karten-Positionen im 3x2 Raster - //std::vector positions = {{-2, 0, -2}, {0, 0, -2}, {2, 0, -2}, - // {-2, 0, 0}, {0, 0, 0}, {2, 0, 0}}; - //==================================================================================== - - // Positionen bestimmen für dynamisches NumberOfCubes - std::vector positions; //noch leer, wird später befüllt in der schleife - int columns = ceil(sqrt(numberOfCubes)); + // Positionen bestimmen für dynamisches NumberOfCubes + std::vector positions; + int columns = ceil(sqrt(numberOfCubes)); int rows = ceil(numberOfCubes / (float)columns); float posi_x = 0; float posi_z = 0; @@ -126,7 +124,6 @@ int main() posi_z = 0; posi_x += 2;; } - // Farben doppelt in einen Pool legen und mischen @@ -134,14 +131,14 @@ int main() int numberOfPairs = numberOfCubes / 2; for (int i = 0; i < numberOfPairs; i++) { - colorPool.push_back(colors[i % 3]); // i % 3, weil nur 3 Farben zur Zeit im Pool sein können -> keine out of range exception + colorPool.push_back(colors[i % 3]); colorPool.push_back(colors[i % 3]); } // Fisher-Yates Shuffle mit rand() for (int i = colorPool.size() - 1; i > 0; --i) { - int j = rand() % (i + 1); // Zufallsindex von 0 bis i + int j = rand() % (i + 1); std::swap(colorPool[i], colorPool[j]); } @@ -163,47 +160,77 @@ int main() // die aktuelle Spielzeit berechnen if (!gameWon) { - playTime = static_cast(time(nullptr) - startTime); + playTime = static_cast(time(nullptr) - startTime); } - // Klick-Erkennung - if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + // Klick-Erkennung (ÜBERSCHRIEBEN durch GameState-Logik) + // Steuerung des Spielflusses: Nur im Idle- oder OneFlipped-Zustand wird reagiert! + if (!gameWon + && state != GameState::LockInput + && state != GameState::CheckingMatch + && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - turnCount++; Vector2 mouse = GetMousePosition(); for (auto &c : cubes) { - if (!c.IsFlipped() && !c.IsMatched()) + if (!c.IsFlipped() && !c.IsMatched()) // Ist verdeckt und nicht gematcht { Vector2 screenPos = GetWorldToScreen({c.GetPosition().x, c.GetPosition().y, c.GetPosition().z}, camera); if (fabs(mouse.x - screenPos.x) < 40 && fabs(mouse.y - screenPos.y) < 40) + { + // Klick verarbeitet, Würfel umdrehen c.FlipForward(); + turnCount++; + + // Zustandswechsel: + if (state == GameState::Idle) + { + state = GameState::OneFlipped; // 1. Klick → OneFlipped + first = &c; + break; // Verlasse die Schleife, da Klick verarbeitet + } + else if (state == GameState::OneFlipped) + { + // Sicherstellen, dass nicht derselbe Würfel geklickt wird + if (&c != first) + { + state = GameState::LockInput; // 2. Klick → Animation läuft, Eingabe sperren + second = &c; + break; // Verlasse die Schleife + } + } + } } } } + // Ende Klick-Erkennung // Animation aller Würfel for (auto &c : cubes) { c.Update(flipSpeed); + } - // Sobald ein Würfel vollständig umgedreht ist → merken - if (c.IsFlipped() && !c.IsMatched()) + // NEU: Zustandswechsel LockInput -> CheckingMatch + // Prüft, ob die Flip-Animationen abgeschlossen sind + if (state == GameState::LockInput && first && second) + { + // Warten auf das Ende der Umdreh-Animation. IsFlipped() prüft, ob der Würfel vollständig aufgedeckt ist. + if (first->IsFlipped() && second->IsFlipped()) // Änderung: !IsFlipping() ersetzt durch IsFlipped() { - if (!first) first = &c; - else if (!second && &c != first) second = &c; + state = GameState::CheckingMatch; } } - // Matching-Logik - if (first && second) + // Matching-Logik (ÜBERSCHRIEBEN und an GameState gekoppelt) + if (state == GameState::CheckingMatch && first && second) { - Color col1 = first->GetColor(); - Color col2 = second->GetColor(); - - if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b) + // Vergleichslogik der Aufgabe + if (first->GetColor().r == second->GetColor().r && + first->GetColor().g == second->GetColor().g && + first->GetColor().b == second->GetColor().b) { first->SetMatched(true); second->SetMatched(true); @@ -214,7 +241,9 @@ int main() second->FlipBackward(); } + // Rücksetzung und Zustandswechsel zu Idle first = second = nullptr; + state = GameState::Idle; } // Gewinnprüfung @@ -222,7 +251,7 @@ int main() gameWon = std::all_of(cubes.begin(), cubes.end(), [](const gamecube &c){ return c.IsMatched(); }); // ----------------------------------------------------------- - // Zeichnen + // Zeichnen (UNVERÄNDERT) // ----------------------------------------------------------- BeginDrawing(); ClearBackground(RAYWHITE); @@ -232,17 +261,17 @@ int main() c.Draw(); EndMode3D(); - + if (gameWon) { - DrawText("Congrats! You found all pairs!", 150, 260, 30, DARKBLUE); - DrawText(("TurnCount: " + std::to_string(turnCount)).c_str(), 150, 290, 20, DARKBLUE); + DrawText("Congrats! You found all pairs!", 150, 260, 30, DARKBLUE); + DrawText(("TurnCount: " + std::to_string(turnCount)).c_str(), 150, 290, 20, DARKBLUE); DrawText(("Seconds played: " + std::to_string(playTime)).c_str(), 150, 310, 20, DARKBLUE); } else { - DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY); - DrawText(("TurnCount: " + std::to_string(turnCount)).c_str(), 10, 30, 20, DARKGRAY); //Zeichne TurnCount + DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY); + DrawText(("TurnCount: " + std::to_string(turnCount)).c_str(), 10, 30, 20, DARKGRAY); //Zeichne TurnCount DrawText(("PlayTime: " + std::to_string(playTime)).c_str(), 10, 50, 20, DARKGRAY); //Zeichne Playtime } EndDrawing(); @@ -250,4 +279,4 @@ int main() CloseWindow(); return 0; -} +} \ No newline at end of file