Watch
2
0
Fork
You've already forked raylib-cs
0

chore: clean recommit

This commit is contained in:
tiger tiger tiger 2026-07-07 23:47:38 +02:00
commit 60ad2e7fb1
122 changed files with 23950 additions and 323 deletions

View file

@ -0,0 +1,283 @@
/*******************************************************************************************
*
* raylib [shapes] example - penrose tile
*
* Example complexity rating: [] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 6.0
* Based on: https://processing.org/examples/penrosetile.html
*
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
using System;
using System.Numerics;
using System.Collections.Generic;
using System.Text;
using static Raylib_cs.Raylib;
namespace Examples.Shapes;
public partial class PenroseTile : IExample
{
private const int screenWidth = 800;
private const int screenHeight = 450;
public string Name => "Shapes / Penrose Tile";
public string Title => "raylib [shapes] example - penrose tile";
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint;
public int TargetFps => 120;
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
private struct TurtleState
{
public Vector2 origin;
public float angle;
}
private class PenroseLSystem
{
public int steps;
public StringBuilder production;
public string ruleW;
public string ruleX;
public string ruleY;
public string ruleZ;
public float drawLength;
public float theta;
}
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
private Stack<TurtleState> turtleStack;
private const float drawLength = 460.0f;
private int minGenerations;
private int maxGenerations;
private int generations;
private PenroseLSystem ls;
public void Init()
{
turtleStack = new Stack<TurtleState>();
minGenerations = 0;
maxGenerations = 4;
generations = 0;
// Initialize new penrose tile
ls = CreatePenroseLSystem(drawLength * (generations / (float)maxGenerations));
for (int i = 0; i < generations; i++) BuildProductionStep(ls);
}
public void Update()
{
// Update
//----------------------------------------------------------------------------------
bool rebuild = false;
if (IsKeyPressed(KeyboardKey.Up))
{
if (generations < maxGenerations)
{
generations++;
rebuild = true;
}
}
else if (IsKeyPressed(KeyboardKey.Down))
{
if (generations > minGenerations)
{
generations--;
if (generations > 0) rebuild = true;
}
}
if (rebuild)
{
ls = CreatePenroseLSystem(drawLength * (generations / (float)maxGenerations));
for (int i = 0; i < generations; i++) BuildProductionStep(ls);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(Color.RayWhite);
if (generations > 0) DrawPenroseLSystem(ls);
DrawText("penrose l-system", 10, 10, 20, Color.DarkGray);
DrawText("press up or down to change generations", 10, 30, 20, Color.DarkGray);
DrawText($"generations: {generations}", 10, 50, 20, Color.DarkGray);
EndDrawing();
//----------------------------------------------------------------------------------
}
public void Unload()
{
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Push turtle state for next step
private void PushTurtleState(TurtleState state)
{
turtleStack.Push(state);
}
// Pop turtle state step
private TurtleState PopTurtleState()
{
if (turtleStack.Count > 0) return turtleStack.Pop();
else TraceLog(TraceLogLevel.Warning, "TURTLE STACK UNDERFLOW!");
return new TurtleState();
}
// Create a new penrose tile structure
private static PenroseLSystem CreatePenroseLSystem(float drawLength)
{
PenroseLSystem ls = new PenroseLSystem
{
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 = new StringBuilder("[X]++[X]++[X]++[X]++[X]");
return ls;
}
// Build next penrose step
private static void BuildProductionStep(PenroseLSystem ls)
{
StringBuilder newProduction = new StringBuilder();
string production = ls.production.ToString();
for (int i = 0; i < production.Length; i++)
{
char step = production[i];
switch (step)
{
case 'W': newProduction.Append(ls.ruleW); break;
case 'X': newProduction.Append(ls.ruleX); break;
case 'Y': newProduction.Append(ls.ruleY); break;
case 'Z': newProduction.Append(ls.ruleZ); break;
default:
{
if (step != 'F') newProduction.Append(step);
} break;
}
}
ls.drawLength *= 0.5f;
ls.production = newProduction;
}
// Draw penrose tile lines
private void DrawPenroseLSystem(PenroseLSystem ls)
{
Vector2 screenCenter = new Vector2(GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f);
TurtleState turtle = new TurtleState
{
origin = new Vector2(0, 0),
angle = -90.0f
};
int repeats = 1;
string production = ls.production.ToString();
int productionLength = production.Length;
ls.steps += 12;
if (ls.steps > productionLength) ls.steps = productionLength;
for (int i = 0; i < ls.steps; i++)
{
char step = 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 * MathF.Cos(radAngle);
turtle.origin.Y += ls.drawLength * MathF.Sin(radAngle);
Vector2 startPosScreen = new Vector2(startPosWorld.X + screenCenter.X, startPosWorld.Y + screenCenter.Y);
Vector2 endPosScreen = new Vector2(turtle.origin.X + screenCenter.X, turtle.origin.Y + screenCenter.Y);
DrawLineEx(startPosScreen, endPosScreen, 2, Fade(Color.Black, 0.2f));
}
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;
}
turtleStack.Clear();
}
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
SetConfigFlags(ConfigFlags.Msaa4xHint);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - penrose tile");
SetTargetFPS(120); // Set our game to run at 120 frames-per-second
//---------------------------------------------------------------------------------------
var game = new PenroseTile();
game.Init();
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
game.Update();
}
game.Unload();
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
}