This commit is contained in:
Tristan 2025-05-24 12:15:03 -04:00
parent 164de6704f
commit 8af3a803b2
3 changed files with 233 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

68
CMakeLists.txt Normal file
View File

@ -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.

164
main.cpp Normal file
View File

@ -0,0 +1,164 @@
#include "raylib.h"
#include <vector>
#include <cstdlib> // For rand(), srand()
#include <ctime> // For time()
#include <cmath> // For fmodf, sinf
#include <algorithm> // 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<ShapeInfo> 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;
}