From b99a6cc6bd93f1355317a1ac49d889b35498158a Mon Sep 17 00:00:00 2001 From: Jopestpe <47086979+Jopestpe@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:35:18 -0300 Subject: [PATCH] [examples] Added `shapes_recursive_tree` (#5229) * ADDED: example: shapes_recursive_tree * [examples] Added shapes_recursive_tree * [examples] shapes_recursive_tree: adjustments * Reduced tree depth from 12 to 10 * new shapes_recursive_tree.png * follow the conventions * follow the conventions 2 --- examples/Makefile | 1 + examples/Makefile.Web | 4 + examples/README.md | 5 +- examples/examples_list.txt | 1 + examples/shapes/shapes_recursive_tree.c | 141 ++++++++++++++++++++++ examples/shapes/shapes_recursive_tree.png | Bin 0 -> 18375 bytes 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 examples/shapes/shapes_recursive_tree.c create mode 100644 examples/shapes/shapes_recursive_tree.png diff --git a/examples/Makefile b/examples/Makefile index fb33b4894..a36b9e447 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -559,6 +559,7 @@ SHAPES = \ shapes/shapes_logo_raylib_anim \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ + shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 0dbefadf2..2d3018abf 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -559,6 +559,7 @@ SHAPES = \ shapes/shapes_logo_raylib_anim \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ + shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ @@ -868,6 +869,9 @@ shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c shapes/shapes_rectangle_scaling: shapes/shapes_rectangle_scaling.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_recursive_tree: shapes/shapes_recursive_tree.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 70e07df2b..d852e7105 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 172] +## EXAMPLES COLLECTION [TOTAL: 173] ### category: core [40] @@ -66,7 +66,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | -### category: shapes [23] +### category: shapes [24] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -84,6 +84,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_following_eyes](shapes/shapes_following_eyes.c) | shapes_following_eyes | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_easings_ball](shapes/shapes_easings_ball.c) | shapes_easings_ball | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_easings_box](shapes/shapes_easings_box.c) | shapes_easings_box | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | +| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) | shapes_recursive_tree | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev| [Jopestpe](https://github.com/jopestpe) | | [shapes_easings_rectangles](shapes/shapes_easings_rectangles.c) | shapes_easings_rectangles | ⭐⭐⭐☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) | | [shapes_ring_drawing](shapes/shapes_ring_drawing.c) | shapes_ring_drawing | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | | [shapes_circle_sector_drawing](shapes/shapes_circle_sector_drawing.c) | shapes_circle_sector_drawing | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) | diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 50643bf2b..5a0c679a4 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -60,6 +60,7 @@ shapes;shapes_following_eyes;★★☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@ shapes;shapes_easings_ball;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_easings_box;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_easings_rectangles;★★★☆;2.0;2.5;2014;2025;"Ramon Santamaria";@raysan5 +shapes;shapes_recursive_tree;★★★☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_ring_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor shapes;shapes_circle_sector_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor shapes;shapes_rounded_rectangle_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c new file mode 100644 index 000000000..3ec46de4b --- /dev/null +++ b/examples/shapes/shapes_recursive_tree.c @@ -0,0 +1,141 @@ +/******************************************************************************************* +* +* raylib [shapes] example - shapes recursive tree +* +* Example complexity rating: [★★★☆] 3/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example contributed by Jopestpe (@jopestpe) +* +* 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) 2018-2025 Jopestpe (@jopestpe) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" // Required for GUI controls + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct { + Vector2 start; + Vector2 end; + float angle; + float length; +} Branch; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - shapes recursive tree"); + + Vector2 start = { (screenWidth/2.0f) - 125.0f, screenHeight }; + float angle = 40.0f; + float thick = 1.0f; + float treeDepth = 10.0f; + float branchDecay = 0.66f; + float length = 120.0f; + bool bezier = false; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + float theta = angle*DEG2RAD; + int maxBranches = (int)(powf(2, (int)(treeDepth))); + Branch branches[1024] = { 0 }; + int count = 0; + + Vector2 initialEnd = CalculateBranchEnd(start, 0.0f, length); + branches[count++] = (Branch){start, initialEnd, 0.0f, length}; + + for (int i = 0; i < count; i++) + { + Branch branch = branches[i]; + if (branch.length < 2) continue; + + float nextLength = branch.length*branchDecay; + + if (count < maxBranches && nextLength >= 2) + { + Vector2 branchStart = branch.end; + + Vector2 branchEnd1 = CalculateBranchEnd(branchStart, branch.angle + theta, nextLength); + Vector2 branchEnd2 = CalculateBranchEnd(branchStart, branch.angle - theta, nextLength); + + branches[count++] = (Branch){branchStart, branchEnd1, branch.angle + theta, nextLength}; + branches[count++] = (Branch){branchStart, branchEnd2, branch.angle - theta, nextLength}; + } + } + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + for (int i = 0; i < count; i++) + { + Branch branch = branches[i]; + if (branch.length >= 2) + { + if (!bezier) DrawLineEx(branch.start, branch.end, thick, RED); + else DrawLineBezier(branch.start, branch.end, thick, RED); + } + } + + DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); + DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 }); + + // Draw GUI controls + //------------------------------------------------------------------------------ + GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180); + GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f); + GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f); + GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.f); + GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8); + GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier); + //------------------------------------------------------------------------------ + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length) +{ + return (Vector2){ start.x + length*sinf(angle), start.y - length*cosf(angle) }; +} \ No newline at end of file diff --git a/examples/shapes/shapes_recursive_tree.png b/examples/shapes/shapes_recursive_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..88932c204bcd24be38c10978b75cda9b002234d8 GIT binary patch literal 18375 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 VwaZoF7#J8BJYD@<);T3K0RTk?UoZdw literal 0 HcmV?d00001