diff --git a/examples/Makefile b/examples/Makefile index fb33b4894759..cae754778b27 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -557,6 +557,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_sine_cosine \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_ring_drawing \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 0dbefadf2672..aab50a5d0684 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -557,6 +557,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_sine_cosine \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_ring_drawing \ @@ -862,6 +863,9 @@ shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 50643bf2b50e..dee62fe90b57 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -70,6 +70,7 @@ shapes;shapes_digital_clock;★★★★;5.5;5.6;2025;2025;"Hamza RAHAL";@hmz-rh shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joecheong2006 shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605 shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5 +models;shapes_math_sine_cosine;★★★★;5.6-dev;5.6-dev;2025;2025;"Olivier";@oqu textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/shapes/shapes_math_sine_cosine.c b/examples/shapes/shapes_math_sine_cosine.c new file mode 100644 index 000000000000..e06b9323be06 --- /dev/null +++ b/examples/shapes/shapes_math_sine_cosine.c @@ -0,0 +1,180 @@ +/******************************************************************************************* + * + * raylib [shapes] example - math sine cosine + * + * Port of the p5.js "sine and cosine" demo to raylib + raygui + * Sources: https://p5js.org/examples/angles-and-motion-sine-cosine/ + * + * Demonstrates uniform circular motion and the correspondence between + * the unit circle and sine / cosine graphs. Right panel contains a + * play/pause toggle implemented with raygui. + * + * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev + * + * Copyright (c) 2025 Olivier (@oqu) + * + ********************************************************************************************/ + +#include "raylib.h" + +// Required for GUI controls +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" + +#include + +int main(void) +{ + // Window initialization + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math sine cosine"); + const char* playText = "Play"; + const char* pauseText = "Pause"; + + // Scene layout (mimic p5 example positioning) + const float circleX = 200.0f; + const float circleY = 150.0f; + const float circleRadius = 75.0f; + + const float graphX = 50.0f; + const float graphY = 300.0f; + const float graphAmplitude = 50.0f; + const float graphPeriod = 300.0f; // width of the graph in pixels + + // Animation / UI state + bool playing = true; // play / pause toggle + int frameCountLocal = 0; // local frame counter (used when playing) + + SetTargetFPS(60); + + // Main loop + while (!WindowShouldClose()) + { + // Handle GUI and input first + BeginDrawing(); + + ClearBackground(BLACK); + + // Right control panel + float panelX = (float)GetScreenWidth() - 270.0f; + Rectangle panel = {panelX, 10, 260, (float)GetScreenHeight() - 20}; + DrawRectangleRec(panel, Fade(LIGHTGRAY, 0.6f)); + DrawRectangleLinesEx(panel, 1, GRAY); + + int y = 20; + int px = (int)panelX + 10; + DrawText("Sine / Cosine Demo", px, y, 20, DARKGRAY); + y += 34; + + // Play / Pause toggle + DrawText("Animation:", px, y, 14, DARKGRAY); + y += 18; + GuiToggle((Rectangle){(float)px, y, 220, 30}, playing ? pauseText : playText, &playing); + y += 40; + + // Small description + DrawText("Animated demonstration of a point moving", px, y, 10, DARKGRAY); + y += 14; + DrawText("around the unit circle and the corresponding", px, y, 10, DARKGRAY); + y += 14; + DrawText("sine (red) and cosine (orange) graphs.", px, y, 10, DARKGRAY); + y += 30; + + DrawFPS(px, GetScreenHeight() - 30); + + // Update frameCount if playing + if (playing) + frameCountLocal++; + + // Angle in degrees (like the p5 example) + int angleDeg = frameCountLocal % 360; + + // Draw angle label + Color labelCol = WHITE; + DrawText(TextFormat("angle: %d", angleDeg), 25, 25, 20, labelCol); + + // --- Draw circle and diameters --- + // circle outer + DrawCircleLines((int)circleX, (int)circleY, circleRadius, Fade(GRAY, 0.6f)); + // diameters + DrawLine((int)circleX, (int)(circleY - circleRadius), (int)circleX, (int)(circleY + circleRadius), Fade(GRAY, 0.6f)); + DrawLine((int)(circleX - circleRadius), (int)circleY, (int)(circleX + circleRadius), (int)circleY, Fade(GRAY, 0.6f)); + + // Compute moving point on circle (cos for x, sin for y). Note: cos/sin in C expect radians + float angRad = angleDeg * (PI / 180.0f); + float pointX = circleX + circleRadius * cosf(angRad); + float pointY = circleY - circleRadius * sinf(angRad); // minus to match p5 y-axis direction + + // line from center to point + DrawLine((int)circleX, (int)circleY, (int)pointX, (int)pointY, Fade(GRAY, 0.6f)); + + // moving points + DrawCircleV((Vector2){pointX, pointY}, 6.0f, WHITE); + DrawCircle((int)pointX, (int)circleY, 6.0f, ORANGE); + DrawCircle((int)circleX, (int)pointY, 6.0f, RED); + + // --- Draw graph area axes --- + // axes lines + DrawLine((int)graphX, (int)graphY, (int)(graphX + graphPeriod), (int)graphY, Fade(GRAY, 0.6f)); + DrawLine((int)graphX, (int)(graphY - graphAmplitude), (int)graphX, (int)(graphY + graphAmplitude), Fade(GRAY, 0.6f)); + DrawLine((int)(graphX + graphPeriod), (int)(graphY - graphAmplitude), (int)(graphX + graphPeriod), (int)(graphY + graphAmplitude), Fade(GRAY, 0.6f)); + + // labels + DrawText("0", (int)graphX - 6, (int)(graphY + graphAmplitude + 6), 14, Fade(GRAY, 0.9f)); + DrawText("360", (int)(graphX + graphPeriod) - 12, (int)(graphY + graphAmplitude + 6), 14, Fade(GRAY, 0.9f)); + DrawText("1", (int)(graphX / 2) - 6, (int)(graphY - graphAmplitude) - 6, 14, Fade(GRAY, 0.9f)); + DrawText("0", (int)(graphX / 2) - 6, (int)(graphY)-6, 14, Fade(GRAY, 0.9f)); + DrawText("-1", (int)(graphX / 2) - 10, (int)(graphY + graphAmplitude) - 6, 14, Fade(GRAY, 0.9f)); + + DrawText("cos", (int)(graphX + graphPeriod + graphX / 2) - 18, (int)(graphY - graphAmplitude) - 10, 20, ORANGE); + DrawText("sin", (int)(graphX + graphPeriod + graphX / 2) - 18, (int)(graphY) - 10, 20, RED); + + // --- Draw cosine curve (orange) --- + for (int t = 0; t <= 360; t++) + { + float x = ((float)t / 360.0f) * graphPeriod + graphX; + float y = graphY - graphAmplitude * cosf(t * (PI / 180.0f)); + // draw small segments between consecutive points for smoother curve + if (t > 0) + { + int prevT = t - 1; + float px = ((float)prevT / 360.0f) * graphPeriod + graphX; + float py = graphY - graphAmplitude * cosf(prevT * (PI / 180.0f)); + DrawLineEx((Vector2){px, py}, (Vector2){x, y}, 2.5f, ORANGE); + } + } + + // --- Draw sine curve (red) --- + for (int t = 0; t <= 360; t++) + { + float x = ((float)t / 360.0f) * graphPeriod + graphX; + float y = graphY - graphAmplitude * sinf(t * (PI / 180.0f)); + if (t > 0) + { + int prevT = t - 1; + float px = ((float)prevT / 360.0f) * graphPeriod + graphX; + float py = graphY - graphAmplitude * sinf(prevT * (PI / 180.0f)); + DrawLineEx((Vector2){px, py}, (Vector2){x, y}, 2.5f, RED); + } + } + + // --- Draw moving vertical line on the graph corresponding to the angle --- + float lineX = ((float)angleDeg / 360.0f) * graphPeriod + graphX; + DrawLine((int)lineX, (int)(graphY - graphAmplitude), (int)lineX, (int)(graphY + graphAmplitude), Fade(GRAY, 0.6f)); + + // moving points on graph + float orangeY = graphY - graphAmplitude * cosf(angRad); + float redY = graphY - graphAmplitude * sinf(angRad); + + DrawCircle((int)lineX, (int)orangeY, 6.0f, ORANGE); + DrawCircle((int)lineX, (int)redY, 6.0f, RED); + + EndDrawing(); + } + + CloseWindow(); + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_math_sine_cosine.png b/examples/shapes/shapes_math_sine_cosine.png new file mode 100644 index 000000000000..8f42724a26ed Binary files /dev/null and b/examples/shapes/shapes_math_sine_cosine.png differ