Prog3b_651/src/main.cpp

442 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "gamecube.h"
#include <algorithm>
#include <ctime>
#include <vector>
#include "raylib.h" // Stellen Sie sicher, dass raylib.h hier oder in gamecube.h inkludiert ist
// -----------------------------------------------------------
// 3D Memory Game Hauptprogramm
// -----------------------------------------------------------
enum GameScreen {MENU = 0, GAMEPLAY};
void SetupGame(std::vector<gamecube>& cubes, int pairs)
{
cubes.clear();
Color colors[] = {RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, WHITE, SKYBLUE};
std::vector<Vec3> positions;
int count = pairs * 2;
int cols = 3;
int rows = 2;
if (count > 6) {
cols = 4;
rows = 3;
}
int index = 0;
// Generiert Positionen basierend auf der Größe
for (int r = 0; r < rows && index < count; ++r) {
for (int c = 0; c < cols && index < count; ++c) {
// Zentriert die Würfel um (0,0,0)
positions.push_back({(float)c * 2.0f - (cols -1 ), 0.0f, (float)r * 2.0f - (rows -1)});
index++;
}
}
std::vector<Color> colorPool;
for (int i = 0; i < pairs; i++) {
colorPool.push_back(colors[i]);
colorPool.push_back(colors[i]);
}
// Fisher-Yates Shuffle
for (int i= colorPool.size() -1; i > 0; --i) {
int j = rand() % (i + 1);
std::swap(colorPool[i], colorPool[j]);
}
// Würfel erstellen
for (int i = 0; i < count; i++)
cubes.emplace_back(positions[i], colorPool[i]);
}
int main()
{
// Zufall initialisieren#include "gamecube.h"
//#include <algorithm>
//#include <ctime>
//
//// -----------------------------------------------------------
//// 3D Memory Game Hauptprogramm
//// -----------------------------------------------------------
//int main()
//{
// // Zufall initialisieren
// srand(time(NULL));
//
// // Fenster und Kamera
// InitWindow(800, 600, "3D Memory Game with Matrix3D Library");
// SetTargetFPS(60);
//
// Camera3D camera{};
// camera.position = {6.0f, 6.0f, 6.0f};
// camera.target = {0.0f, 0.0f, 0.0f};
// camera.up = {0.0f, 1.0f, 0.0f};
// camera.fovy = 45.0f;
// camera.projection = CAMERA_PERSPECTIVE;
//
// // Nur 3 Farben für 3 Paare
// Color colors[] = { RED, GREEN, BLUE };
//
// // 6 Karten-Positionen im 3x2 Raster
// std::vector<Vec3> positions = {{-2, 0, -2}, {0, 0, -2}, {2, 0, -2},{-2, 0, 0}, {0, 0, 0}, {2, 0, 0}};
//
// // Farben doppelt in einen Pool legen und mischen
// std::vector<Color> colorPool;
// for (int i = 0; i < 3; i++)
// {
// colorPool.push_back(colors[i]);
// colorPool.push_back(colors[i]);
// }
//
// // Fisher-Yates Shuffle mit rand()
// for (int i = colorPool.size() - 1; i > 0; --i)
// {
// int j = rand() % (i + 1); // Zufallsindex von 0 bis i
// std::swap(colorPool[i], colorPool[j]);
// }
//
// // Karten/Würfel erstellen
// std::vector<gamecube> cubes;
// for (int i = 0; i < 6; i++)
// cubes.emplace_back(positions[i], colorPool[i]);
//
// gamecube* first = nullptr;
// gamecube* second = nullptr;
// float flipSpeed = 5.0f; // Drehgeschwindigkeit
// bool gameWon = false;
//
// // -----------------------------------------------------------
// // Hauptspielschleife
// // -----------------------------------------------------------
// while (!WindowShouldClose())
// {
// // Klick-Erkennung
// if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
// {
// Vector2 mouse = GetMousePosition();
//
// for (auto &c : cubes)
// {
// if (!c.IsFlipped() && !c.IsMatched())
// {
// 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)
// c.FlipForward();
// }
// }
// }
//
// // 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())
// {
// if (!first) first = &c;
// else if (!second && &c != first) second = &c;
// }
// }
//
// // Matching-Logik
// if (first && second)
// {
// Color col1 = first->GetColor();
// Color col2 = second->GetColor();
//
// if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b)
// {
// first->SetMatched(true);
// second->SetMatched(true);
// }
// else
// {
// first->FlipBackward();
// second->FlipBackward();
// }
//
// first = second = nullptr;
// }
//
// // Gewinnprüfung
// if (!gameWon)
// gameWon = std::all_of(cubes.begin(), cubes.end(), [](const gamecube &c){ return c.IsMatched(); });
//
// // -----------------------------------------------------------
// // Zeichnen
// // -----------------------------------------------------------
// BeginDrawing();
// ClearBackground(RAYWHITE);
// BeginMode3D(camera);
//
// for (auto &c : cubes)
// c.Draw();
//
// EndMode3D();
//
// if (gameWon)
// DrawText("Congrats! You found all pairs!", 150, 260, 30, DARKBLUE);
// else
// DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY);
//
// EndDrawing();
// }
//
// CloseWindow();
// return 0;
//}
srand(time(NULL));
double startTime = 0.0;
double endTime = 0.0;
bool timerStarted = false;
GameScreen currentScreen = MENU;
int selectedPairs = 3;
// 1. SPIELSPEZIFISCHE VARIABLEN HIER DEKLARIEREN (ohne Initialisierung)
std::vector<gamecube> cubes;
gamecube* first = nullptr;
gamecube* second = nullptr;
float flipSpeed = 5.0f; // Drehgeschwindigkeit
bool gameWon = false;
int moves = 0;
// Fenster und Kamera
InitWindow(800, 600, "3D Memory Game with Matrix3D Library");
SetTargetFPS(60);
Camera3D camera{};
camera.position = {6.0f, 6.0f, 6.0f};
camera.target = {0.0f, 0.0f, 0.0f};
camera.up = {0.0f, 1.0f, 0.0f};
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
// -----------------------------------------------------------
// Hauptspielschleife
// -----------------------------------------------------------
while (!WindowShouldClose())
{
// -------------------------------------------------------
// UPDATE-LOGIK NACH ZUSTAND
// -------------------------------------------------------
switch (currentScreen)
{
case MENU:
{
// Menü-Abfrage: Auf Tastendruck warten
if (IsKeyPressed(KEY_THREE)) {
selectedPairs = 3; // 6 Würfel
SetupGame(cubes, selectedPairs);
gameWon = false;
first = second = nullptr;
currentScreen = GAMEPLAY;
timerStarted = false; // Timer-Reset
moves = 0;
} else if (IsKeyPressed(KEY_SIX)) {
selectedPairs = 6; // 12 Würfel
SetupGame(cubes, selectedPairs);
gameWon = false;
first = second = nullptr;
currentScreen = GAMEPLAY;
timerStarted = false; // Timer-Reset
moves = 0;
}
break;
}
case GAMEPLAY:
{
// Timer starten
if (!timerStarted)
{
startTime = GetTime();
timerStarted = true;
}
// Klick-Erkennung
<<<<<<< HEAD
if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
Vector2 mouse = GetMousePosition();
for (auto &c : cubes)
{
if (!c.IsFlipped() && !c.IsMatched())
{
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)
c.FlipForward();
=======
// Klick-Erkennung (nur wenn noch nicht 2 ausgewählt sind)
if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (second == nullptr))
{
Vector2 mouse = GetMousePosition();
Ray ray = GetMouseRay(mouse, camera);
gamecube* hitCube = nullptr;
float bestDist = 1e9f;
for (auto &c : cubes)
{
if (c.IsMatched() || c.IsFlipped()) continue;
auto p = c.GetPosition();
BoundingBox box;
box.min = { p.x - 0.75f, p.y - 0.75f, p.z - 0.75f };
box.max = { p.x + 0.75f, p.y + 0.75f, p.z + 0.75f };
RayCollision col = GetRayCollisionBox(ray, box);
if (col.hit && col.distance < bestDist)
{
bestDist = col.distance;
hitCube = &c;
}
}
if (hitCube)
{
if (!first)
{
first = hitCube;
first->FlipForward();
}
else if (hitCube != first)
{
second = hitCube;
second->FlipForward();
>>>>>>> 5fc4346 (funktioniert, 3 oder 6 + Timer komplett)
}
}
}
// Animation aller Würfel
for (auto &c : cubes)
{
c.Update(flipSpeed);
<<<<<<< HEAD
if (c.IsFlipped() && !c.IsMatched())
{
if (!first) first = &c;
else if (!second && &c != first) second = &c;
}
}
// Matching-Logik
if (first && second)
=======
}
// Matching-Logik
// Matching-Logik: erst wenn beide vollständig umgedreht sind
if (first && second && first->IsFlipped() && second->IsFlipped())
>>>>>>> 5fc4346 (funktioniert, 3 oder 6 + Timer komplett)
{
moves++;
Color col1 = first->GetColor();
Color col2 = second->GetColor();
if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b)
{
first->SetMatched(true);
second->SetMatched(true);
}
else
{
first->FlipBackward();
second->FlipBackward();
}
<<<<<<< HEAD
first = second = nullptr;
=======
first = nullptr;
second = nullptr;
>>>>>>> 5fc4346 (funktioniert, 3 oder 6 + Timer komplett)
}
// Gewinnprüfung
if (!gameWon)
{
// Prüft, ob ALLE Würfel gematcht sind
gameWon = std::all_of(cubes.begin(), cubes.end(), [](const gamecube &c){ return c.IsMatched(); });
if (gameWon)
{
endTime = GetTime() - startTime;
}
}
break;
} // ENDE GAMEPLAY UPDATE
}
// -----------------------------------------------------------
// ZEICHNEN NACH ZUSTAND
// -----------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
switch (currentScreen)
{
case MENU:
{
// Menü-Darstellung
DrawText("3D MEMORY SPIEL", GetScreenWidth() / 2 - MeasureText("3D MEMORY SPIEL", 50) / 2, 80, 50, DARKGRAY);
DrawText("Waehlen Sie die Spielgroesse:", 50, 200, 25, BLACK);
DrawText("Druecken Sie [3] fuer 3 Paare (6 Wuerfel)", 50, 240, 20, BLUE);
DrawText("Druecken Sie [6] fuer 6 Paare (12 Wuerfel)", 50, 280, 20, BLUE);
break;
}
case GAMEPLAY:
{
// Spiel-Darstellung
BeginMode3D(camera);
for (auto &c : cubes)
c.Draw();
EndMode3D();
if (gameWon)
{
DrawText("Congrats! You found all pairs!", 150, 260, 30, DARKBLUE);
char buffer[64];
sprintf(buffer, "Cleared in %.2f seconds", endTime);
DrawText(buffer, 150, 300, 28, DARKGREEN);
}
else
{
DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY);
char liveBuf[64];
sprintf(liveBuf, "Time: %.2f", GetTime() - startTime);
DrawText(liveBuf, 10, 40, 20, DARKGRAY);
char moveBuf[64];
snprintf(moveBuf, sizeof(moveBuf), "Moves: %d", moves);
DrawText(moveBuf, 10, 70, 20, DARKGRAY);
}
break;
} // ENDE GAMEPLAY DRAW
}
EndDrawing();
}
CloseWindow();
return 0;
}