diff --git a/.idea/editor.xml b/.idea/editor.xml
index 25c6c37..9fd2016 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -244,55 +244,61 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
@@ -300,11 +306,6 @@
-
-
-
-
-
@@ -316,29 +317,28 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b49ebf6..100e1c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,56 +1,84 @@
cmake_minimum_required(VERSION 3.28)
project(Prog3B)
+
set(EXECUTABLE_NAME Prog3B)
-# Generate compile_commands.json
+# -------------------------------------------------
+# Global settings
+# -------------------------------------------------
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
+# -------------------------------------------------
+# Main executable
+# -------------------------------------------------
set(SRC_FILES
src/main.cpp
src/gamecube.cpp
src/gamematrix.cpp
)
+
add_executable(${EXECUTABLE_NAME} ${SRC_FILES})
+
target_include_directories(${EXECUTABLE_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/includes
${CMAKE_CURRENT_LIST_DIR}/raylib
)
-
+# -------------------------------------------------
+# Tests executable
+# -------------------------------------------------
set(TEST_FILES
- src/tests.cpp
src/gamematrix.cpp
)
+
add_executable(tests ${TEST_FILES})
+
target_include_directories(tests PRIVATE
${CMAKE_CURRENT_LIST_DIR}/includes
)
-
-if(WIN32)
+# -------------------------------------------------
+# Platform specific linking
+# -------------------------------------------------
+if (WIN32)
message(STATUS "Configuring for Windows")
+
target_link_libraries(${EXECUTABLE_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/windows/libraylib.a
- opengl32 gdi32 winmm
+ opengl32
+ gdi32
+ winmm
)
-elseif(APPLE)
- message(STATUS "Configuring for MacOS")
+elseif (APPLE)
+
+ message(STATUS "Configuring for macOS")
target_link_libraries(${EXECUTABLE_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/mac_x86/libraylib.a
- "-framework IOKit"
"-framework Cocoa"
"-framework OpenGL"
+ "-framework IOKit"
)
-else()
- # --- Linux ---
+
+else ()
+
message(STATUS "Configuring for Linux")
+
target_link_libraries(${EXECUTABLE_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/linux/libraylib.a
- GL X11 m
+ GL
+ X11
+ m
+ pthread
+ dl
)
-endif()
\ No newline at end of file
+
+ target_link_libraries(tests PRIVATE
+ m
+ )
+
+endif ()
diff --git a/includes/gamecube.h b/includes/gamecube.h
index bbe0028..71cd8b6 100644
--- a/includes/gamecube.h
+++ b/includes/gamecube.h
@@ -31,4 +31,5 @@ private:
bool flippingForward = false;
bool flippingBackward = false;
float rotation = 0.0f;
-};
\ No newline at end of file
+};
+
diff --git a/src/main.cpp b/src/main.cpp
index 28bb190..80b8a77 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,6 +6,11 @@
//Ab Zeile 114 if game won
//Ab Zeile 148 checking match?
+
+// -----------------------------------------------------------
+// Initialisierung
+// -----------------------------------------------------------
+
void innitGame(int pairCount,
std::vector &cubes,
std::vector &positions )
@@ -68,8 +73,6 @@ void innitGame(int pairCount,
// -----------------------------------------------------------
int main()
{
-
-
//NEU Counter
int counter = 0;
@@ -91,7 +94,7 @@ int main()
// -------------------------------------------------------
// Spielvariablen
// -------------------------------------------------------
- // Nur 3 Farben für 3 Paare
+ // Nur 3 Farben für 3 Paare
int pairCount = 2; // <-- vorerst fixe Anzahl
std::vector positions;
std::vector cubes;
@@ -107,35 +110,48 @@ int main()
float flipSpeed = 5.0f; // Drehgeschwindigkeit
bool gameWon = false;
+ GameState state = GameState::Idle; //legen wir fest, in welchem Zustand das Spiel startet
+
// -----------------------------------------------------------
// Hauptspielschleife
// -----------------------------------------------------------
+
while (!WindowShouldClose())
{
- GameState state = GameState::Idle; //legen wir fest, in welchem Zustand das Spiel startet
+
// Klick-Erkennung
if (!gameWon
- //&& state != GameState::LockInput //nutzlos gerade
- //&& state != GameState::CheckingMatch //Nutzlos gerade
+ && (state == GameState::Idle || state == GameState::OneFlipped)
&& IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
// nur im Idle- oder OneFlipped-Zustand wird reagiert<-------------------------------------------------
//Wenn einer Dreht, clicken blockieren
// ...
- //Neu Counter
- counter++;
Vector2 mouse = GetMousePosition();
for (auto &c : cubes) //Hier die State Logik
{
std::cout<<("State missing");
- if (!c.IsFlipped() && !c.IsMatched())
+ if (!c.IsFlipped() && !c.IsMatched()) //<--------------- Zustandwechsel anpassen
{
- Vector2 screenPos = GetWorldToScreen({c.GetPosition().x, c.GetPosition().y, c.GetPosition().z}, camera);
+ 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)
+ if (fabs(mouse.x - screenPos.x) < 40 &&
+ fabs(mouse.y - screenPos.y) < 40)
+ {
c.FlipForward(); //<-----Animation Start
+ //Neu Counter
+ counter++;
+
+ if (state == GameState::Idle) //Neu (Ü4)
+ state = GameState::OneFlipped;
+ else
+ state = GameState::LockInput;
+
+ break; // 🔒 nur EIN Würfel pro Klick
+ }
}
}
}
@@ -148,8 +164,10 @@ int main()
// 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;
+ if (!first)
+ first = &c;
+ else if (!second && &c != first)
+ second = &c;
}
}
@@ -161,7 +179,9 @@ int main()
Color col1 = first->GetColor();
Color col2 = second->GetColor();
- if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b)
+ if (col1.r == col2.r &&
+ col1.g == col2.g &&
+ col1.b == col2.b)
{
first->SetMatched(true);
second->SetMatched(true);
@@ -174,9 +194,12 @@ int main()
first = second = nullptr;
+ state = GameState::Idle; //neu
}
- // Gewinnprüfung
+ // -----------------------------
+ // WIN CHECK
+ // -----------------------------
if (!gameWon)
gameWon = std::all_of(cubes.begin(), cubes.end(), [](const gamecube &c){ return c.IsMatched(); });
diff --git a/src/test.cpp b/src/test.cpp
new file mode 100644
index 0000000..9f43e03
--- /dev/null
+++ b/src/test.cpp
@@ -0,0 +1,211 @@
+//
+// Created by gamer on 14.12.2025.
+//
+#include "gamecube.h"
+#include
+#include
+#include
+
+// -----------------------------------------------------------
+// GameState – Zustandsmaschine
+// -----------------------------------------------------------
+enum class GameState
+{
+ Idle, // kein Würfel offen
+ OneFlipped, // ein Würfel offen
+ LockInput, // Animation läuft
+ CheckingMatch // Vergleich
+};
+
+// -----------------------------------------------------------
+// Initialisierung
+// -----------------------------------------------------------
+void innitGame(int pairCount,
+ std::vector &cubes,
+ std::vector &positions)
+{
+ cubes.clear();
+ positions.clear();
+
+ int total = pairCount * 2;
+ int cols = ceil(sqrt(total));
+ int rows = (total + cols - 1) / cols;
+ float spacing = 2.2f;
+
+ for (int r = 0; r < rows; r++)
+ for (int c = 0; c < cols; c++)
+ if ((int)positions.size() < total)
+ positions.push_back({
+ (c - cols / 2.0f) * spacing,
+ 0,
+ (r - rows / 2.0f) * spacing
+ });
+
+ std::vector colorPool;
+ for (int i = 0; i < pairCount; i++)
+ {
+ Color col = {
+ (unsigned char)(rand() % 256),
+ (unsigned char)(rand() % 256),
+ (unsigned char)(rand() % 256),
+ 255
+ };
+ colorPool.push_back(col);
+ colorPool.push_back(col);
+ }
+
+ for (int i = total - 1; i > 0; --i)
+ std::swap(colorPool[i], colorPool[rand() % (i + 1)]);
+
+ for (int i = 0; i < total; i++)
+ cubes.emplace_back(positions[i], colorPool[i]);
+}
+
+// -----------------------------------------------------------
+// MAIN
+// -----------------------------------------------------------
+int main()
+{
+ srand(time(NULL));
+ InitWindow(800, 600, "3D Memory Game – Stable Version");
+ SetTargetFPS(60);
+
+ Camera3D camera{};
+ camera.position = {6, 6, 6};
+ camera.target = {0, 0, 0};
+ camera.up = {0, 1, 0};
+ camera.fovy = 45;
+ camera.projection = CAMERA_PERSPECTIVE;
+
+ int pairCount = 2;
+ std::vector positions;
+ std::vector cubes;
+ innitGame(pairCount, cubes, positions);
+
+ gamecube *first = nullptr;
+ gamecube *second = nullptr;
+
+ float flipSpeed = 5.0f;
+ bool gameWon = false;
+ int counter = 0;
+
+ GameState state = GameState::Idle;
+
+ // -----------------------------------------------------------
+ // GAME LOOP
+ // -----------------------------------------------------------
+ while (!WindowShouldClose())
+ {
+ // -----------------------------
+ // INPUT (nur wenn erlaubt)
+ // -----------------------------
+ if (!gameWon &&
+ (state == GameState::Idle || state == GameState::OneFlipped) &&
+ 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();
+ counter++;
+
+ if (state == GameState::Idle)
+ state = GameState::OneFlipped;
+ else
+ state = GameState::LockInput;
+
+ break; // 🔒 nur EIN Würfel pro Klick
+ }
+ }
+ }
+ }
+
+ // -----------------------------
+ // UPDATE – Animation
+ // -----------------------------
+ for (auto &c : cubes)
+ {
+ c.Update(flipSpeed);
+
+ if (c.IsFlipped() && !c.IsMatched())
+ {
+ if (!first)
+ first = &c;
+ else if (!second && &c != first)
+ second = &c;
+ }
+ }
+
+ // -----------------------------
+ // Animation beendet → Vergleich
+ // -----------------------------
+ if (state == GameState::LockInput && first && second)
+ state = GameState::CheckingMatch;
+
+ // -----------------------------
+ // MATCHING
+ // -----------------------------
+ if (state == GameState::CheckingMatch)
+ {
+ Color a = first->GetColor();
+ Color b = second->GetColor();
+
+ if (a.r == b.r && a.g == b.g && a.b == b.b)
+ {
+ first->SetMatched(true);
+ second->SetMatched(true);
+ }
+ else
+ {
+ first->FlipBackward();
+ second->FlipBackward();
+ }
+
+ first = second = nullptr;
+ state = GameState::Idle;
+ }
+
+ // -----------------------------
+ // WIN CHECK
+ // -----------------------------
+ if (!gameWon)
+ gameWon = std::all_of(
+ cubes.begin(),
+ cubes.end(),
+ [](const gamecube &c)
+ { return c.IsMatched(); });
+
+ // -----------------------------
+ // DRAW
+ // -----------------------------
+ BeginDrawing();
+ ClearBackground(RAYWHITE);
+ BeginMode3D(camera);
+
+ for (auto &c : cubes)
+ c.Draw();
+
+ EndMode3D();
+
+ if (gameWon)
+ DrawText("Congrats! You found all pairs!", 140, 260, 30, DARKBLUE);
+ else
+ DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY);
+
+ DrawText(TextFormat("Moves: %i", counter / 2), 10, 40, 20, DARKGRAY);
+ EndDrawing();
+ }
+
+ CloseWindow();
+ return 0;
+}
diff --git a/src/testmain.cpp b/src/testmain.cpp
new file mode 100644
index 0000000..0e2ac11
--- /dev/null
+++ b/src/testmain.cpp
@@ -0,0 +1,163 @@
+#include "gamecube.h"
+#include
+#include
+//Funktion innitGame
+ //Anzahl der Paare(pairCount*2)
+void innitGame()
+{
+
+
+}
+// -----------------------------------------------------------
+// 3D Memory Game – Hauptprogramm
+// -----------------------------------------------------------
+int main()
+{
+
+
+ //NEU Counter
+ int counter = 0;
+
+
+ // 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 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 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 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))
+ {
+ //Neu Counter
+ counter++;
+
+ 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)
+ {
+ //counter hier macht umdrehungen
+
+ 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);
+ //Neu Counter
+ DrawText(TextFormat("Counter: %i",counter/2),10,40,20,DARKGRAY); //counter//2 da sonst doppelt
+
+ EndDrawing();
+ }
+
+ CloseWindow();
+ return 0;
+}
\ No newline at end of file
diff --git a/windows/libgamematrix.a b/windows/libgamematrix.a
new file mode 100644
index 0000000..8b4ca5a
Binary files /dev/null and b/windows/libgamematrix.a differ