diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..34a6e73 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 3.15) +project(ShapePatternGenerator VERSION 1.0 LANGUAGES CXX C) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_C_STANDARD 99) # Raylib is C, so C99 is a safe bet for it + +# --- Locating Raylib --- + +# Option 1: Using find_package (Preferred if Raylib is installed system-wide, via vcpkg, or CMAKE_PREFIX_PATH is set) +# This relies on Raylib providing a raylib-config.cmake or RaylibConfig.cmake. +# You might need to set CMAKE_PREFIX_PATH if Raylib is installed in a custom location. +# e.g., cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/raylib_install_dir +# Remove or adjust version number based on your Raylib installation. +find_package(raylib CONFIG) + +if (raylib_FOUND) + message(STATUS "Found Raylib version ${raylib_VERSION} using find_package.") + add_executable(ShapeGenerator main.cpp) + # Modern CMake uses an imported target like raylib::raylib if provided by Raylib's CMake config + target_link_libraries(ShapeGenerator PRIVATE raylib::raylib) +else() + message(WARNING "Raylib not found via find_package(raylib CONFIG).") + message(STATUS "Attempting to build Raylib from a subdirectory (if present)...") + + # Option 2: Add Raylib as a subdirectory (if you have the Raylib source code in a 'raylib' folder) + # Example: git submodule add https://github.com/raysan5/raylib.git raylib + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/raylib/CMakeLists.txt") + message(STATUS "Found Raylib source in 'raylib' subdirectory, adding it.") + + # Common Raylib build options (can be customized as needed) + set(BUILD_EXAMPLES OFF CACHE BOOL "Build Raylib examples" FORCE) + set(SUPPORT_MODULE_RSHAPES OFF CACHE BOOL "Build rshapes module" FORCE) # Keep build minimal + set(SUPPORT_MODULE_RTEXTURES OFF CACHE BOOL "Build rtextures module" FORCE) + # Add other SUPPORT_MODULE_* OFF if you want to slim down Raylib further + + add_subdirectory(raylib) # This will build Raylib along with your project + + add_executable(ShapeGenerator main.cpp) + # 'raylib' is the target name defined by Raylib's CMakeLists.txt when built as a subdirectory + target_link_libraries(ShapeGenerator PRIVATE raylib) + else() + message(FATAL_ERROR + "Raylib not found via find_package and no 'raylib' subdirectory with Raylib source found. " + "Please ensure Raylib is correctly installed and discoverable by CMake (e.g., set CMAKE_PREFIX_PATH), " + "or clone Raylib into a 'raylib' subdirectory of your project.") + endif() +endif() + +# Set the output directory for the executable (e.g., to the root of the build folder) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +# Optional: For some platforms/compilers, especially on Windows with GCC/Clang (MinGW), +# Raylib might require linking against specific system libraries. +# If using `find_package` with a proper Raylib CMake config or `add_subdirectory`, +# Raylib's own CMake script should handle these. This is just for troubleshooting. +# if (WIN32 AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) +# target_link_libraries(ShapeGenerator PRIVATE opengl32 gdi32 winmm shell32) +# endif() + +# --- Information for using Clang --- +# To use Clang, you can either: +# 1. Set environment variables before running CMake: +# export CC=clang +# export CXX=clang++ +# 2. Or specify the compilers when configuring CMake: +# cmake -S . -B build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ +# CMake will then use Clang for compilation. \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..45a6fc0 --- /dev/null +++ b/main.cpp @@ -0,0 +1,164 @@ +#include "raylib.h" +#include +#include // For rand(), srand() +#include // For time() +#include // For fmodf, sinf +#include // For std::min + +// Shape types +enum ShapeType { + SHAPE_CIRCLE, + SHAPE_RECTANGLE, + SHAPE_TRIANGLE +}; + +// Structure to hold shape properties +struct ShapeInfo { + ShapeType type; + Vector2 position; + float size; // Radius for circle, half-width for square, base for triangle + Color baseColor; + Color currentColor; + float hueShift; // For color animation + float timeAlive; // For other animations if needed +}; + +// --- Configuration --- +const int screenWidth = 1024; +const int screenHeight = 768; +const int gridSize = 12; // e.g., 12x12 grid +const float regenerationInterval = 7.0f; // Regenerate pattern every 7 seconds +const float colorAnimationSpeed = 30.0f; // Degrees of hue shift per second + +// --- Globals --- +std::vector shapes; +float patternTimer = 0.0f; +float cellWidth; +float cellHeight; + +// Function to generate/regenerate the pattern +void GeneratePattern() { + shapes.clear(); + if (shapes.capacity() < gridSize * gridSize) { + shapes.reserve(gridSize * gridSize); // Pre-allocate memory + } + + // Re-seed for different patterns each time (optional, could seed once at start for same sequence) + // srand(time(NULL)); // Moved to main to seed once for more deterministic sequence during one run if preferred + + cellWidth = (float)screenWidth / gridSize; + cellHeight = (float)screenHeight / gridSize; + + for (int y = 0; y < gridSize; ++y) { + for (int x = 0; x < gridSize; ++x) { + ShapeInfo s; + s.type = (ShapeType)(rand() % 3); // Random shape type + + // Center of the cell + float centerX = (x + 0.5f) * cellWidth; + float centerY = (y + 0.5f) * cellHeight; + s.position = { centerX, centerY }; + + // Base size, ensuring it fits well within the cell, with slight variation + float maxRadius = std::min(cellWidth, cellHeight) * 0.4f; // Max 40% of smaller cell dimension + s.size = maxRadius * (0.8f + (rand() % 41) / 100.0f); // 80% to 120% of maxRadius + + unsigned char r = rand() % 206 + 50; // Brighter colors + unsigned char g = rand() % 206 + 50; + unsigned char b = rand() % 206 + 50; + s.baseColor = { r, g, b, 255 }; + s.currentColor = s.baseColor; + s.hueShift = (float)(rand() % 360); // Start with a random hue shift + s.timeAlive = 0.0f; + + shapes.push_back(s); + } + } +} + +// Function to update shape properties (e.g., color animation) +void UpdateShapes(float deltaTime) { + for (auto& shape : shapes) { + shape.timeAlive += deltaTime; + + // Color animation: continuously shift hue + shape.hueShift = fmodf(shape.hueShift + colorAnimationSpeed * deltaTime, 360.0f); + + Vector3 hsvBase = ColorToHSV(shape.baseColor); + Vector3 hsvCurrent = hsvBase; + hsvCurrent.x = fmodf(hsvBase.x + shape.hueShift, 360.0f); + if (hsvCurrent.x < 0) hsvCurrent.x += 360.0f; // Ensure positive hue + + shape.currentColor = ColorFromHSV(hsvCurrent.x, hsvCurrent.y, hsvCurrent.z); + + // Example: Pulsating size for circles + // if (shape.type == SHAPE_CIRCLE) { + // float baseRadius = std::min(cellWidth, cellHeight) * 0.4f * (0.8f + (shape.baseColor.r % 41) / 100.0f); // re-get base for consistency + // shape.size = baseRadius * (1.0f + 0.1f * sinf(shape.timeAlive * 2.0f)); + // } + } +} + +// Main program loop +int main(void) { + srand(time(NULL)); // Seed random number generator once at the start + + InitWindow(screenWidth, screenHeight, "C++ Shape Pattern Generator - Raylib"); + SetTargetFPS(60); + + GeneratePattern(); // Initial pattern generation + + while (!WindowShouldClose()) { // Detect window close button or ESC key + float deltaTime = GetFrameTime(); + patternTimer += deltaTime; + + // Regenerate pattern periodically + if (patternTimer >= regenerationInterval) { + GeneratePattern(); + patternTimer = 0.0f; + } + + UpdateShapes(deltaTime); + + BeginDrawing(); + ClearBackground(BLACK); // Use a dark background for better contrast + + for (const auto& shape : shapes) { + switch (shape.type) { + case SHAPE_CIRCLE: + DrawCircleV(shape.position, shape.size, shape.currentColor); + break; + case SHAPE_RECTANGLE: + // Draw rectangle centered at shape.position + DrawRectangleRec( + { shape.position.x - shape.size, shape.position.y - shape.size, shape.size * 2, shape.size * 2 }, + shape.currentColor + ); + break; + case SHAPE_TRIANGLE: + // Draw an isosceles triangle pointing up + DrawTriangle( + { shape.position.x, shape.position.y - shape.size }, // Top point + { shape.position.x - shape.size * 0.866f, shape.position.y + shape.size * 0.5f }, // Bottom-left + { shape.position.x + shape.size * 0.866f, shape.position.y + shape.size * 0.5f }, // Bottom-right + shape.currentColor + ); + // A simpler triangle: + // DrawTriangle( + // { shape.position.x, shape.position.y - shape.size }, + // { shape.position.x - shape.size, shape.position.y + shape.size }, + // { shape.position.x + shape.size, shape.position.y + shape.size }, + // shape.currentColor); + break; + } + } + + DrawText("Shape Pattern Generator", 10, 10, 20, LIGHTGRAY); + DrawFPS(screenWidth - 90, 10); + + EndDrawing(); + } + + CloseWindow(); + return 0; +} \ No newline at end of file