diff --git a/examples/shapes/shapes_math_sine_cosine.c b/examples/shapes/shapes_math_sine_cosine.c new file mode 100644 index 000000000..1cc3b53dc --- /dev/null +++ b/examples/shapes/shapes_math_sine_cosine.c @@ -0,0 +1,204 @@ +/******************************************************************************************* +* +* raylib [shapes] example - math sine cosine +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.6, last time updated with raylib 5.6 +* +* Example contributed by Midiphony (@midiphony) 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-2025 Zero (@zerohorsepower) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" // Required for: Vector2 operations and Clamp() +#include // Required for: malloc(), free() +#include // Required for: cosf(), sinf() + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const Color cosineColor = RED; + const Color sineColor = ORANGE; + const int pointsSize = 6; + const int lineThickness = 2; + + const int screenWidth = 800; + const int screenHeight = 450; + + // Circle + const int circleX = screenWidth/4 - 20; + const int circleY = screenHeight/2; + const Vector2 circlePosition = { circleX, circleY }; + const int circleRadius = 140; + const int circleLeft = circleX - circleRadius; + const int circleRight = circleX + circleRadius; + const int circleTop = circleY - circleRadius; + const int circleBottom = circleY + circleRadius; + + const int circleTextFontSize = 20; + + // Graph + const int graphLeft = screenWidth/2; + const int graphRight = 750; + const int graphHeight = 200; + const int graphHalfHeight = graphHeight/2; + const int graphYMiddle = screenHeight/2; + const int graphTop = graphYMiddle - graphHalfHeight; + const int graphBottom = graphYMiddle + graphHalfHeight; + const int graphWidth = graphRight - graphLeft; + + const int graphTextFontSize = 20; + const int graphTextPadding = 10; + + Vector2* cosineCurvePoints = (Vector2*)malloc(graphWidth*sizeof(Vector2)); // Points array + Vector2* sineCurvePoints = (Vector2*)malloc(graphWidth*sizeof(Vector2)); // Points array + + // Initialize cosine curve + for (int x = 0; x < graphWidth; x++) + { + float y = -cosf(((float)x/graphWidth)*2.0*PI); + int yCoord = graphYMiddle + y*graphHalfHeight; + cosineCurvePoints[x] = (Vector2){ graphLeft + x, yCoord }; + } + + // Initialize sine curve + for (int x = 0; x < graphWidth; x++) + { + float y = sinf(((float)x/graphWidth)*2.0*PI); + int yCoord = graphYMiddle - y*graphHalfHeight; + sineCurvePoints[x] = (Vector2){ graphLeft + x, yCoord }; + } + + const int windowSplitX = ((circleX + circleRadius) + graphLeft)/2; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math sine cosine"); + + const int circleTextMaxLength = MeasureText("-1.000", circleTextFontSize); + const int graphTextMaxLength = MeasureText("-1.000", graphTextFontSize); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + Vector2 mousePosition = GetMousePosition(); + float angleInDegrees = 0.0f; + float angle = 0; + + if (mousePosition.x <= windowSplitX) // Calculate angle relative to the circle + { + angle = Vector2Angle(Vector2Subtract(mousePosition, circlePosition), (Vector2) { 1, 0 }); + if (angle < 0.0f) + { + angle += 2*PI; + } + } + else // Calculate angle relative to the graph + { + angle = Clamp((mousePosition.x - graphLeft)*2*PI/graphWidth, 0.0f, 2*PI); + } + + angleInDegrees = angle*RAD2DEG; + + float cosine = cosf(angle); + float sine = sinf(angle); + int pointX = circleX + circleRadius*cosine; + int pointY = circleY - circleRadius*sine; + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw top angle label + DrawText(TextFormat("Angle:%.1f", angleInDegrees), 20, 20, 30, GRAY); + + // Trigonometry circle + // -------------------- + DrawRing(circlePosition, circleRadius - lineThickness/2, circleRadius + lineThickness/2, 0, 360, 0, GRAY); // 0 ring segment to let DrawRing choose a number of segments giving a smooth circle + DrawLineEx((Vector2) { circleLeft, circleY }, (Vector2) { circleRight, circleY }, lineThickness, GRAY); + DrawLineEx((Vector2) { circleX, circleTop }, (Vector2) { circleX, circleBottom }, lineThickness, GRAY); + + DrawCircleSectorLines(circlePosition, circleRadius/3, 0, -angleInDegrees, 0, BLUE); + + // Draw line to point + DrawLine(circleX, circleY, pointX, pointY, GRAY); + + // Draw cosine point + DrawLineEx((Vector2) { circleX, circleY }, (Vector2) { pointX, circleY }, lineThickness, cosineColor); + DrawText(TextFormat("%.3f", cosine), ((pointX + circleX)/2) - circleTextMaxLength/2, circleY + 2, circleTextFontSize, cosineColor); + // Draw sine point + DrawLineEx((Vector2) { pointX, circleY }, (Vector2) { pointX, pointY }, lineThickness, sineColor); + DrawText(TextFormat("%.3f", sine), pointX + 5, (pointY + circleY)/2 - circleTextFontSize/2, circleTextFontSize, sineColor); + + // Draw point + DrawCircle(pointX, pointY, pointsSize, BLACK); + // -------------------- + + // Window split + DrawLine(windowSplitX, 0, windowSplitX, screenHeight - 1, GRAY); + + // Graph + // -------------------- + // Draw graph borders + DrawLineEx((Vector2) { graphLeft, graphTop }, (Vector2) { graphLeft, graphBottom }, 2, GRAY); + DrawLineEx((Vector2) { graphRight, graphTop }, (Vector2) { graphRight, graphBottom }, 2, GRAY); + DrawLineEx((Vector2) { graphLeft, graphYMiddle }, (Vector2) { graphRight, graphYMiddle }, 2, GRAY); + + // Draw graph outer texts + DrawText("1", graphLeft - graphTextPadding - MeasureText("1", graphTextFontSize), graphTop - graphTextFontSize/2, graphTextFontSize, GRAY); + DrawText("0", graphLeft - graphTextPadding - MeasureText("0", graphTextFontSize), graphYMiddle - graphTextFontSize/2, graphTextFontSize, GRAY); + DrawText("-1", graphLeft - graphTextPadding - MeasureText("-1", graphTextFontSize), graphBottom - graphTextFontSize/2, graphTextFontSize, GRAY); + DrawText("0", graphLeft - MeasureText("0", graphTextFontSize)/2, graphBottom + graphTextPadding/2, graphTextFontSize, GRAY); + DrawText("360", graphRight - MeasureText("360", graphTextFontSize)/2, graphBottom + graphTextPadding/2, graphTextFontSize, GRAY); + + // Draw cosine curve + DrawSplineLinear(cosineCurvePoints, graphWidth, 2, cosineColor); + DrawText("cos", graphRight + graphTextPadding, cosineCurvePoints[graphWidth - 1].y - graphTextFontSize/2, graphTextFontSize, cosineColor); + + // Draw sine curve + DrawSplineLinear(sineCurvePoints, graphWidth, 2, sineColor); + DrawText("sin", graphRight + graphTextPadding, sineCurvePoints[graphWidth - 1].y - graphTextFontSize/2, graphTextFontSize, sineColor); + + // Draw graph progress line + int x = graphLeft + graphWidth*angleInDegrees/360.0f; + DrawLine(x, graphBottom, x, graphTop, BLUE); + + // Draw cosine and sine points on graph + int cosineY = graphYMiddle - cosine*graphHalfHeight; + int sineY = graphYMiddle - sine*graphHalfHeight; + DrawCircle(x, cosineY, pointsSize, cosineColor); + DrawText(TextFormat("%.3f", cosine), x - circleTextMaxLength/2, cosineY - circleTextFontSize - 5, circleTextFontSize, cosineColor); + DrawCircle(x, sineY, pointsSize, sineColor); + DrawText(TextFormat("%.3f", sine), x - circleTextMaxLength/2, sineY + 8, circleTextFontSize, sineColor); + // -------------------- + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + free(cosineCurvePoints); + free(sineCurvePoints); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + 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 000000000..4bac572fa Binary files /dev/null and b/examples/shapes/shapes_math_sine_cosine.png differ