1+ /*******************************************************************************************
2+ *
3+ * raylib [shapes] example - shapes recursive tree
4+ *
5+ * Example complexity rating: [★★★☆] 3/4
6+ *
7+ * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
8+ *
9+ * Example contributed by Jopestpe (@jopestpe)
10+ *
11+ * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
12+ * BSD-like license that allows static linking with closed source software
13+ *
14+ * Copyright (c) 2018-2025 Jopestpe (@jopestpe)
15+ *
16+ ********************************************************************************************/
17+
18+ #include "raylib.h"
19+ #include <math.h>
20+
21+ #define RAYGUI_IMPLEMENTATION
22+ #include "raygui.h" // Required for GUI controls
23+
24+ //----------------------------------------------------------------------------------
25+ // Types and Structures Definition
26+ //----------------------------------------------------------------------------------
27+ typedef struct {
28+ Vector2 start ;
29+ Vector2 end ;
30+ float angle ;
31+ float length ;
32+ } Branch ;
33+
34+ //----------------------------------------------------------------------------------
35+ // Module Functions Declaration
36+ //----------------------------------------------------------------------------------
37+ static Vector2 CalculateBranchEnd (Vector2 start , float angle , float length );
38+
39+ //------------------------------------------------------------------------------------
40+ // Program main entry point
41+ //------------------------------------------------------------------------------------
42+ int main (void )
43+ {
44+ // Initialization
45+ //--------------------------------------------------------------------------------------
46+ const int screenWidth = 800 ;
47+ const int screenHeight = 450 ;
48+
49+ InitWindow (screenWidth , screenHeight , "raylib [shapes] example - shapes recursive tree" );
50+
51+ Vector2 start = { (screenWidth /2.0f ) - 125.0f , screenHeight };
52+ float angle = 40.0f ;
53+ float thick = 1.0f ;
54+ float treeDepth = 10.0f ;
55+ float branchDecay = 0.66f ;
56+ float length = 120.0f ;
57+ bool bezier = false;
58+
59+ SetTargetFPS (60 ); // Set our game to run at 60 frames-per-second
60+ //--------------------------------------------------------------------------------------
61+
62+ // Main game loop
63+ while (!WindowShouldClose ()) // Detect window close button or ESC key
64+ {
65+ // Update
66+ //----------------------------------------------------------------------------------
67+
68+ float theta = angle * DEG2RAD ;
69+ int maxBranches = (int )(powf (2 , (int )(treeDepth )));
70+ Branch branches [1024 ] = { 0 };
71+ int count = 0 ;
72+
73+ Vector2 initialEnd = CalculateBranchEnd (start , 0.0f , length );
74+ branches [count ++ ] = (Branch ){start , initialEnd , 0.0f , length };
75+
76+ for (int i = 0 ; i < count ; i ++ )
77+ {
78+ Branch branch = branches [i ];
79+ if (branch .length < 2 ) continue ;
80+
81+ float nextLength = branch .length * branchDecay ;
82+
83+ if (count < maxBranches && nextLength >= 2 )
84+ {
85+ Vector2 branchStart = branch .end ;
86+
87+ Vector2 branchEnd1 = CalculateBranchEnd (branchStart , branch .angle + theta , nextLength );
88+ Vector2 branchEnd2 = CalculateBranchEnd (branchStart , branch .angle - theta , nextLength );
89+
90+ branches [count ++ ] = (Branch ){branchStart , branchEnd1 , branch .angle + theta , nextLength };
91+ branches [count ++ ] = (Branch ){branchStart , branchEnd2 , branch .angle - theta , nextLength };
92+ }
93+ }
94+
95+ // Draw
96+ //----------------------------------------------------------------------------------
97+ BeginDrawing ();
98+
99+ ClearBackground (RAYWHITE );
100+
101+ for (int i = 0 ; i < count ; i ++ )
102+ {
103+ Branch branch = branches [i ];
104+ if (branch .length >= 2 )
105+ {
106+ if (!bezier ) DrawLineEx (branch .start , branch .end , thick , RED );
107+ else DrawLineBezier (branch .start , branch .end , thick , RED );
108+ }
109+ }
110+
111+ DrawLine (580 , 0 , 580 , GetScreenHeight (), (Color ){ 218 , 218 , 218 , 255 });
112+ DrawRectangle (580 , 0 , GetScreenWidth (), GetScreenHeight (), (Color ){ 232 , 232 , 232 , 255 });
113+
114+ // Draw GUI controls
115+ //------------------------------------------------------------------------------
116+ GuiSliderBar ((Rectangle ){ 640 , 40 , 120 , 20 }, "Angle" , TextFormat ("%.0f" , angle ), & angle , 0 , 180 );
117+ GuiSliderBar ((Rectangle ){ 640 , 70 , 120 , 20 }, "Length" , TextFormat ("%.0f" , length ), & length , 12.0f , 240.0f );
118+ GuiSliderBar ((Rectangle ){ 640 , 100 , 120 , 20 }, "Decay" , TextFormat ("%.2f" , branchDecay ), & branchDecay , 0.1f , 0.78f );
119+ GuiSliderBar ((Rectangle ){ 640 , 130 , 120 , 20 }, "Depth" , TextFormat ("%.0f" , treeDepth ), & treeDepth , 1.0f , 10.f );
120+ GuiSliderBar ((Rectangle ){ 640 , 160 , 120 , 20 }, "Thick" , TextFormat ("%.0f" , thick ), & thick , 1 , 8 );
121+ GuiCheckBox ((Rectangle ){ 640 , 190 , 20 , 20 }, "Bezier" , & bezier );
122+ //------------------------------------------------------------------------------
123+
124+ DrawFPS (10 , 10 );
125+
126+ EndDrawing ();
127+ //----------------------------------------------------------------------------------
128+ }
129+
130+ // De-Initialization
131+ //--------------------------------------------------------------------------------------
132+ CloseWindow (); // Close window and OpenGL context
133+ //--------------------------------------------------------------------------------------
134+
135+ return 0 ;
136+ }
137+
138+ static Vector2 CalculateBranchEnd (Vector2 start , float angle , float length )
139+ {
140+ return (Vector2 ){ start .x + length * sinf (angle ), start .y - length * cosf (angle ) };
141+ }
0 commit comments