|
@@ -16,14 +16,18 @@
|
|
|
*
|
|
*
|
|
|
********************************************************************************************/
|
|
********************************************************************************************/
|
|
|
|
|
|
|
|
|
|
+#include "raylib.h"
|
|
|
|
|
+
|
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
#include <string.h>
|
|
|
#include <math.h>
|
|
#include <math.h>
|
|
|
-#include "raylib.h"
|
|
|
|
|
|
|
|
|
|
-#define STR_MAX_SIZE 10000
|
|
|
|
|
-#define TURTLE_STACK_MAX_SIZE 50
|
|
|
|
|
|
|
+#define STR_MAX_SIZE 10000
|
|
|
|
|
+#define TURTLE_STACK_MAX_SIZE 50
|
|
|
|
|
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+// Types and Structures Definition
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
typedef struct TurtleState {
|
|
typedef struct TurtleState {
|
|
|
Vector2 origin;
|
|
Vector2 origin;
|
|
|
double angle;
|
|
double angle;
|
|
@@ -40,32 +44,111 @@ typedef struct PenroseLSystem {
|
|
|
float theta;
|
|
float theta;
|
|
|
} PenroseLSystem;
|
|
} PenroseLSystem;
|
|
|
|
|
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+// Global Variables Definition
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
static TurtleState turtleStack[TURTLE_STACK_MAX_SIZE];
|
|
static TurtleState turtleStack[TURTLE_STACK_MAX_SIZE];
|
|
|
static int turtleTop = -1;
|
|
static int turtleTop = -1;
|
|
|
|
|
|
|
|
-void PushTurtleState(TurtleState state)
|
|
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+// Module Functions Declaration
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+static void PushTurtleState(TurtleState state);
|
|
|
|
|
+static TurtleState PopTurtleState(void);
|
|
|
|
|
+static PenroseLSystem CreatePenroseLSystem(float drawLength);
|
|
|
|
|
+static void BuildProductionStep(PenroseLSystem *ls);
|
|
|
|
|
+static void BuildPenroseLSystem(PenroseLSystem *ls, float drawLength, int generations);
|
|
|
|
|
+static void DrawPenroseLSystem(PenroseLSystem *ls);
|
|
|
|
|
+
|
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
|
+// Program main entry point
|
|
|
|
|
+//------------------------------------------------------------------------------------
|
|
|
|
|
+int main(void)
|
|
|
{
|
|
{
|
|
|
- if (turtleTop < TURTLE_STACK_MAX_SIZE - 1)
|
|
|
|
|
- {
|
|
|
|
|
- turtleStack[++turtleTop] = state;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
|
|
+ // Initialization
|
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
|
+ const int screenWidth = 800;
|
|
|
|
|
+ const int screenHeight = 450;
|
|
|
|
|
+
|
|
|
|
|
+ SetConfigFlags(FLAG_MSAA_4X_HINT);
|
|
|
|
|
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - penrose tile");
|
|
|
|
|
+
|
|
|
|
|
+ float drawLength = 460.0f;
|
|
|
|
|
+ int minGenerations = 0;
|
|
|
|
|
+ int maxGenerations = 4;
|
|
|
|
|
+ int generations = 0;
|
|
|
|
|
+
|
|
|
|
|
+ PenroseLSystem ls = {0};
|
|
|
|
|
+ BuildPenroseLSystem(&ls, drawLength*(generations/(float)maxGenerations), generations);
|
|
|
|
|
+
|
|
|
|
|
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
|
|
|
|
+ //---------------------------------------------------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+ // Main game loop
|
|
|
|
|
+ while (!WindowShouldClose()) // Detect window close button or ESC key
|
|
|
{
|
|
{
|
|
|
- TraceLog(LOG_WARNING, "TURTLE STACK OVERFLOW!");
|
|
|
|
|
|
|
+ // Update
|
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
|
+ bool rebuild = false;
|
|
|
|
|
+ if (IsKeyPressed(KEY_UP))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (generations < maxGenerations)
|
|
|
|
|
+ {
|
|
|
|
|
+ generations++;
|
|
|
|
|
+ rebuild = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (IsKeyPressed(KEY_DOWN))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (generations > minGenerations)
|
|
|
|
|
+ {
|
|
|
|
|
+ generations--;
|
|
|
|
|
+ if (generations > 0) rebuild = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (rebuild) BuildPenroseLSystem(&ls, drawLength*(generations/(float)maxGenerations), generations);
|
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+ // Draw
|
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
|
|
+ BeginDrawing();
|
|
|
|
|
+
|
|
|
|
|
+ ClearBackground( RAYWHITE );
|
|
|
|
|
+
|
|
|
|
|
+ if (generations > 0) DrawPenroseLSystem(&ls);
|
|
|
|
|
+
|
|
|
|
|
+ DrawText("penrose l-system", 10, 10, 20, DARKGRAY);
|
|
|
|
|
+ DrawText("press up or down to change generations", 10, 30, 20, DARKGRAY);
|
|
|
|
|
+ DrawText(TextFormat("generations: %d", generations), 10, 50, 20, DARKGRAY);
|
|
|
|
|
+
|
|
|
|
|
+ EndDrawing();
|
|
|
|
|
+ //----------------------------------------------------------------------------------
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // De-Initialization
|
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
|
+ CloseWindow(); // Close window and OpenGL context
|
|
|
|
|
+ //--------------------------------------------------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+// Module Functions Definition
|
|
|
|
|
+//----------------------------------------------------------------------------------
|
|
|
|
|
+void PushTurtleState(TurtleState state)
|
|
|
|
|
+{
|
|
|
|
|
+ if (turtleTop < (TURTLE_STACK_MAX_SIZE - 1)) turtleStack[++turtleTop] = state;
|
|
|
|
|
+ else TraceLog(LOG_WARNING, "TURTLE STACK OVERFLOW!");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
TurtleState PopTurtleState(void)
|
|
TurtleState PopTurtleState(void)
|
|
|
{
|
|
{
|
|
|
- if (turtleTop >= 0)
|
|
|
|
|
- {
|
|
|
|
|
- return turtleStack[turtleTop--];
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
|
|
|
|
|
- }
|
|
|
|
|
- return (TurtleState) {0};
|
|
|
|
|
|
|
+ if (turtleTop >= 0) return turtleStack[turtleTop--];
|
|
|
|
|
+ else TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
|
|
|
|
|
+
|
|
|
|
|
+ return (TurtleState){ 0 };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PenroseLSystem CreatePenroseLSystem(float drawLength)
|
|
PenroseLSystem CreatePenroseLSystem(float drawLength)
|
|
@@ -77,86 +160,19 @@ PenroseLSystem CreatePenroseLSystem(float drawLength)
|
|
|
.ruleY = "-WF++XF[+++YF++ZF]-",
|
|
.ruleY = "-WF++XF[+++YF++ZF]-",
|
|
|
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
|
|
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
|
|
|
.drawLength = drawLength,
|
|
.drawLength = drawLength,
|
|
|
- .theta = 36.0f // in degrees
|
|
|
|
|
|
|
+ .theta = 36.0f // Degrees
|
|
|
};
|
|
};
|
|
|
- ls.production = (char*) malloc(sizeof(char) * STR_MAX_SIZE);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ ls.production = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
|
|
ls.production[0] = '\0';
|
|
ls.production[0] = '\0';
|
|
|
strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE);
|
|
strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE);
|
|
|
- return ls;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void DrawPenroseLSystem(PenroseLSystem *ls)
|
|
|
|
|
-{
|
|
|
|
|
- Vector2 screenCenter = {GetScreenWidth()/2, GetScreenHeight()/2};
|
|
|
|
|
-
|
|
|
|
|
- TurtleState turtle = {
|
|
|
|
|
- .origin = {0},
|
|
|
|
|
- .angle = -90.0f
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- int repeats = 1;
|
|
|
|
|
- int productionLength = (int) strnlen(ls->production, STR_MAX_SIZE);
|
|
|
|
|
- ls->steps += 12;
|
|
|
|
|
-
|
|
|
|
|
- if (ls->steps > productionLength)
|
|
|
|
|
- {
|
|
|
|
|
- ls->steps = productionLength;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- for (int i = 0; i < ls->steps; i++)
|
|
|
|
|
- {
|
|
|
|
|
- char step = ls->production[i];
|
|
|
|
|
- if ( step == 'F' )
|
|
|
|
|
- {
|
|
|
|
|
- for ( int j = 0; j < repeats; j++ )
|
|
|
|
|
- {
|
|
|
|
|
- Vector2 startPosWorld = turtle.origin;
|
|
|
|
|
- float radAngle = DEG2RAD * turtle.angle;
|
|
|
|
|
- turtle.origin.x += ls->drawLength * cosf(radAngle);
|
|
|
|
|
- turtle.origin.y += ls->drawLength * sinf(radAngle);
|
|
|
|
|
- Vector2 startPosScreen = {startPosWorld.x + screenCenter.x, startPosWorld.y + screenCenter.y};
|
|
|
|
|
- Vector2 endPosScreen = {turtle.origin.x + screenCenter.x, turtle.origin.y + screenCenter.y};
|
|
|
|
|
- DrawLineEx(startPosScreen, endPosScreen, 2, Fade(BLACK, 0.2));
|
|
|
|
|
- }
|
|
|
|
|
- repeats = 1;
|
|
|
|
|
- }
|
|
|
|
|
- else if ( step == '+' )
|
|
|
|
|
- {
|
|
|
|
|
- for ( int j = 0; j < repeats; j++ )
|
|
|
|
|
- {
|
|
|
|
|
- turtle.angle += ls->theta;
|
|
|
|
|
- }
|
|
|
|
|
- repeats = 1;
|
|
|
|
|
- }
|
|
|
|
|
- else if ( step == '-' )
|
|
|
|
|
- {
|
|
|
|
|
- for ( int j = 0; j < repeats; j++ )
|
|
|
|
|
- {
|
|
|
|
|
- turtle.angle += -ls->theta;
|
|
|
|
|
- }
|
|
|
|
|
- repeats = 1;
|
|
|
|
|
- }
|
|
|
|
|
- else if ( step == '[' )
|
|
|
|
|
- {
|
|
|
|
|
- PushTurtleState(turtle);
|
|
|
|
|
- }
|
|
|
|
|
- else if ( step == ']' )
|
|
|
|
|
- {
|
|
|
|
|
- turtle = PopTurtleState();
|
|
|
|
|
- }
|
|
|
|
|
- else if ( ( step >= 48 ) && ( step <= 57 ) )
|
|
|
|
|
- {
|
|
|
|
|
- repeats = (int) step - 48;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- turtleTop = -1;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ return ls;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void BuildProductionStep(PenroseLSystem *ls)
|
|
void BuildProductionStep(PenroseLSystem *ls)
|
|
|
{
|
|
{
|
|
|
- char *newProduction = (char*) malloc(sizeof(char) * STR_MAX_SIZE);
|
|
|
|
|
|
|
+ char *newProduction = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
|
|
newProduction[0] = '\0';
|
|
newProduction[0] = '\0';
|
|
|
|
|
|
|
|
int productionLength = strnlen(ls->production, STR_MAX_SIZE);
|
|
int productionLength = strnlen(ls->production, STR_MAX_SIZE);
|
|
@@ -177,7 +193,7 @@ void BuildProductionStep(PenroseLSystem *ls)
|
|
|
{
|
|
{
|
|
|
int t = strnlen(newProduction, STR_MAX_SIZE);
|
|
int t = strnlen(newProduction, STR_MAX_SIZE);
|
|
|
newProduction[t] = step;
|
|
newProduction[t] = step;
|
|
|
- newProduction[t+1] = '\0';
|
|
|
|
|
|
|
+ newProduction[t + 1] = '\0';
|
|
|
}
|
|
}
|
|
|
} break;
|
|
} break;
|
|
|
}
|
|
}
|
|
@@ -185,89 +201,75 @@ void BuildProductionStep(PenroseLSystem *ls)
|
|
|
|
|
|
|
|
ls->drawLength *= 0.5f;
|
|
ls->drawLength *= 0.5f;
|
|
|
strncpy(ls->production, newProduction, STR_MAX_SIZE);
|
|
strncpy(ls->production, newProduction, STR_MAX_SIZE);
|
|
|
- free( newProduction );
|
|
|
|
|
|
|
+
|
|
|
|
|
+ RL_FREE(newProduction);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void BuildPenroseLSystem(PenroseLSystem *ls, float drawLength, int generations)
|
|
void BuildPenroseLSystem(PenroseLSystem *ls, float drawLength, int generations)
|
|
|
{
|
|
{
|
|
|
*ls = CreatePenroseLSystem(drawLength);
|
|
*ls = CreatePenroseLSystem(drawLength);
|
|
|
- for (int i = 0; i < generations; i++)
|
|
|
|
|
- {
|
|
|
|
|
- BuildProductionStep(ls);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (int i = 0; i < generations; i++) BuildProductionStep(ls);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-//------------------------------------------------------------------------------------
|
|
|
|
|
-// Program main entry point
|
|
|
|
|
-//------------------------------------------------------------------------------------
|
|
|
|
|
-int main(void)
|
|
|
|
|
|
|
+void DrawPenroseLSystem(PenroseLSystem *ls)
|
|
|
{
|
|
{
|
|
|
- // Initialization
|
|
|
|
|
- //--------------------------------------------------------------------------------------
|
|
|
|
|
- const int screenWidth = 800;
|
|
|
|
|
- const int screenHeight = 450;
|
|
|
|
|
-
|
|
|
|
|
- SetConfigFlags( FLAG_MSAA_4X_HINT );
|
|
|
|
|
- InitWindow(screenWidth, screenHeight, "raylib [shapes] example - penrose tile");
|
|
|
|
|
-
|
|
|
|
|
- float drawLength = 460.0f;
|
|
|
|
|
- int minGenerations = 0;
|
|
|
|
|
- int maxGenerations = 4;
|
|
|
|
|
- int generations = 0;
|
|
|
|
|
|
|
+ Vector2 screenCenter = { GetScreenWidth()/2, GetScreenHeight()/2 };
|
|
|
|
|
|
|
|
- PenroseLSystem ls = {0};
|
|
|
|
|
- BuildPenroseLSystem(&ls, drawLength * (generations / (float) maxGenerations), generations);
|
|
|
|
|
-
|
|
|
|
|
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
|
|
|
|
- //---------------------------------------------------------------------------------------
|
|
|
|
|
|
|
+ TurtleState turtle = {
|
|
|
|
|
+ .origin = {0},
|
|
|
|
|
+ .angle = -90.0f
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- // Main game loop
|
|
|
|
|
- while (!WindowShouldClose()) // Detect window close button or ESC key
|
|
|
|
|
|
|
+ int repeats = 1;
|
|
|
|
|
+ int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE);
|
|
|
|
|
+ ls->steps += 12;
|
|
|
|
|
+
|
|
|
|
|
+ if (ls->steps > productionLength) ls->steps = productionLength;
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < ls->steps; i++)
|
|
|
{
|
|
{
|
|
|
- // Update
|
|
|
|
|
- //----------------------------------------------------------------------------------
|
|
|
|
|
- bool rebuild = false;
|
|
|
|
|
- if (IsKeyPressed(KEY_UP))
|
|
|
|
|
|
|
+ char step = ls->production[i];
|
|
|
|
|
+ if (step == 'F')
|
|
|
{
|
|
{
|
|
|
- if (generations < maxGenerations)
|
|
|
|
|
|
|
+ for (int j = 0; j < repeats; j++)
|
|
|
{
|
|
{
|
|
|
- generations++;
|
|
|
|
|
- rebuild = true;
|
|
|
|
|
|
|
+ Vector2 startPosWorld = turtle.origin;
|
|
|
|
|
+ float radAngle = DEG2RAD*turtle.angle;
|
|
|
|
|
+ turtle.origin.x += ls->drawLength*cosf(radAngle);
|
|
|
|
|
+ turtle.origin.y += ls->drawLength*sinf(radAngle);
|
|
|
|
|
+ Vector2 startPosScreen = { startPosWorld.x + screenCenter.x, startPosWorld.y + screenCenter.y };
|
|
|
|
|
+ Vector2 endPosScreen = { turtle.origin.x + screenCenter.x, turtle.origin.y + screenCenter.y };
|
|
|
|
|
+
|
|
|
|
|
+ DrawLineEx(startPosScreen, endPosScreen, 2, Fade(BLACK, 0.2));
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- else if (IsKeyPressed(KEY_DOWN))
|
|
|
|
|
|
|
+
|
|
|
|
|
+ repeats = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (step == '+')
|
|
|
{
|
|
{
|
|
|
- if (generations > minGenerations)
|
|
|
|
|
- {
|
|
|
|
|
- generations--;
|
|
|
|
|
- rebuild = generations > 0;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- if (rebuild)
|
|
|
|
|
|
|
+ for (int j = 0; j < repeats; j++) turtle.angle += ls->theta;
|
|
|
|
|
+
|
|
|
|
|
+ repeats = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (step == '-')
|
|
|
{
|
|
{
|
|
|
- BuildPenroseLSystem(&ls, drawLength * (generations / (float) maxGenerations), generations);
|
|
|
|
|
- }
|
|
|
|
|
- //----------------------------------------------------------------------------------
|
|
|
|
|
|
|
+ for (int j = 0; j < repeats; j++) turtle.angle += -ls->theta;
|
|
|
|
|
|
|
|
- // Draw
|
|
|
|
|
- //----------------------------------------------------------------------------------
|
|
|
|
|
- BeginDrawing();
|
|
|
|
|
- ClearBackground( RAYWHITE );
|
|
|
|
|
- if (generations > 0)
|
|
|
|
|
- {
|
|
|
|
|
- DrawPenroseLSystem(&ls);
|
|
|
|
|
- }
|
|
|
|
|
- DrawText("penrose l-system", 10, 10, 20, DARKGRAY);
|
|
|
|
|
- DrawText("press up or down to change generations", 10, 30, 20, DARKGRAY);
|
|
|
|
|
- DrawText(TextFormat("generations: %d", generations), 10, 50, 20, DARKGRAY);
|
|
|
|
|
- EndDrawing();
|
|
|
|
|
- //----------------------------------------------------------------------------------
|
|
|
|
|
|
|
+ repeats = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (step == '[')
|
|
|
|
|
+ {
|
|
|
|
|
+ PushTurtleState(turtle);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (step == ']')
|
|
|
|
|
+ {
|
|
|
|
|
+ turtle = PopTurtleState();
|
|
|
|
|
+ }
|
|
|
|
|
+ else if ((step >= 48) && (step <= 57))
|
|
|
|
|
+ {
|
|
|
|
|
+ repeats = (int) step - 48;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // De-Initialization
|
|
|
|
|
- //--------------------------------------------------------------------------------------
|
|
|
|
|
- CloseWindow(); // Close window and OpenGL context
|
|
|
|
|
- //--------------------------------------------------------------------------------------
|
|
|
|
|
-
|
|
|
|
|
- return 0;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ turtleTop = -1;
|
|
|
|
|
+}
|