mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-06 06:13:10 +00:00
REVIEWED: example: shapes_penrose_tile formating
This commit is contained in:
parent
d13314fe1c
commit
d3addad9a7
@ -16,14 +16,18 @@
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.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 {
|
||||
Vector2 origin;
|
||||
double angle;
|
||||
@ -40,162 +44,21 @@ typedef struct PenroseLSystem {
|
||||
float theta;
|
||||
} PenroseLSystem;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static TurtleState turtleStack[TURTLE_STACK_MAX_SIZE];
|
||||
static int turtleTop = -1;
|
||||
|
||||
void PushTurtleState(TurtleState state)
|
||||
{
|
||||
if (turtleTop < TURTLE_STACK_MAX_SIZE - 1)
|
||||
{
|
||||
turtleStack[++turtleTop] = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(LOG_WARNING, "TURTLE STACK OVERFLOW!");
|
||||
}
|
||||
}
|
||||
|
||||
TurtleState PopTurtleState(void)
|
||||
{
|
||||
if (turtleTop >= 0)
|
||||
{
|
||||
return turtleStack[turtleTop--];
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
|
||||
}
|
||||
return (TurtleState) {0};
|
||||
}
|
||||
|
||||
PenroseLSystem CreatePenroseLSystem(float drawLength)
|
||||
{
|
||||
PenroseLSystem ls = {
|
||||
.steps = 0,
|
||||
.ruleW = "YF++ZF4-XF[-YF4-WF]++",
|
||||
.ruleX = "+YF--ZF[3-WF--XF]+",
|
||||
.ruleY = "-WF++XF[+++YF++ZF]-",
|
||||
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
|
||||
.drawLength = drawLength,
|
||||
.theta = 36.0f // in degrees
|
||||
};
|
||||
ls.production = (char*) malloc(sizeof(char) * STR_MAX_SIZE);
|
||||
ls.production[0] = '\0';
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void BuildProductionStep(PenroseLSystem *ls)
|
||||
{
|
||||
char *newProduction = (char*) malloc(sizeof(char) * STR_MAX_SIZE);
|
||||
newProduction[0] = '\0';
|
||||
|
||||
int productionLength = strnlen(ls->production, STR_MAX_SIZE);
|
||||
|
||||
for (int i = 0; i < productionLength; i++)
|
||||
{
|
||||
char step = ls->production[i];
|
||||
int remainingSpace = STR_MAX_SIZE - strnlen(newProduction, STR_MAX_SIZE) - 1;
|
||||
switch (step)
|
||||
{
|
||||
case 'W': strncat(newProduction, ls->ruleW, remainingSpace); break;
|
||||
case 'X': strncat(newProduction, ls->ruleX, remainingSpace); break;
|
||||
case 'Y': strncat(newProduction, ls->ruleY, remainingSpace); break;
|
||||
case 'Z': strncat(newProduction, ls->ruleZ, remainingSpace); break;
|
||||
default:
|
||||
{
|
||||
if (step != 'F')
|
||||
{
|
||||
int t = strnlen(newProduction, STR_MAX_SIZE);
|
||||
newProduction[t] = step;
|
||||
newProduction[t+1] = '\0';
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
ls->drawLength *= 0.5f;
|
||||
strncpy(ls->production, newProduction, STR_MAX_SIZE);
|
||||
free( newProduction );
|
||||
}
|
||||
|
||||
void BuildPenroseLSystem(PenroseLSystem *ls, float drawLength, int generations)
|
||||
{
|
||||
*ls = CreatePenroseLSystem(drawLength);
|
||||
for (int i = 0; i < generations; i++)
|
||||
{
|
||||
BuildProductionStep(ls);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
// 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
|
||||
@ -207,7 +70,7 @@ int main(void)
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags( FLAG_MSAA_4X_HINT );
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - penrose tile");
|
||||
|
||||
float drawLength = 460.0f;
|
||||
@ -216,7 +79,7 @@ int main(void)
|
||||
int generations = 0;
|
||||
|
||||
PenroseLSystem ls = {0};
|
||||
BuildPenroseLSystem(&ls, drawLength * (generations / (float) maxGenerations), generations);
|
||||
BuildPenroseLSystem(&ls, drawLength*(generations/(float)maxGenerations), generations);
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
@ -240,26 +103,25 @@ int main(void)
|
||||
if (generations > minGenerations)
|
||||
{
|
||||
generations--;
|
||||
rebuild = generations > 0;
|
||||
if (generations > 0) rebuild = true;
|
||||
}
|
||||
}
|
||||
if (rebuild)
|
||||
{
|
||||
BuildPenroseLSystem(&ls, drawLength * (generations / (float) maxGenerations), generations);
|
||||
}
|
||||
|
||||
if (rebuild) BuildPenroseLSystem(&ls, drawLength*(generations/(float)maxGenerations), generations);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground( RAYWHITE );
|
||||
if (generations > 0)
|
||||
{
|
||||
DrawPenroseLSystem(&ls);
|
||||
}
|
||||
|
||||
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();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
@ -271,3 +133,143 @@ int main(void)
|
||||
|
||||
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)
|
||||
{
|
||||
if (turtleTop >= 0) return turtleStack[turtleTop--];
|
||||
else TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
|
||||
|
||||
return (TurtleState){ 0 };
|
||||
}
|
||||
|
||||
PenroseLSystem CreatePenroseLSystem(float drawLength)
|
||||
{
|
||||
PenroseLSystem ls = {
|
||||
.steps = 0,
|
||||
.ruleW = "YF++ZF4-XF[-YF4-WF]++",
|
||||
.ruleX = "+YF--ZF[3-WF--XF]+",
|
||||
.ruleY = "-WF++XF[+++YF++ZF]-",
|
||||
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
|
||||
.drawLength = drawLength,
|
||||
.theta = 36.0f // Degrees
|
||||
};
|
||||
|
||||
ls.production = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
||||
ls.production[0] = '\0';
|
||||
strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE);
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
void BuildProductionStep(PenroseLSystem *ls)
|
||||
{
|
||||
char *newProduction = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
||||
newProduction[0] = '\0';
|
||||
|
||||
int productionLength = strnlen(ls->production, STR_MAX_SIZE);
|
||||
|
||||
for (int i = 0; i < productionLength; i++)
|
||||
{
|
||||
char step = ls->production[i];
|
||||
int remainingSpace = STR_MAX_SIZE - strnlen(newProduction, STR_MAX_SIZE) - 1;
|
||||
switch (step)
|
||||
{
|
||||
case 'W': strncat(newProduction, ls->ruleW, remainingSpace); break;
|
||||
case 'X': strncat(newProduction, ls->ruleX, remainingSpace); break;
|
||||
case 'Y': strncat(newProduction, ls->ruleY, remainingSpace); break;
|
||||
case 'Z': strncat(newProduction, ls->ruleZ, remainingSpace); break;
|
||||
default:
|
||||
{
|
||||
if (step != 'F')
|
||||
{
|
||||
int t = strnlen(newProduction, STR_MAX_SIZE);
|
||||
newProduction[t] = step;
|
||||
newProduction[t + 1] = '\0';
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
ls->drawLength *= 0.5f;
|
||||
strncpy(ls->production, newProduction, STR_MAX_SIZE);
|
||||
|
||||
RL_FREE(newProduction);
|
||||
}
|
||||
|
||||
void BuildPenroseLSystem(PenroseLSystem *ls, float drawLength, int generations)
|
||||
{
|
||||
*ls = CreatePenroseLSystem(drawLength);
|
||||
for (int i = 0; i < generations; i++) BuildProductionStep(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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user