From 94366746d44311dc74f752973cce38ef8f53ff6b Mon Sep 17 00:00:00 2001 From: themushroompirates <59015901+themushroompirates@users.noreply.github.com> Date: Fri, 10 Oct 2025 18:19:27 +0200 Subject: [PATCH] Added simple starfield example --- examples/Makefile | 1 + examples/Makefile.Web | 1 + examples/README.md | 5 +- examples/shapes/shapes_starfield.c | 143 +++++++++++++++++++++++++++ examples/shapes/shapes_starfield.png | Bin 0 -> 20913 bytes 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 examples/shapes/shapes_starfield.c create mode 100644 examples/shapes/shapes_starfield.png diff --git a/examples/Makefile b/examples/Makefile index 6e2853edb93e..5cef8156a2ca 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -564,6 +564,7 @@ SHAPES = \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ + shapes/shapes_starfield \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle diff --git a/examples/Makefile.Web b/examples/Makefile.Web index f1662a301843..76739d705a87 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -564,6 +564,7 @@ SHAPES = \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ + shapes/shapes_starfield \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle diff --git a/examples/README.md b/examples/README.md index 441c5a368774..36be8a527f55 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: 175] +## EXAMPLES COLLECTION [TOTAL: 176] ### 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 [26] +### category: shapes [27] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -92,6 +92,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) | | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐⭐⭐⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) | | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | shapes_splines_drawing | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | +| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐⭐⭐☆ | 5.5 | 5.5 | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_digital_clock](shapes/shapes_digital_clock.c) | shapes_digital_clock | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) | | [shapes_double_pendulum](shapes/shapes_double_pendulum.c) | shapes_double_pendulum | ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) | | [shapes_dashed_line](shapes/shapes_dashed_line.c) | shapes_dashed_line | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) | diff --git a/examples/shapes/shapes_starfield.c b/examples/shapes/shapes_starfield.c new file mode 100644 index 000000000000..457912dec05b --- /dev/null +++ b/examples/shapes/shapes_starfield.c @@ -0,0 +1,143 @@ +/******************************************************************************************* +* +* raylib [shapes] example - simple starfield +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5 +* +* Example contributed by JP Mortiboys (@themushroompirates) 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 JP Mortiboys (@themushroompirates) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" // Required for: Lerp() + +#define STAR_COUNT 420 + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield"); + + Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.69f); + + // Speed at which we fly forward + float speed = 10.0f/9.0f; + + // We're either drawing lines or circles + bool drawLines = true; + + Vector3 stars[STAR_COUNT] = { 0 }; + Vector2 starsScreenPos[STAR_COUNT] = { 0 }; + + // Setup the stars with a random position + for (int i = 0; i < STAR_COUNT; i++) { + stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); + stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + stars[i].z = 1.0f; + } + + 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 + //---------------------------------------------------------------------------------- + + // Change speed based on number keys + for (int i = 0; i <= 9; i++) { + if (IsKeyPressed(KEY_ZERO + i)) { + speed = 2.0f * (float)i / 9.0f; + } + } + + // Toggle lines / points with space bar + if (IsKeyPressed(KEY_SPACE)) { + drawLines = !drawLines; + } + + float dt = GetFrameTime(); + for (int i = 0; i < STAR_COUNT; i++) { + // Update star's timer + stars[i].z -= dt * speed; + // Calculate the screen position + starsScreenPos[i] = (Vector2) { + screenWidth*.5f + stars[i].x / stars[i].z, + screenHeight*.5f + stars[i].y / stars[i].z, + }; + // If the star is too old, or offscreen, it dies and we make a new random one + if (stars[i].z < 0.0f + || starsScreenPos[i].x < 0 || starsScreenPos[i].y < 0.0f + || starsScreenPos[i].x > screenWidth || starsScreenPos[i].y > screenHeight) { + stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); + stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + stars[i].z = 1.0f; + } + } + + + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(bgColor); + + for (int i = 0; i < STAR_COUNT; i++) { + if (drawLines) { + // Get the time a little while ago for this star, but clamp it + float t = Clamp(stars[i].z + 1.0f/32.0f, 0.0f, 1.0f); + // If it's different enough from the current time, we proceed + if (t - stars[i].z > 1e-3) { + // Calculate the screen position of the old point + Vector2 startPos = (Vector2) { + screenWidth*.5f + stars[i].x / t, + screenHeight*.5f + stars[i].y / t, + }; + // Draw a line connecting the old point to the current point + DrawLineV(startPos, starsScreenPos[i], RAYWHITE); + } + } + else { + // Make the radius grow as the star ages + float radius = Lerp(stars[i].z, 1.0f, 5.0f); + // Draw the circle + DrawCircleV(starsScreenPos[i], radius, RAYWHITE); + } + } + + DrawFPS(10, 10); + + DrawText(TextFormat("Current Speed: %.0f [Number keys to change]", 9.0f * speed / 2.0f), 10, 30, 20, RAYWHITE); + DrawText(TextFormat("Drawing %s [Space to change]", drawLines ? "Lines" : "Circles"), 10, 50, 20, RAYWHITE); + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_starfield.png b/examples/shapes/shapes_starfield.png new file mode 100644 index 0000000000000000000000000000000000000000..6903f222b5e0e25b22be5717b79da5b66f6503d5 GIT binary patch literal 20913 zcmaKUdpuP6|NqRGWoR(n$1u#Ki!RD#Tym)~Q)eWkv~6p0?VjlIs zKO_d+Vjk-@#wTQ45ohUe|(UoxIqOv=D)ur9*E*vIceD_@1 zHKF*vvkvlX^S|b!4S#XwV7lS|`lfH2!%0DbH$_WHzwgp2MZcPQJsOyJ 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