164 lines
5.9 KiB
C++
164 lines
5.9 KiB
C++
#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;
|
|
} |