Gitignore zig crap
@ -0,0 +1,263 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* reasings - raylib easings library, based on Robert Penner library
|
||||
*
|
||||
* Useful easing functions for values animation
|
||||
*
|
||||
* This header uses:
|
||||
* #define REASINGS_STATIC_INLINE // Inlines all functions code, so it runs faster.
|
||||
* // This requires lots of memory on system.
|
||||
* How to use:
|
||||
* The four inputs t,b,c,d are defined as follows:
|
||||
* t = current time (in any unit measure, but same unit as duration)
|
||||
* b = starting value to interpolate
|
||||
* c = the total change in value of b that needs to occur
|
||||
* d = total time it should take to complete (duration)
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* int currentTime = 0;
|
||||
* int duration = 100;
|
||||
* float startPositionX = 0.0f;
|
||||
* float finalPositionX = 30.0f;
|
||||
* float currentPositionX = startPositionX;
|
||||
*
|
||||
* while (currentPositionX < finalPositionX)
|
||||
* {
|
||||
* currentPositionX = EaseSineIn(currentTime, startPositionX, finalPositionX - startPositionX, duration);
|
||||
* currentTime++;
|
||||
* }
|
||||
*
|
||||
* A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/)
|
||||
*
|
||||
* Robert Penner License
|
||||
* ---------------------------------------------------------------------------------
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright (c) 2001 Robert Penner. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ---------------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2015-2024 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||
* in the product documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
* as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#ifndef REASINGS_H
|
||||
#define REASINGS_H
|
||||
|
||||
#define REASINGS_STATIC_INLINE // NOTE: By default, compile functions as static inline
|
||||
|
||||
#if defined(REASINGS_STATIC_INLINE)
|
||||
#define EASEDEF static inline
|
||||
#else
|
||||
#define EASEDEF extern
|
||||
#endif
|
||||
|
||||
#include <math.h> // Required for: sinf(), cosf(), sqrtf(), powf()
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846f //Required as PI is not always defined in math.h
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
|
||||
// Linear Easing functions
|
||||
EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear
|
||||
EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear In
|
||||
EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear Out
|
||||
EASEDEF float EaseLinearInOut(float t, float b, float c, float d) { return (c*t/d + b); } // Ease: Linear In Out
|
||||
|
||||
// Sine Easing functions
|
||||
EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cosf(t/d*(PI/2.0f)) + c + b); } // Ease: Sine In
|
||||
EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sinf(t/d*(PI/2.0f)) + b); } // Ease: Sine Out
|
||||
EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2.0f*(cosf(PI*t/d) - 1.0f) + b); } // Ease: Sine In Out
|
||||
|
||||
// Circular Easing functions
|
||||
EASEDEF float EaseCircIn(float t, float b, float c, float d) { t /= d; return (-c*(sqrtf(1.0f - t*t) - 1.0f) + b); } // Ease: Circular In
|
||||
EASEDEF float EaseCircOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*sqrtf(1.0f - t*t) + b); } // Ease: Circular Out
|
||||
EASEDEF float EaseCircInOut(float t, float b, float c, float d) // Ease: Circular In Out
|
||||
{
|
||||
if ((t/=d/2.0f) < 1.0f) return (-c/2.0f*(sqrtf(1.0f - t*t) - 1.0f) + b);
|
||||
t -= 2.0f; return (c/2.0f*(sqrtf(1.0f - t*t) + 1.0f) + b);
|
||||
}
|
||||
|
||||
// Cubic Easing functions
|
||||
EASEDEF float EaseCubicIn(float t, float b, float c, float d) { t /= d; return (c*t*t*t + b); } // Ease: Cubic In
|
||||
EASEDEF float EaseCubicOut(float t, float b, float c, float d) { t = t/d - 1.0f; return (c*(t*t*t + 1.0f) + b); } // Ease: Cubic Out
|
||||
EASEDEF float EaseCubicInOut(float t, float b, float c, float d) // Ease: Cubic In Out
|
||||
{
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*t*t*t + b);
|
||||
t -= 2.0f; return (c/2.0f*(t*t*t + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Quadratic Easing functions
|
||||
EASEDEF float EaseQuadIn(float t, float b, float c, float d) { t /= d; return (c*t*t + b); } // Ease: Quadratic In
|
||||
EASEDEF float EaseQuadOut(float t, float b, float c, float d) { t /= d; return (-c*t*(t - 2.0f) + b); } // Ease: Quadratic Out
|
||||
EASEDEF float EaseQuadInOut(float t, float b, float c, float d) // Ease: Quadratic In Out
|
||||
{
|
||||
if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
|
||||
return (-c/2.0f*(((t - 1.0f)*(t - 3.0f)) - 1.0f) + b);
|
||||
}
|
||||
|
||||
// Exponential Easing functions
|
||||
EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0.0f) ? b : (c*powf(2.0f, 10.0f*(t/d - 1.0f)) + b); } // Ease: Exponential In
|
||||
EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-powf(2.0f, -10.0f*t/d) + 1.0f) + b); } // Ease: Exponential Out
|
||||
EASEDEF float EaseExpoInOut(float t, float b, float c, float d) // Ease: Exponential In Out
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if (t == d) return (b + c);
|
||||
if ((t/=d/2.0f) < 1.0f) return (c/2.0f*powf(2.0f, 10.0f*(t - 1.0f)) + b);
|
||||
|
||||
return (c/2.0f*(-powf(2.0f, -10.0f*(t - 1.0f)) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Back Easing functions
|
||||
EASEDEF float EaseBackIn(float t, float b, float c, float d) // Ease: Back In
|
||||
{
|
||||
float s = 1.70158f;
|
||||
float postFix = t/=d;
|
||||
return (c*(postFix)*t*((s + 1.0f)*t - s) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackOut(float t, float b, float c, float d) // Ease: Back Out
|
||||
{
|
||||
float s = 1.70158f;
|
||||
t = t/d - 1.0f;
|
||||
return (c*(t*t*((s + 1.0f)*t + s) + 1.0f) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseBackInOut(float t, float b, float c, float d) // Ease: Back In Out
|
||||
{
|
||||
float s = 1.70158f;
|
||||
if ((t/=d/2.0f) < 1.0f)
|
||||
{
|
||||
s *= 1.525f;
|
||||
return (c/2.0f*(t*t*((s + 1.0f)*t - s)) + b);
|
||||
}
|
||||
|
||||
float postFix = t-=2.0f;
|
||||
s *= 1.525f;
|
||||
return (c/2.0f*((postFix)*t*((s + 1.0f)*t + s) + 2.0f) + b);
|
||||
}
|
||||
|
||||
// Bounce Easing functions
|
||||
EASEDEF float EaseBounceOut(float t, float b, float c, float d) // Ease: Bounce Out
|
||||
{
|
||||
if ((t/=d) < (1.0f/2.75f))
|
||||
{
|
||||
return (c*(7.5625f*t*t) + b);
|
||||
}
|
||||
else if (t < (2.0f/2.75f))
|
||||
{
|
||||
float postFix = t-=(1.5f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.75f) + b);
|
||||
}
|
||||
else if (t < (2.5/2.75))
|
||||
{
|
||||
float postFix = t-=(2.25f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.9375f) + b);
|
||||
}
|
||||
else
|
||||
{
|
||||
float postFix = t-=(2.625f/2.75f);
|
||||
return (c*(7.5625f*(postFix)*t + 0.984375f) + b);
|
||||
}
|
||||
}
|
||||
|
||||
EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d - t, 0.0f, c, d) + b); } // Ease: Bounce In
|
||||
EASEDEF float EaseBounceInOut(float t, float b, float c, float d) // Ease: Bounce In Out
|
||||
{
|
||||
if (t < d/2.0f) return (EaseBounceIn(t*2.0f, 0.0f, c, d)*0.5f + b);
|
||||
else return (EaseBounceOut(t*2.0f - d, 0.0f, c, d)*0.5f + c*0.5f + b);
|
||||
}
|
||||
|
||||
// Elastic Easing functions
|
||||
EASEDEF float EaseElasticIn(float t, float b, float c, float d) // Ease: Elastic In
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
float postFix = a*powf(2.0f, 10.0f*(t-=1.0f));
|
||||
|
||||
return (-(postFix*sinf((t*d-s)*(2.0f*PI)/p )) + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticOut(float t, float b, float c, float d) // Ease: Elastic Out
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d) == 1.0f) return (b + c);
|
||||
|
||||
float p = d*0.3f;
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
|
||||
return (a*powf(2.0f,-10.0f*t)*sinf((t*d-s)*(2.0f*PI)/p) + c + b);
|
||||
}
|
||||
|
||||
EASEDEF float EaseElasticInOut(float t, float b, float c, float d) // Ease: Elastic In Out
|
||||
{
|
||||
if (t == 0.0f) return b;
|
||||
if ((t/=d/2.0f) == 2.0f) return (b + c);
|
||||
|
||||
float p = d*(0.3f*1.5f);
|
||||
float a = c;
|
||||
float s = p/4.0f;
|
||||
|
||||
if (t < 1.0f)
|
||||
{
|
||||
float postFix = a*powf(2.0f, 10.0f*(t-=1.0f));
|
||||
return -0.5f*(postFix*sinf((t*d-s)*(2.0f*PI)/p)) + b;
|
||||
}
|
||||
|
||||
float postFix = a*powf(2.0f, -10.0f*(t-=1.0f));
|
||||
|
||||
return (postFix*sinf((t*d-s)*(2.0f*PI)/p)*0.5f + c + b);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // REASINGS_H
|
||||
@ -0,0 +1,229 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - ball physics
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by David Buzatto (@davidbuzatto) 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 David Buzatto (@davidbuzatto)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for: malloc(), free()
|
||||
#include <math.h> // Required for: hypot()
|
||||
|
||||
#define MAX_BALLS 5000 // Maximum quantity of balls
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Ball data type
|
||||
typedef struct Ball {
|
||||
Vector2 position;
|
||||
Vector2 speed;
|
||||
Vector2 prevPosition;
|
||||
float radius;
|
||||
float friction;
|
||||
float elasticity;
|
||||
Color color;
|
||||
bool grabbed;
|
||||
} Ball;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ball physics");
|
||||
|
||||
Ball *balls = (Ball*)RL_MALLOC(sizeof(Ball)*MAX_BALLS);
|
||||
|
||||
// Init first ball in the array
|
||||
balls[0] = (Ball){
|
||||
.position = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f },
|
||||
.speed = { 200, 200 },
|
||||
.prevPosition = { 0 },
|
||||
.radius = 40,
|
||||
.friction = 0.99f,
|
||||
.elasticity = 0.9f,
|
||||
.color = BLUE,
|
||||
.grabbed = false
|
||||
};
|
||||
|
||||
int ballCount = 1;
|
||||
Ball *grabbedBall = NULL; // A pointer to the current ball that is grabbed
|
||||
Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd
|
||||
|
||||
float gravity = 100; // World gravity
|
||||
|
||||
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 delta = GetFrameTime();
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
|
||||
// Checks if a ball was grabbed
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
for (int i = ballCount - 1; i >= 0; i--)
|
||||
{
|
||||
Ball *ball = &balls[i];
|
||||
pressOffset.x = mousePos.x - ball->position.x;
|
||||
pressOffset.y = mousePos.y - ball->position.y;
|
||||
|
||||
// If the distance between the ball position and the mouse press position
|
||||
// is less than or equal to the ball radius, the event occurred inside the ball
|
||||
if (hypot(pressOffset.x, pressOffset.y) <= ball->radius)
|
||||
{
|
||||
ball->grabbed = true;
|
||||
grabbedBall = ball;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Releases any ball the was grabbed
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
if (grabbedBall != NULL)
|
||||
{
|
||||
grabbedBall->grabbed = false;
|
||||
grabbedBall = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new ball
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) || (IsKeyDown(KEY_LEFT_CONTROL) && IsMouseButtonDown(MOUSE_BUTTON_RIGHT)))
|
||||
{
|
||||
if (ballCount < MAX_BALLS)
|
||||
{
|
||||
balls[ballCount++] = (Ball){
|
||||
.position = mousePos,
|
||||
.speed = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) },
|
||||
.prevPosition = { 0 },
|
||||
.radius = 20.0f + (float)GetRandomValue(0, 30),
|
||||
.friction = 0.99f,
|
||||
.elasticity = 0.9f,
|
||||
.color = { GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 },
|
||||
.grabbed = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Shake balls
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
||||
{
|
||||
for (int i = 0; i < ballCount; i++)
|
||||
{
|
||||
if (!balls[i].grabbed) balls[i].speed = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) };
|
||||
}
|
||||
}
|
||||
|
||||
// Changes gravity
|
||||
gravity += GetMouseWheelMove()*5;
|
||||
|
||||
// Updates each ball state
|
||||
for (int i = 0; i < ballCount; i++)
|
||||
{
|
||||
Ball *ball = &balls[i];
|
||||
|
||||
// The ball is not grabbed
|
||||
if (!ball->grabbed)
|
||||
{
|
||||
// Ball repositioning using the velocity
|
||||
ball->position.x += ball->speed.x * delta;
|
||||
ball->position.y += ball->speed.y * delta;
|
||||
|
||||
// Does the ball hit the screen right boundary?
|
||||
if ((ball->position.x + ball->radius) >= screenWidth)
|
||||
{
|
||||
ball->position.x = screenWidth - ball->radius; // Ball repositioning
|
||||
ball->speed.x = -ball->speed.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit
|
||||
}
|
||||
// Does the ball hit the screen left boundary?
|
||||
else if ((ball->position.x - ball->radius) <= 0)
|
||||
{
|
||||
ball->position.x = ball->radius;
|
||||
ball->speed.x = -ball->speed.x*ball->elasticity;
|
||||
}
|
||||
|
||||
// The same for y axis
|
||||
if ((ball->position.y + ball->radius) >= screenHeight)
|
||||
{
|
||||
ball->position.y = screenHeight - ball->radius;
|
||||
ball->speed.y = -ball->speed.y*ball->elasticity;
|
||||
}
|
||||
else if ((ball->position.y - ball->radius) <= 0)
|
||||
{
|
||||
ball->position.y = ball->radius;
|
||||
ball->speed.y = -ball->speed.y*ball->elasticity;
|
||||
}
|
||||
|
||||
// Friction makes the ball lose 1% of its velocity each frame
|
||||
ball->speed.x = ball->speed.x*ball->friction;
|
||||
// Gravity affects only the y axis
|
||||
ball->speed.y = ball->speed.y*ball->friction + gravity;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ball repositioning using the mouse position
|
||||
ball->position.x = mousePos.x - pressOffset.x;
|
||||
ball->position.y = mousePos.y - pressOffset.y;
|
||||
|
||||
// While the ball is grabbed, recalculates its velocity
|
||||
ball->speed.x = (ball->position.x - ball->prevPosition.x)/delta;
|
||||
ball->speed.y = (ball->position.y - ball->prevPosition.y)/delta;
|
||||
ball->prevPosition = ball->position;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
for (int i = 0; i < ballCount; i++)
|
||||
{
|
||||
DrawCircleV(balls[i].position, balls[i].radius, balls[i].color);
|
||||
DrawCircleLinesV(balls[i].position, balls[i].radius, BLACK);
|
||||
}
|
||||
|
||||
DrawText("grab a ball by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY);
|
||||
DrawText("right click to create new balls (keep left control pressed to create a lot)", 10, 30, 10, DARKGRAY);
|
||||
DrawText("use mouse wheel to change gravity", 10, 50, 10, DARKGRAY);
|
||||
DrawText("middle click to shake", 10, 70, 10, DARKGRAY);
|
||||
DrawText(TextFormat("BALL COUNT: %d", ballCount), 10, GetScreenHeight() - 70, 20, BLACK);
|
||||
DrawText(TextFormat("GRAVITY: %.2f", gravity), 10, GetScreenHeight() - 40, 20, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
RL_FREE(balls);
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,90 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - basic shapes
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 4.2
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes");
|
||||
|
||||
float rotation = 0.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
|
||||
//----------------------------------------------------------------------------------
|
||||
rotation += 0.2f;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("some basic shapes available on raylib", 20, 20, 20, DARKGRAY);
|
||||
|
||||
// Circle shapes and lines
|
||||
DrawCircle(screenWidth/5, 120, 35, DARKBLUE);
|
||||
DrawCircleGradient((Vector2){ screenWidth/5.0f, 220.0f }, 60, GREEN, SKYBLUE);
|
||||
DrawCircleLines(screenWidth/5, 340, 80, DARKBLUE);
|
||||
DrawEllipse(screenWidth/5, 120, 25, 20, YELLOW);
|
||||
DrawEllipseLines(screenWidth/5, 120, 30, 25, YELLOW);
|
||||
|
||||
// Rectangle shapes and lines
|
||||
DrawRectangle(screenWidth/4*2 - 60, 100, 120, 60, RED);
|
||||
DrawRectangleGradientH(screenWidth/4*2 - 90, 170, 180, 130, MAROON, GOLD);
|
||||
DrawRectangleLines(screenWidth/4*2 - 40, 320, 80, 60, ORANGE); // NOTE: Uses QUADS internally, not lines
|
||||
|
||||
// Triangle shapes and lines
|
||||
DrawTriangle((Vector2){ screenWidth/4.0f *3.0f, 80.0f },
|
||||
(Vector2){ screenWidth/4.0f *3.0f - 60.0f, 150.0f },
|
||||
(Vector2){ screenWidth/4.0f *3.0f + 60.0f, 150.0f }, VIOLET);
|
||||
|
||||
DrawTriangleLines((Vector2){ screenWidth/4.0f*3.0f, 160.0f },
|
||||
(Vector2){ screenWidth/4.0f*3.0f - 20.0f, 230.0f },
|
||||
(Vector2){ screenWidth/4.0f*3.0f + 20.0f, 230.0f }, DARKBLUE);
|
||||
|
||||
// Polygon shapes and lines
|
||||
DrawPoly((Vector2){ screenWidth/4.0f*3, 330 }, 6, 80, rotation, BROWN);
|
||||
DrawPolyLines((Vector2){ screenWidth/4.0f*3, 330 }, 6, 90, rotation, BROWN);
|
||||
DrawPolyLinesEx((Vector2){ screenWidth/4.0f*3, 330 }, 6, 85, rotation, 6, BEIGE);
|
||||
|
||||
// NOTE: We draw all LINES based shapes together to optimize internal drawing,
|
||||
// this way, all LINES are rendered in a single draw pass
|
||||
DrawLine(18, 42, screenWidth - 18, 42, BLACK);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
@ -0,0 +1,94 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - bouncing ball
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Ramon Santamaria (@raysan5), reviewed 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) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//---------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bouncing ball");
|
||||
|
||||
Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
|
||||
Vector2 ballSpeed = { 5.0f, 4.0f };
|
||||
int ballRadius = 20;
|
||||
float gravity = 0.2f;
|
||||
|
||||
bool useGravity = true;
|
||||
bool pause = 0;
|
||||
int framesCounter = 0;
|
||||
|
||||
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
|
||||
//-----------------------------------------------------
|
||||
if (IsKeyPressed(KEY_G)) useGravity = !useGravity;
|
||||
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
|
||||
|
||||
if (!pause)
|
||||
{
|
||||
ballPosition.x += ballSpeed.x;
|
||||
ballPosition.y += ballSpeed.y;
|
||||
|
||||
if (useGravity) ballSpeed.y += gravity;
|
||||
|
||||
// Check walls collision for bouncing
|
||||
if ((ballPosition.x >= (GetScreenWidth() - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f;
|
||||
if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -0.95f;
|
||||
}
|
||||
else framesCounter++;
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawCircleV(ballPosition, (float)ballRadius, MAROON);
|
||||
DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
|
||||
|
||||
if (useGravity) DrawText("GRAVITY: ON (Press G to disable)", 10, GetScreenHeight() - 50, 20, DARKGREEN);
|
||||
else DrawText("GRAVITY: OFF (Press G to enable)", 10, GetScreenHeight() - 50, 20, RED);
|
||||
|
||||
// On pause, we draw a blinking message
|
||||
if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//-----------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//---------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.3 KiB |
@ -0,0 +1,248 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - bullet hell
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.6, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Zero (@zerohorsepower) 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 Zero (@zerohorsepower)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
#include <math.h> // Required for: cosf(), sinf()
|
||||
|
||||
#define MAX_BULLETS 500000 // Max bullets to be processed
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct Bullet {
|
||||
Vector2 position; // Bullet position on screen
|
||||
Vector2 acceleration; // Amount of pixels to be incremented to position every frame
|
||||
bool disabled; // Skip processing and draw case out of screen
|
||||
Color color; // Bullet color
|
||||
} Bullet;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bullet hell");
|
||||
|
||||
// Bullets definition
|
||||
Bullet *bullets = (Bullet *)RL_CALLOC(MAX_BULLETS, sizeof(Bullet)); // Bullets array
|
||||
int bulletCount = 0;
|
||||
int bulletDisabledCount = 0; // Used to calculate how many bullets are on screen
|
||||
int bulletRadius = 10;
|
||||
float bulletSpeed = 3.0f;
|
||||
int bulletRows = 6;
|
||||
Color bulletColor[2] = { RED, BLUE };
|
||||
|
||||
// Spawner variables
|
||||
float baseDirection = 0;
|
||||
int angleIncrement = 5; // After spawn all bullet rows, increment this value on the baseDirection for next the frame
|
||||
float spawnCooldown = 2;
|
||||
float spawnCooldownTimer = spawnCooldown;
|
||||
|
||||
// Magic circle
|
||||
float magicCircleRotation = 0;
|
||||
|
||||
// Used on performance drawing
|
||||
RenderTexture bulletTexture = LoadRenderTexture(24, 24);
|
||||
|
||||
// Draw circle to bullet texture, then draw bullet using DrawTexture()
|
||||
// NOTE: This is done to improve the performance, since DrawCircle() is very slow
|
||||
BeginTextureMode(bulletTexture);
|
||||
DrawCircle(12, 12, (float)bulletRadius, WHITE);
|
||||
DrawCircleLines(12, 12, (float)bulletRadius, BLACK);
|
||||
EndTextureMode();
|
||||
|
||||
bool drawInPerformanceMode = true; // Switch between DrawCircle() and DrawTexture()
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Reset the bullet index
|
||||
// New bullets will replace the old ones that are already disabled due to out-of-screen
|
||||
if (bulletCount >= MAX_BULLETS)
|
||||
{
|
||||
bulletCount = 0;
|
||||
bulletDisabledCount = 0;
|
||||
}
|
||||
|
||||
spawnCooldownTimer--;
|
||||
if (spawnCooldownTimer < 0)
|
||||
{
|
||||
spawnCooldownTimer = spawnCooldown;
|
||||
|
||||
// Spawn bullets
|
||||
float degreesPerRow = 360.0f/bulletRows;
|
||||
for (int row = 0; row < bulletRows; row++)
|
||||
{
|
||||
if (bulletCount < MAX_BULLETS)
|
||||
{
|
||||
bullets[bulletCount].position = (Vector2){(float) screenWidth/2, (float) screenHeight/2};
|
||||
bullets[bulletCount].disabled = false;
|
||||
bullets[bulletCount].color = bulletColor[row%2];
|
||||
|
||||
float bulletDirection = baseDirection + (degreesPerRow*row);
|
||||
|
||||
// Bullet speed*bullet direction, this will determine how much pixels will be incremented/decremented
|
||||
// from the bullet position every frame. Since the bullets doesn't change its direction and speed,
|
||||
// only need to calculate it at the spawning time
|
||||
// 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise
|
||||
// Case you want it to be anti-clockwise, add "* -1" at the y acceleration
|
||||
bullets[bulletCount].acceleration = (Vector2){
|
||||
bulletSpeed*cosf(bulletDirection*DEG2RAD),
|
||||
bulletSpeed*sinf(bulletDirection*DEG2RAD)
|
||||
};
|
||||
|
||||
bulletCount++;
|
||||
}
|
||||
}
|
||||
|
||||
baseDirection += angleIncrement;
|
||||
}
|
||||
|
||||
// Update bullets position based on its acceleration
|
||||
for (int i = 0; i < bulletCount; i++)
|
||||
{
|
||||
// Only update bullet if inside the screen
|
||||
if (!bullets[i].disabled)
|
||||
{
|
||||
bullets[i].position.x += bullets[i].acceleration.x;
|
||||
bullets[i].position.y += bullets[i].acceleration.y;
|
||||
|
||||
// Disable bullet if out of screen
|
||||
if ((bullets[i].position.x < -bulletRadius*2) ||
|
||||
(bullets[i].position.x > screenWidth + bulletRadius*2) ||
|
||||
(bullets[i].position.y < -bulletRadius*2) ||
|
||||
(bullets[i].position.y > screenHeight + bulletRadius*2))
|
||||
{
|
||||
bullets[i].disabled = true;
|
||||
bulletDisabledCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input logic
|
||||
if ((IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_D)) && (bulletRows < 359)) bulletRows++;
|
||||
if ((IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_A)) && (bulletRows > 1)) bulletRows--;
|
||||
if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) bulletSpeed += 0.25f;
|
||||
if ((IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) && (bulletSpeed > 0.50f)) bulletSpeed -= 0.25f;
|
||||
if (IsKeyPressed(KEY_Z) && (spawnCooldown > 1)) spawnCooldown--;
|
||||
if (IsKeyPressed(KEY_X)) spawnCooldown++;
|
||||
if (IsKeyPressed(KEY_ENTER)) drawInPerformanceMode = !drawInPerformanceMode;
|
||||
|
||||
if (IsKeyDown(KEY_SPACE))
|
||||
{
|
||||
angleIncrement += 1;
|
||||
angleIncrement %= 360;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_C))
|
||||
{
|
||||
bulletCount = 0;
|
||||
bulletDisabledCount = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw magic circle
|
||||
magicCircleRotation++;
|
||||
DrawRectanglePro((Rectangle){ (float)screenWidth/2, (float)screenHeight/2, 120, 120 },
|
||||
(Vector2){ 60.0f, 60.0f }, magicCircleRotation, PURPLE);
|
||||
DrawRectanglePro((Rectangle){ (float)screenWidth/2, (float)screenHeight/2, 120, 120 },
|
||||
(Vector2){ 60.0f, 60.0f }, magicCircleRotation + 45, PURPLE);
|
||||
DrawCircleLines(screenWidth/2, screenHeight/2, 70, BLACK);
|
||||
DrawCircleLines(screenWidth/2, screenHeight/2, 50, BLACK);
|
||||
DrawCircleLines(screenWidth/2, screenHeight/2, 30, BLACK);
|
||||
|
||||
// Draw bullets
|
||||
if (drawInPerformanceMode)
|
||||
{
|
||||
// Draw bullets using pre-rendered texture containing circle
|
||||
for (int i = 0; i < bulletCount; i++)
|
||||
{
|
||||
// Do not draw disabled bullets (out of screen)
|
||||
if (!bullets[i].disabled)
|
||||
{
|
||||
DrawTexture(bulletTexture.texture,
|
||||
(int)(bullets[i].position.x - bulletTexture.texture.width*0.5f),
|
||||
(int)(bullets[i].position.y - bulletTexture.texture.height*0.5f),
|
||||
bullets[i].color);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw bullets using DrawCircle(), less performant
|
||||
for (int i = 0; i < bulletCount; i++)
|
||||
{
|
||||
// Do not draw disabled bullets (out of screen)
|
||||
if (!bullets[i].disabled)
|
||||
{
|
||||
DrawCircleV(bullets[i].position, (float)bulletRadius, bullets[i].color);
|
||||
DrawCircleLinesV(bullets[i].position, (float)bulletRadius, BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw UI
|
||||
DrawRectangle(10, 10, 280, 150, (Color){0,0, 0, 200 });
|
||||
DrawText("Controls:", 20, 20, 10, LIGHTGRAY);
|
||||
DrawText("- Right/Left or A/D: Change rows number", 40, 40, 10, LIGHTGRAY);
|
||||
DrawText("- Up/Down or W/S: Change bullet speed", 40, 60, 10, LIGHTGRAY);
|
||||
DrawText("- Z or X: Change spawn cooldown", 40, 80, 10, LIGHTGRAY);
|
||||
DrawText("- Space (Hold): Change the angle increment", 40, 100, 10, LIGHTGRAY);
|
||||
DrawText("- Enter: Switch draw method (Performance)", 40, 120, 10, LIGHTGRAY);
|
||||
DrawText("- C: Clear bullets", 40, 140, 10, LIGHTGRAY);
|
||||
|
||||
DrawRectangle(610, 10, 170, 30, (Color){0,0, 0, 200 });
|
||||
if (drawInPerformanceMode) DrawText("Draw method: DrawTexture(*)", 620, 20, 10, GREEN);
|
||||
else DrawText("Draw method: DrawCircle(*)", 620, 20, 10, RED);
|
||||
|
||||
DrawRectangle(135, 410, 530, 30, (Color){0,0, 0, 200 });
|
||||
DrawText(TextFormat("[ FPS: %d, Bullets: %d, Rows: %d, Bullet speed: %.2f, Angle increment per frame: %d, Cooldown: %.0f ]",
|
||||
GetFPS(), bulletCount - bulletDisabledCount, bulletRows, bulletSpeed, angleIncrement, spawnCooldown),
|
||||
155, 420, 10, GREEN);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(bulletTexture); // Unload bullet texture
|
||||
|
||||
RL_FREE(bullets); // Free bullets array data
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 38 KiB |
@ -0,0 +1,90 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - circle sector drawing
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) 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) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - circle sector drawing");
|
||||
|
||||
Vector2 center = {(GetScreenWidth() - 300)/2.0f, GetScreenHeight()/2.0f };
|
||||
|
||||
float outerRadius = 180.0f;
|
||||
float startAngle = 0.0f;
|
||||
float endAngle = 180.0f;
|
||||
float segments = 10.0f;
|
||||
float minSegments = 4;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
// NOTE: All variables update happens inside GUI control functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawLine(500, 0, 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.6f));
|
||||
DrawRectangle(500, 0, GetScreenWidth() - 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawCircleSector(center, outerRadius, startAngle, endAngle, (int)segments, Fade(MAROON, 0.3f));
|
||||
DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, (int)segments, Fade(MAROON, 0.6f));
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
GuiSliderBar((Rectangle){ 600, 40, 120, 20}, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, 0, 720);
|
||||
GuiSliderBar((Rectangle){ 600, 70, 120, 20}, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, 0, 720);
|
||||
|
||||
GuiSliderBar((Rectangle){ 600, 140, 120, 20}, "Radius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200);
|
||||
GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 100);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
minSegments = truncf(ceilf((endAngle - startAngle)/90));
|
||||
DrawText(TextFormat("MODE: %s", (segments >= minSegments)? "MANUAL" : "AUTO"), 600, 200, 10, (segments >= minSegments)? MAROON : DARKGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,205 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - clock of clocks
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
*
|
||||
* 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()
|
||||
#include <time.h> // Required for: time(), localtime()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - clock of clocks");
|
||||
|
||||
const Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.75f);
|
||||
const Color handsColor = ColorLerp(YELLOW, RAYWHITE, .25f);
|
||||
|
||||
const float clockFaceSize = 24;
|
||||
const float clockFaceSpacing = 8.0f;
|
||||
const float sectionSpacing = 16.0f;
|
||||
|
||||
const Vector2 TL = (Vector2){ 0.0f, 90.0f }; // Top-left corner
|
||||
const Vector2 TR = (Vector2){ 90.0f, 180.0f }; // Top-right corner
|
||||
const Vector2 BR = (Vector2){ 180.0f, 270.0f }; // Bottom-right corner
|
||||
const Vector2 BL = (Vector2){ 0.0f, 270.0f }; // Bottom-left corner
|
||||
const Vector2 HH = (Vector2){ 0.0f, 180.0f }; // Horizontal line
|
||||
const Vector2 VV = (Vector2){ 90.0f, 270.0f }; // Vertical line
|
||||
const Vector2 ZZ = (Vector2){ 135.0f, 135.0f }; // Not relevant
|
||||
|
||||
const Vector2 digitAngles[10][24] = {
|
||||
/* 0 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,VV,VV,VV,/* */ VV,VV,VV,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR },
|
||||
/* 1 */ { TL,HH,TR,ZZ, /* */ BL,TR,VV,ZZ,/* */ ZZ,VV,VV,ZZ,/* */ ZZ,VV,VV,ZZ,/* */ TL,BR,BL,TR,/* */ BL,HH,HH,BR },
|
||||
/* 2 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ BL,HH,HH,BR },
|
||||
/* 3 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR },
|
||||
/* 4 */ { TL,TR,TL,TR, /* */ VV,VV,VV,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,BL,BR },
|
||||
/* 5 */ { TL,HH,HH,TR, /* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR },
|
||||
/* 6 */ { TL,HH,HH,TR, /* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR },
|
||||
/* 7 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,BL,BR },
|
||||
/* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR },
|
||||
/* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR },
|
||||
};
|
||||
|
||||
// Time for the hands to move to the new position (in seconds); this must be <1s
|
||||
const float handsMoveDuration = 0.5f;
|
||||
|
||||
int prevSeconds = -1;
|
||||
Vector2 currentAngles[6][24] = { 0 };
|
||||
Vector2 srcAngles[6][24] = { 0 };
|
||||
Vector2 dstAngles[6][24] = { 0 };
|
||||
|
||||
float handsMoveTimer = 0.0f;
|
||||
int hourMode = 24;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
// Get the current time
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
if (timeinfo->tm_sec != prevSeconds)
|
||||
{
|
||||
// The time has changed, so we need to move the hands to the new positions
|
||||
prevSeconds = timeinfo->tm_sec;
|
||||
|
||||
// Format the current time so we can access the individual digits
|
||||
const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour%hourMode, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
|
||||
// Fetch where we want all the hands to be
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int cell = 0; cell < 24; cell++)
|
||||
{
|
||||
srcAngles[digit][cell] = currentAngles[digit][cell];
|
||||
dstAngles[digit][cell] = digitAngles[clockDigits[digit] - '0'][cell];
|
||||
|
||||
// Quick exception for 12h mode
|
||||
if ((digit == 0) && (hourMode == 12) && (clockDigits[0] == '0')) dstAngles[digit][cell] = ZZ;
|
||||
if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) srcAngles[digit][cell].x -= 360.0f;
|
||||
if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) srcAngles[digit][cell].y -= 360.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the timer
|
||||
handsMoveTimer = -GetFrameTime();
|
||||
}
|
||||
|
||||
// Now let's animate all the hands if we need to
|
||||
if (handsMoveTimer < handsMoveDuration)
|
||||
{
|
||||
// Increase the timer but don't go above the maximum
|
||||
handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration);
|
||||
|
||||
// Calculate the%completion of the animation
|
||||
float t = handsMoveTimer/handsMoveDuration;
|
||||
|
||||
// A little cheeky smoothstep
|
||||
t = t*t*(3.0f - 2.0f*t);
|
||||
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int cell = 0; cell < 24; cell++)
|
||||
{
|
||||
currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t);
|
||||
currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle input
|
||||
if (IsKeyPressed(KEY_SPACE)) hourMode = 36 - hourMode; // Toggle between 12 and 24 hour mode with space
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(bgColor);
|
||||
|
||||
DrawText(TextFormat("%d-h mode, space to change", hourMode), 10, 30, 20, RAYWHITE);
|
||||
|
||||
float xOffset = 4.0f;
|
||||
|
||||
for (int digit = 0; digit < 6; digit++)
|
||||
{
|
||||
for (int row = 0; row < 6; row++)
|
||||
{
|
||||
for (int col = 0; col < 4; col++)
|
||||
{
|
||||
Vector2 centre = (Vector2){
|
||||
xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f,
|
||||
100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f
|
||||
};
|
||||
|
||||
DrawRing(centre, clockFaceSize*0.5f - 2.0f, clockFaceSize*0.5f, 0, 360, 24, DARKGRAY);
|
||||
|
||||
// Big hand
|
||||
DrawRectanglePro(
|
||||
(Rectangle){centre.x, centre.y, clockFaceSize*0.5f+4.0f, 4.0f},
|
||||
(Vector2){ 2.0f, 2.0f },
|
||||
currentAngles[digit][row*4+col].x,
|
||||
handsColor
|
||||
);
|
||||
|
||||
// Little hand
|
||||
DrawRectanglePro(
|
||||
(Rectangle){centre.x, centre.y, clockFaceSize*0.5f+2.0f, 4.0f},
|
||||
(Vector2){ 2.0f, 2.0f },
|
||||
currentAngles[digit][row*4+col].y,
|
||||
handsColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
xOffset += (clockFaceSize+clockFaceSpacing)*4;
|
||||
if (digit%2 == 1)
|
||||
{
|
||||
DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
|
||||
DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
|
||||
xOffset += sectionSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,117 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - collision area
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//---------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision area");
|
||||
|
||||
// Box A: Moving box
|
||||
Rectangle boxA = { 10, GetScreenHeight()/2.0f - 50, 200, 100 };
|
||||
int boxASpeedX = 4;
|
||||
|
||||
// Box B: Mouse moved box
|
||||
Rectangle boxB = { GetScreenWidth()/2.0f - 30, GetScreenHeight()/2.0f - 30, 60, 60 };
|
||||
|
||||
Rectangle boxCollision = { 0 }; // Collision rectangle
|
||||
|
||||
int screenUpperLimit = 40; // Top menu limits
|
||||
|
||||
bool pause = false; // Movement pause
|
||||
bool collision = false; // Collision detection
|
||||
|
||||
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
|
||||
//-----------------------------------------------------
|
||||
// Move box if not paused
|
||||
if (!pause) boxA.x += boxASpeedX;
|
||||
|
||||
// Bounce box on x screen limits
|
||||
if (((boxA.x + boxA.width) >= GetScreenWidth()) || (boxA.x <= 0)) boxASpeedX *= -1;
|
||||
|
||||
// Update player-controlled-box (box02)
|
||||
boxB.x = GetMouseX() - boxB.width/2;
|
||||
boxB.y = GetMouseY() - boxB.height/2;
|
||||
|
||||
// Make sure Box B does not go out of move area limits
|
||||
if ((boxB.x + boxB.width) >= GetScreenWidth()) boxB.x = GetScreenWidth() - boxB.width;
|
||||
else if (boxB.x <= 0) boxB.x = 0;
|
||||
|
||||
if ((boxB.y + boxB.height) >= GetScreenHeight()) boxB.y = GetScreenHeight() - boxB.height;
|
||||
else if (boxB.y <= screenUpperLimit) boxB.y = (float)screenUpperLimit;
|
||||
|
||||
// Check boxes collision
|
||||
collision = CheckCollisionRecs(boxA, boxB);
|
||||
|
||||
// Get collision rectangle (only on collision)
|
||||
if (collision) boxCollision = GetCollisionRec(boxA, boxB);
|
||||
|
||||
// Pause Box A movement
|
||||
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawRectangle(0, 0, screenWidth, screenUpperLimit, collision? RED : BLACK);
|
||||
|
||||
DrawRectangleRec(boxA, GOLD);
|
||||
DrawRectangleRec(boxB, BLUE);
|
||||
|
||||
if (collision)
|
||||
{
|
||||
// Draw collision area
|
||||
DrawRectangleRec(boxCollision, LIME);
|
||||
|
||||
// Draw collision message
|
||||
DrawText("COLLISION!", GetScreenWidth()/2 - MeasureText("COLLISION!", 20)/2, screenUpperLimit/2 - 10, 20, BLACK);
|
||||
|
||||
// Draw collision area
|
||||
DrawText(TextFormat("Collision Area: %i", (int)boxCollision.width*(int)boxCollision.height), GetScreenWidth()/2 - 100, screenUpperLimit + 10, 20, BLACK);
|
||||
}
|
||||
|
||||
// Draw help instructions
|
||||
DrawText("Press SPACE to PAUSE/RESUME", 20, screenHeight - 35, 20, LIGHTGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//-----------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//---------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,106 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - colors palette
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MAX_COLORS_COUNT 21 // Number of colors available
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - colors palette");
|
||||
|
||||
Color colors[MAX_COLORS_COUNT] = {
|
||||
DARKGRAY, MAROON, ORANGE, DARKGREEN, DARKBLUE, DARKPURPLE, DARKBROWN,
|
||||
GRAY, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK, YELLOW,
|
||||
GREEN, SKYBLUE, PURPLE, BEIGE };
|
||||
|
||||
const char *colorNames[MAX_COLORS_COUNT] = {
|
||||
"DARKGRAY", "MAROON", "ORANGE", "DARKGREEN", "DARKBLUE", "DARKPURPLE",
|
||||
"DARKBROWN", "GRAY", "RED", "GOLD", "LIME", "BLUE", "VIOLET", "BROWN",
|
||||
"LIGHTGRAY", "PINK", "YELLOW", "GREEN", "SKYBLUE", "PURPLE", "BEIGE" };
|
||||
|
||||
Rectangle colorsRecs[MAX_COLORS_COUNT] = { 0 }; // Rectangles array
|
||||
|
||||
// Fills colorsRecs data (for every rectangle)
|
||||
for (int i = 0; i < MAX_COLORS_COUNT; i++)
|
||||
{
|
||||
colorsRecs[i].x = 20.0f + 100.0f *(i%7) + 10.0f *(i%7);
|
||||
colorsRecs[i].y = 80.0f + 100.0f *((int)i/7) + 10.0f *((float)i/7);
|
||||
colorsRecs[i].width = 100.0f;
|
||||
colorsRecs[i].height = 100.0f;
|
||||
}
|
||||
|
||||
int colorState[MAX_COLORS_COUNT] = { 0 }; // Color state: 0-DEFAULT, 1-MOUSE_HOVER
|
||||
|
||||
Vector2 mousePoint = { 0.0f, 0.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
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePoint = GetMousePosition();
|
||||
|
||||
for (int i = 0; i < MAX_COLORS_COUNT; i++)
|
||||
{
|
||||
if (CheckCollisionPointRec(mousePoint, colorsRecs[i])) colorState[i] = 1;
|
||||
else colorState[i] = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("raylib colors palette", 28, 42, 20, BLACK);
|
||||
DrawText("press SPACE to see all colors", GetScreenWidth() - 180, GetScreenHeight() - 40, 10, GRAY);
|
||||
|
||||
for (int i = 0; i < MAX_COLORS_COUNT; i++) // Draw all rectangles
|
||||
{
|
||||
DrawRectangleRec(colorsRecs[i], Fade(colors[i], colorState[i]? 0.6f : 1.0f));
|
||||
|
||||
if (IsKeyDown(KEY_SPACE) || colorState[i])
|
||||
{
|
||||
DrawRectangle((int)colorsRecs[i].x, (int)(colorsRecs[i].y + colorsRecs[i].height - 26), (int)colorsRecs[i].width, 20, BLACK);
|
||||
DrawRectangleLinesEx(colorsRecs[i], 6, Fade(BLACK, 0.3f));
|
||||
DrawText(colorNames[i], (int)(colorsRecs[i].x + colorsRecs[i].width - MeasureText(colorNames[i], 10) - 12),
|
||||
(int)(colorsRecs[i].y + colorsRecs[i].height - 20), 10, colors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,96 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - dashed line
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Luís Almeida (@luis605)
|
||||
*
|
||||
* 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 Luís Almeida (@luis605)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - dashed line");
|
||||
|
||||
// Line Properties
|
||||
Vector2 lineStartPosition = { 20.0f, 50.0f };
|
||||
Vector2 lineEndPosition = { 780.0f, 400.0f };
|
||||
float dashLength = 25.0f;
|
||||
float blankLength = 15.0f;
|
||||
|
||||
// Color selection
|
||||
Color lineColors[] = { RED, ORANGE, GOLD, GREEN, BLUE, VIOLET, PINK, BLACK };
|
||||
int colorIndex = 0;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
lineEndPosition = GetMousePosition(); // Line endpoint follows the mouse
|
||||
|
||||
// Change Dash Length (UP/DOWN arrows)
|
||||
if (IsKeyDown(KEY_UP)) dashLength += 1.0f;
|
||||
if (IsKeyDown(KEY_DOWN) && dashLength > 1.0f) dashLength -= 1.0f;
|
||||
|
||||
// Change Space Length (LEFT/RIGHT arrows)
|
||||
if (IsKeyDown(KEY_RIGHT)) blankLength += 1.0f;
|
||||
if (IsKeyDown(KEY_LEFT) && blankLength > 1.0f) blankLength -= 1.0f;
|
||||
|
||||
// Cycle through colors ('C' key)
|
||||
if (IsKeyPressed(KEY_C)) colorIndex = (colorIndex + 1)%(sizeof(lineColors)/sizeof(Color));
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw the dashed line with the current properties
|
||||
DrawLineDashed(lineStartPosition, lineEndPosition, (int)dashLength, (int)blankLength, lineColors[colorIndex]);
|
||||
|
||||
// Draw UI and Instructions
|
||||
DrawRectangle(5, 5, 265, 95, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(5, 5, 265, 95, BLUE);
|
||||
|
||||
DrawText("CONTROLS:", 15, 15, 10, BLACK);
|
||||
DrawText("UP/DOWN: Change Dash Length", 15, 35, 10, BLACK);
|
||||
DrawText("LEFT/RIGHT: Change Space Length", 15, 55, 10, BLACK);
|
||||
DrawText("C: Cycle Color", 15, 75, 10, BLACK);
|
||||
|
||||
DrawText(TextFormat("Dash: %.0f | Space: %.0f", dashLength, blankLength), 15, 115, 10, DARKGRAY);
|
||||
|
||||
DrawFPS(screenWidth - 80, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,319 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - digital clock
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Hamza RAHAL (@hmz-rhl) 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 Hamza RAHAL (@hmz-rhl) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable some Visual Studio warnings
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <math.h> // Required for: cosf(), sinf()
|
||||
#include <time.h> // Required for: time(), localtime()
|
||||
|
||||
#define CLOCK_ANALOG 0
|
||||
#define CLOCK_DIGITAL 1
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Clock hand type
|
||||
typedef struct {
|
||||
int value; // Time value
|
||||
|
||||
// Visual elements
|
||||
float angle; // Hand angle
|
||||
int length; // Hand length
|
||||
int thickness; // Hand thickness
|
||||
Color color; // Hand color
|
||||
} ClockHand;
|
||||
|
||||
// Clock hands
|
||||
typedef struct {
|
||||
ClockHand second; // Clock hand for seconds
|
||||
ClockHand minute; // Clock hand for minutes
|
||||
ClockHand hour; // Clock hand for hours
|
||||
} Clock;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void UpdateClock(Clock *clock); // Update clock time
|
||||
static void DrawClockAnalog(Clock clock, Vector2 position); // Draw analog clock at desired center position
|
||||
static void DrawClockDigital(Clock clock, Vector2 position); // Draw digital clock at desired position
|
||||
|
||||
static void DrawDisplayValue(Vector2 position, int value, Color colorOn, Color colorOff);
|
||||
static void Draw7SDisplay(Vector2 position, char segments, Color colorOn, Color colorOff);
|
||||
static void DrawDisplaySegment(Vector2 center, int length, int thick, bool vertical, Color color);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - digital clock");
|
||||
|
||||
int clockMode = CLOCK_DIGITAL;
|
||||
|
||||
// Initialize clock
|
||||
// NOTE: Includes visual info for anlaog clock
|
||||
Clock clock = {
|
||||
.second.angle = 45,
|
||||
.second.length = 140,
|
||||
.second.thickness = 3,
|
||||
.second.color = MAROON,
|
||||
|
||||
.minute.angle = 10,
|
||||
.minute.length = 130,
|
||||
.minute.thickness = 7,
|
||||
.minute.color = DARKGRAY,
|
||||
|
||||
.hour.angle = 0,
|
||||
.hour.length = 100,
|
||||
.hour.thickness = 7,
|
||||
.hour.color = BLACK,
|
||||
};
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
// Toggle clock mode
|
||||
if (clockMode == CLOCK_DIGITAL) clockMode = CLOCK_ANALOG;
|
||||
else if (clockMode == CLOCK_ANALOG) clockMode = CLOCK_DIGITAL;
|
||||
}
|
||||
|
||||
UpdateClock(&clock); // Update clock required data: value and angle
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw clock in selected mode
|
||||
if (clockMode == CLOCK_ANALOG) DrawClockAnalog(clock, (Vector2){ 400, 240 });
|
||||
else if (clockMode == CLOCK_DIGITAL)
|
||||
{
|
||||
DrawClockDigital(clock, (Vector2){ 30, 60 });
|
||||
|
||||
// Draw clock using default raylib font
|
||||
// Get pointer to formated clock time string
|
||||
// WARNING: Pointing to an internal static string that is reused between TextFormat() calls
|
||||
const char *clockTime = TextFormat("%02i:%02i:%02i", clock.hour.value, clock.minute.value, clock.second.value);
|
||||
DrawText(clockTime, GetScreenWidth()/2 - MeasureText(clockTime, 150)/2, 300, 150, BLACK);
|
||||
}
|
||||
|
||||
DrawText(TextFormat("Press [SPACE] to switch clock mode: %s",
|
||||
(clockMode == CLOCK_DIGITAL)? "DIGITAL CLOCK" : "ANALOGUE CLOCK"), 10, 10, 20, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Update clock time
|
||||
static void UpdateClock(Clock *clock)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
// Updating time data
|
||||
clock->second.value = timeinfo->tm_sec;
|
||||
clock->minute.value = timeinfo->tm_min;
|
||||
clock->hour.value = timeinfo->tm_hour;
|
||||
|
||||
clock->hour.angle = (timeinfo->tm_hour%12)*180.0f/6.0f;
|
||||
clock->hour.angle += (timeinfo->tm_min%60)*30/60.0f;
|
||||
clock->hour.angle -= 90;
|
||||
|
||||
clock->minute.angle = (timeinfo->tm_min%60)*6.0f;
|
||||
clock->minute.angle += (timeinfo->tm_sec%60)*6/60.0f;
|
||||
clock->minute.angle -= 90;
|
||||
|
||||
clock->second.angle = (timeinfo->tm_sec%60)*6.0f;
|
||||
clock->second.angle -= 90;
|
||||
}
|
||||
|
||||
// Draw analog clock
|
||||
// Parameter: position, refers to center position
|
||||
static void DrawClockAnalog(Clock clock, Vector2 position)
|
||||
{
|
||||
// Draw clock base
|
||||
DrawCircleV(position, clock.second.length + 40.0f, LIGHTGRAY);
|
||||
DrawCircleV(position, 12.0f, GRAY);
|
||||
|
||||
// Draw clock minutes/seconds lines
|
||||
for (int i = 0; i < 60; i++)
|
||||
{
|
||||
DrawLineEx((Vector2){ position.x + (clock.second.length + ((i%5)? 10 : 6))*cosf((6.0f*i - 90.0f)*DEG2RAD),
|
||||
position.y + (clock.second.length + ((i%5)? 10 : 6))*sinf((6.0f*i - 90.0f)*DEG2RAD) },
|
||||
(Vector2){ position.x + (clock.second.length + 20)*cosf((6.0f*i - 90.0f)*DEG2RAD),
|
||||
position.y + (clock.second.length + 20)*sinf((6.0f*i - 90.0f)*DEG2RAD) }, ((i%5)? 1.0f : 3.0f), DARKGRAY);
|
||||
|
||||
// Draw seconds numbers
|
||||
//DrawText(TextFormat("%02i", i), centerPosition.x + (clock.second.length + 50)*cosf((6.0f*i - 90.0f)*DEG2RAD) - 10/2,
|
||||
// centerPosition.y + (clock.second.length + 50)*sinf((6.0f*i - 90.0f)*DEG2RAD) - 10/2, 10, GRAY);
|
||||
}
|
||||
|
||||
// Draw hand seconds
|
||||
DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.second.length, (float)clock.second.thickness },
|
||||
(Vector2){ 0.0f, clock.second.thickness/2.0f }, clock.second.angle, clock.second.color);
|
||||
|
||||
// Draw hand minutes
|
||||
DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.minute.length, (float)clock.minute.thickness },
|
||||
(Vector2){ 0.0f, clock.minute.thickness/2.0f }, clock.minute.angle, clock.minute.color);
|
||||
|
||||
// Draw hand hours
|
||||
DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.hour.length, (float)clock.hour.thickness },
|
||||
(Vector2){ 0.0f, clock.hour.thickness/2.0f }, clock.hour.angle, clock.hour.color);
|
||||
}
|
||||
|
||||
// Draw digital clock
|
||||
// PARAM: position, refers to top-left corner
|
||||
static void DrawClockDigital(Clock clock, Vector2 position)
|
||||
{
|
||||
// Draw clock using custom 7-segments display (made of shapes)
|
||||
DrawDisplayValue((Vector2){ position.x, position.y }, clock.hour.value/10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
DrawDisplayValue((Vector2){ position.x + 120, position.y }, clock.hour.value%10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawCircle((int)position.x + 240, (int)position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
|
||||
DrawCircle((int)position.x + 240, (int)position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawDisplayValue((Vector2){ position.x + 260, position.y }, clock.minute.value/10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
DrawDisplayValue((Vector2){ position.x + 380, position.y }, clock.minute.value%10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawCircle((int)position.x + 500, (int)position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
|
||||
DrawCircle((int)position.x + 500, (int)position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawDisplayValue((Vector2){ position.x + 520, position.y }, clock.second.value/10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
DrawDisplayValue((Vector2){ position.x + 640, position.y }, clock.second.value%10, RED, Fade(LIGHTGRAY, 0.3f));
|
||||
}
|
||||
|
||||
// Draw 7-segment display with value
|
||||
static void DrawDisplayValue(Vector2 position, int value, Color colorOn, Color colorOff)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0: Draw7SDisplay(position, 0b00111111, colorOn, colorOff); break;
|
||||
case 1: Draw7SDisplay(position, 0b00000110, colorOn, colorOff); break;
|
||||
case 2: Draw7SDisplay(position, 0b01011011, colorOn, colorOff); break;
|
||||
case 3: Draw7SDisplay(position, 0b01001111, colorOn, colorOff); break;
|
||||
case 4: Draw7SDisplay(position, 0b01100110, colorOn, colorOff); break;
|
||||
case 5: Draw7SDisplay(position, 0b01101101, colorOn, colorOff); break;
|
||||
case 6: Draw7SDisplay(position, 0b01111101, colorOn, colorOff); break;
|
||||
case 7: Draw7SDisplay(position, 0b00000111, colorOn, colorOff); break;
|
||||
case 8: Draw7SDisplay(position, 0b01111111, colorOn, colorOff); break;
|
||||
case 9: Draw7SDisplay(position, 0b01101111, colorOn, colorOff); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw seven segments display
|
||||
// Parameter: position, refers to top-left corner of display
|
||||
// Parameter: segments, defines in binary the segments to be activated
|
||||
static void Draw7SDisplay(Vector2 position, char segments, Color colorOn, Color colorOff)
|
||||
{
|
||||
int segmentLen = 60;
|
||||
int segmentThick = 20;
|
||||
float offsetYAdjust = segmentThick*0.3f; // HACK: Adjust gap space between segment limits
|
||||
|
||||
// Segment A
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + segmentThick },
|
||||
segmentLen, segmentThick, false, (segments & 0b00000001)? colorOn : colorOff);
|
||||
// Segment B
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen + segmentThick/2.0f, position.y + 2*segmentThick + segmentLen/2.0f - offsetYAdjust },
|
||||
segmentLen, segmentThick, true, (segments & 0b00000010)? colorOn : colorOff);
|
||||
// Segment C
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen + segmentThick/2.0f, position.y + 4*segmentThick + segmentLen + segmentLen/2.0f - 3*offsetYAdjust },
|
||||
segmentLen, segmentThick, true, (segments & 0b00000100)? colorOn : colorOff);
|
||||
// Segment D
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + 5*segmentThick + 2*segmentLen - 4*offsetYAdjust },
|
||||
segmentLen, segmentThick, false, (segments & 0b00001000)? colorOn : colorOff);
|
||||
// Segment E
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick/2.0f, position.y + 4*segmentThick + segmentLen + segmentLen/2.0f - 3*offsetYAdjust },
|
||||
segmentLen, segmentThick, true, (segments & 0b00010000)? colorOn : colorOff);
|
||||
// Segment F
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick/2.0f, position.y + 2*segmentThick + segmentLen/2.0f - offsetYAdjust },
|
||||
segmentLen, segmentThick, true, (segments & 0b00100000)? colorOn : colorOff);
|
||||
// Segment G
|
||||
DrawDisplaySegment((Vector2){ position.x + segmentThick + segmentLen/2.0f, position.y + 3*segmentThick + segmentLen - 2*offsetYAdjust },
|
||||
segmentLen, segmentThick, false, (segments & 0b01000000)? colorOn : colorOff);
|
||||
}
|
||||
|
||||
// Draw one 7-segment display segment, horizontal or vertical
|
||||
static void DrawDisplaySegment(Vector2 center, int length, int thick, bool vertical, Color color)
|
||||
{
|
||||
if (!vertical)
|
||||
{
|
||||
// Horizontal segment points
|
||||
/*
|
||||
3___________________________5
|
||||
/ \
|
||||
/1 x 6\
|
||||
\ /
|
||||
\2___________________________4/
|
||||
*/
|
||||
Vector2 segmentPointsH[6] = {
|
||||
(Vector2){ center.x - length/2.0f - thick/2.0f, center.y }, // Point 1
|
||||
(Vector2){ center.x - length/2.0f, center.y + thick/2.0f }, // Point 2
|
||||
(Vector2){ center.x - length/2.0f, center.y - thick/2.0f }, // Point 3
|
||||
(Vector2){ center.x + length/2.0f, center.y + thick/2.0f }, // Point 4
|
||||
(Vector2){ center.x + length/2.0f, center.y - thick/2.0f }, // Point 5
|
||||
(Vector2){ center.x + length/2.0f + thick/2.0f, center.y }, // Point 6
|
||||
};
|
||||
|
||||
DrawTriangleStrip(segmentPointsH, 6, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Vertical segment points
|
||||
Vector2 segmentPointsV[6] = {
|
||||
(Vector2){ center.x, center.y - length/2.0f - thick/2.0f }, // Point 1
|
||||
(Vector2){ center.x - thick/2.0f, center.y - length/2.0f }, // Point 2
|
||||
(Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3
|
||||
(Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4
|
||||
(Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5
|
||||
(Vector2){ center.x, center.y + (float)length/2 + thick/2.0f }, // Point 6
|
||||
};
|
||||
|
||||
DrawTriangleStrip(segmentPointsV, 6, color);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,171 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - double pendulum
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by JoeCheong (@Joecheong2006) 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 JoeCheong (@Joecheong2006)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <math.h> // Required for: sin(), cos(), PI
|
||||
|
||||
// Constant for Simulation
|
||||
#define SIMULATION_STEPS 30
|
||||
#define G 9.81f
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static Vector2 CalculatePendulumEndPoint(float l, float theta);
|
||||
static Vector2 CalculateDoublePendulumEndPoint(float l1, float theta1, float l2, float theta2);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_HIGHDPI);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - double pendulum");
|
||||
|
||||
// Simulation Parameters
|
||||
float l1 = 15.0f, m1 = 0.2f, theta1 = DEG2RAD*170, w1 = 0;
|
||||
float l2 = 15.0f, m2 = 0.1f, theta2 = DEG2RAD*0, w2 = 0;
|
||||
float lengthScaler = 0.1f;
|
||||
float totalM = m1 + m2;
|
||||
|
||||
Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
||||
previousPosition.x += ((float)screenWidth/2);
|
||||
previousPosition.y += ((float)screenHeight/2 - 100);
|
||||
|
||||
// Scale length
|
||||
float L1 = l1*lengthScaler;
|
||||
float L2 = l2*lengthScaler;
|
||||
|
||||
// Draw parameters
|
||||
float lineThick = 20, trailThick = 2;
|
||||
float fateAlpha = 0.01f;
|
||||
|
||||
// Create framebuffer
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
SetTextureFilter(target.texture, TEXTURE_FILTER_BILINEAR);
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float dt = GetFrameTime();
|
||||
float step = dt/SIMULATION_STEPS, step2 = step*step;
|
||||
|
||||
// Update Physics - larger steps = better approximation
|
||||
for (int i = 0; i < SIMULATION_STEPS; i++)
|
||||
{
|
||||
float delta = theta1 - theta2;
|
||||
float sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta);
|
||||
float ww1 = w1*w1, ww2 = w2*w2;
|
||||
|
||||
// Calculate a1
|
||||
float a1 = (-G*(2*m1 + m2)*sinf(theta1)
|
||||
- m2*G*sinf(theta1 - 2*theta2)
|
||||
- 2*sinD*m2*(ww2*L2 + ww1*L1*cosD))
|
||||
/(L1*(2*m1 + m2 - m2*cos2D));
|
||||
|
||||
// Calculate a2
|
||||
float a2 = (2*sinD*(ww1*L1*totalM
|
||||
+ G*totalM*cosf(theta1)
|
||||
+ ww2*L2*m2*cosD))
|
||||
/(L2*(2*m1 + m2 - m2*cos2D));
|
||||
|
||||
// Update thetas
|
||||
theta1 += w1*step + 0.5f*a1*step2;
|
||||
theta2 += w2*step + 0.5f*a2*step2;
|
||||
|
||||
// Update omegas
|
||||
w1 += a1*step;
|
||||
w2 += a2*step;
|
||||
}
|
||||
|
||||
// Calculate position
|
||||
Vector2 currentPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
|
||||
currentPosition.x += (float)screenWidth/2;
|
||||
currentPosition.y += (float)screenHeight/2 - 100;
|
||||
|
||||
// Draw to render texture
|
||||
BeginTextureMode(target);
|
||||
// Draw a transparent rectangle - smaller alpha = longer trails
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, fateAlpha));
|
||||
|
||||
// Draw trail
|
||||
DrawCircleV(previousPosition, trailThick, RED);
|
||||
DrawLineEx(previousPosition, currentPosition, trailThick*2, RED);
|
||||
EndTextureMode();
|
||||
|
||||
// Update previous position
|
||||
previousPosition = currentPosition;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
// Draw trails texture
|
||||
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0, 0 }, WHITE);
|
||||
|
||||
// Draw double pendulum
|
||||
DrawRectanglePro((Rectangle){ screenWidth/2.0f, screenHeight/2.0f - 100, 10*l1, lineThick },
|
||||
(Vector2){0, lineThick*0.5f}, 90 - RAD2DEG*theta1, RAYWHITE);
|
||||
|
||||
Vector2 endpoint1 = CalculatePendulumEndPoint(l1, theta1);
|
||||
DrawRectanglePro((Rectangle){ screenWidth/2.0f + endpoint1.x, screenHeight/2.0f - 100 + endpoint1.y, 10*l2, lineThick },
|
||||
(Vector2){0, lineThick*0.5f}, 90 - RAD2DEG*theta2, RAYWHITE);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Calculate pendulum end point
|
||||
static Vector2 CalculatePendulumEndPoint(float l, float theta)
|
||||
{
|
||||
return (Vector2){ 10*l*sinf(theta), 10*l*cosf(theta) };
|
||||
}
|
||||
|
||||
// Calculate double pendulum end point
|
||||
static Vector2 CalculateDoublePendulumEndPoint(float l1, float theta1, float l2, float theta2)
|
||||
{
|
||||
Vector2 endpoint1 = CalculatePendulumEndPoint(l1, theta1);
|
||||
Vector2 endpoint2 = CalculatePendulumEndPoint(l2, theta2);
|
||||
return (Vector2){ endpoint1.x + endpoint2.x, endpoint1.y + endpoint2.y };
|
||||
}
|
||||
|
After Width: | Height: | Size: 285 KiB |
@ -0,0 +1,117 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - easings ball
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "reasings.h" // Required for easing functions
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings ball");
|
||||
|
||||
// Ball variable value to be animated with easings
|
||||
int ballPositionX = -100;
|
||||
int ballRadius = 20;
|
||||
float ballAlpha = 0.0f;
|
||||
|
||||
int state = 0;
|
||||
int framesCounter = 0;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (state == 0) // Move ball position X with easing
|
||||
{
|
||||
framesCounter++;
|
||||
ballPositionX = (int)EaseElasticOut((float)framesCounter, -100, screenWidth/2.0f + 100, 120);
|
||||
|
||||
if (framesCounter >= 120)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
else if (state == 1) // Increase ball radius with easing
|
||||
{
|
||||
framesCounter++;
|
||||
ballRadius = (int)EaseElasticIn((float)framesCounter, 20, 500, 200);
|
||||
|
||||
if (framesCounter >= 200)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 2;
|
||||
}
|
||||
}
|
||||
else if (state == 2) // Change ball alpha with easing (background color blending)
|
||||
{
|
||||
framesCounter++;
|
||||
ballAlpha = EaseCubicOut((float)framesCounter, 0.0f, 1.0f, 200);
|
||||
|
||||
if (framesCounter >= 200)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
else if (state == 3) // Reset state to play again
|
||||
{
|
||||
if (IsKeyPressed(KEY_ENTER))
|
||||
{
|
||||
// Reset required variables to play again
|
||||
ballPositionX = -100;
|
||||
ballRadius = 20;
|
||||
ballAlpha = 0.0f;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_R)) framesCounter = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (state >= 2) DrawRectangle(0, 0, screenWidth, screenHeight, GREEN);
|
||||
DrawCircle(ballPositionX, 200, (float)ballRadius, Fade(RED, 1.0f - ballAlpha));
|
||||
|
||||
if (state == 3) DrawText("PRESS [ENTER] TO PLAY AGAIN!", 240, 200, 20, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,143 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - easings box
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "reasings.h" // Required for easing functions
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings box");
|
||||
|
||||
// Box variables to be animated with easings
|
||||
Rectangle rec = { GetScreenWidth()/2.0f, -100, 100, 100 };
|
||||
float rotation = 0.0f;
|
||||
float alpha = 1.0f;
|
||||
|
||||
int state = 0;
|
||||
int framesCounter = 0;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (state)
|
||||
{
|
||||
case 0: // Move box down to center of screen
|
||||
{
|
||||
framesCounter++;
|
||||
|
||||
// NOTE: Remember that 3rd parameter of easing function refers to
|
||||
// desired value variation, do not confuse it with expected final value!
|
||||
rec.y = EaseElasticOut((float)framesCounter, -100, GetScreenHeight()/2.0f + 100, 120);
|
||||
|
||||
if (framesCounter >= 120)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 1;
|
||||
}
|
||||
} break;
|
||||
case 1: // Scale box to an horizontal bar
|
||||
{
|
||||
framesCounter++;
|
||||
rec.height = EaseBounceOut((float)framesCounter, 100, -90, 120);
|
||||
rec.width = EaseBounceOut((float)framesCounter, 100, (float)GetScreenWidth(), 120);
|
||||
|
||||
if (framesCounter >= 120)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 2;
|
||||
}
|
||||
} break;
|
||||
case 2: // Rotate horizontal bar rectangle
|
||||
{
|
||||
framesCounter++;
|
||||
rotation = EaseQuadOut((float)framesCounter, 0.0f, 270.0f, 240);
|
||||
|
||||
if (framesCounter >= 240)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 3;
|
||||
}
|
||||
} break;
|
||||
case 3: // Increase bar size to fill all screen
|
||||
{
|
||||
framesCounter++;
|
||||
rec.height = EaseCircOut((float)framesCounter, 10, (float)GetScreenWidth(), 120);
|
||||
|
||||
if (framesCounter >= 120)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 4;
|
||||
}
|
||||
} break;
|
||||
case 4: // Fade out animation
|
||||
{
|
||||
framesCounter++;
|
||||
alpha = EaseSineOut((float)framesCounter, 1.0f, -1.0f, 160);
|
||||
|
||||
if (framesCounter >= 160)
|
||||
{
|
||||
framesCounter = 0;
|
||||
state = 5;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Reset animation at any moment
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
rec = (Rectangle){ GetScreenWidth()/2.0f, -100, 100, 100 };
|
||||
rotation = 0.0f;
|
||||
alpha = 1.0f;
|
||||
state = 0;
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawRectanglePro(rec, (Vector2){ rec.width/2, rec.height/2 }, rotation, Fade(BLACK, alpha));
|
||||
|
||||
DrawText("PRESS [SPACE] TO RESET BOX ANIMATION!", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,125 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - easings rectangles
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy
|
||||
* the library to same directory as example or make sure it's available on include path
|
||||
*
|
||||
* Example originally created with raylib 2.0, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "reasings.h" // Required for easing functions
|
||||
|
||||
#define RECS_WIDTH 50
|
||||
#define RECS_HEIGHT 50
|
||||
|
||||
#define MAX_RECS_X 800/RECS_WIDTH
|
||||
#define MAX_RECS_Y 450/RECS_HEIGHT
|
||||
|
||||
#define PLAY_TIME_IN_FRAMES 240 // At 60 fps = 4 seconds
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings rectangles");
|
||||
|
||||
Rectangle recs[MAX_RECS_X*MAX_RECS_Y] = { 0 };
|
||||
|
||||
for (int y = 0; y < MAX_RECS_Y; y++)
|
||||
{
|
||||
for (int x = 0; x < MAX_RECS_X; x++)
|
||||
{
|
||||
recs[y*MAX_RECS_X + x].x = RECS_WIDTH/2.0f + RECS_WIDTH*x;
|
||||
recs[y*MAX_RECS_X + x].y = RECS_HEIGHT/2.0f + RECS_HEIGHT*y;
|
||||
recs[y*MAX_RECS_X + x].width = RECS_WIDTH;
|
||||
recs[y*MAX_RECS_X + x].height = RECS_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
float rotation = 0.0f;
|
||||
int framesCounter = 0;
|
||||
int state = 0; // Rectangles animation state: 0-Playing, 1-Finished
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (state == 0)
|
||||
{
|
||||
framesCounter++;
|
||||
|
||||
for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++)
|
||||
{
|
||||
recs[i].height = EaseCircOut((float)framesCounter, RECS_HEIGHT, -RECS_HEIGHT, PLAY_TIME_IN_FRAMES);
|
||||
recs[i].width = EaseCircOut((float)framesCounter, RECS_WIDTH, -RECS_WIDTH, PLAY_TIME_IN_FRAMES);
|
||||
|
||||
if (recs[i].height < 0) recs[i].height = 0;
|
||||
if (recs[i].width < 0) recs[i].width = 0;
|
||||
|
||||
if ((recs[i].height == 0) && (recs[i].width == 0)) state = 1; // Finish playing
|
||||
|
||||
rotation = EaseLinearIn((float)framesCounter, 0.0f, 360.0f, PLAY_TIME_IN_FRAMES);
|
||||
}
|
||||
}
|
||||
else if ((state == 1) && IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
// When animation has finished, press space to restart
|
||||
framesCounter = 0;
|
||||
|
||||
for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++)
|
||||
{
|
||||
recs[i].height = RECS_HEIGHT;
|
||||
recs[i].width = RECS_WIDTH;
|
||||
}
|
||||
|
||||
state = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
for (int i = 0; i < MAX_RECS_X*MAX_RECS_Y; i++)
|
||||
{
|
||||
DrawRectanglePro(recs[i], (Vector2){ recs[i].width/2, recs[i].height/2 }, rotation, RED);
|
||||
}
|
||||
}
|
||||
else if (state == 1) DrawText("PRESS [SPACE] TO PLAY AGAIN!", 240, 200, 20, GRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,247 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - easings testbed
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Juan Miguel López (@flashback-fx) 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) 2019-2025 Juan Miguel López (@flashback-fx) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "reasings.h" // Required for: easing functions
|
||||
|
||||
#define FONT_SIZE 20
|
||||
|
||||
#define D_STEP 20.0f
|
||||
#define D_STEP_FINE 2.0f
|
||||
#define D_MIN 1.0f
|
||||
#define D_MAX 10000.0f
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Easing types
|
||||
enum EasingTypes {
|
||||
EASE_LINEAR_NONE = 0,
|
||||
EASE_LINEAR_IN,
|
||||
EASE_LINEAR_OUT,
|
||||
EASE_LINEAR_IN_OUT,
|
||||
EASE_SINE_IN,
|
||||
EASE_SINE_OUT,
|
||||
EASE_SINE_IN_OUT,
|
||||
EASE_CIRC_IN,
|
||||
EASE_CIRC_OUT,
|
||||
EASE_CIRC_IN_OUT,
|
||||
EASE_CUBIC_IN,
|
||||
EASE_CUBIC_OUT,
|
||||
EASE_CUBIC_IN_OUT,
|
||||
EASE_QUAD_IN,
|
||||
EASE_QUAD_OUT,
|
||||
EASE_QUAD_IN_OUT,
|
||||
EASE_EXPO_IN,
|
||||
EASE_EXPO_OUT,
|
||||
EASE_EXPO_IN_OUT,
|
||||
EASE_BACK_IN,
|
||||
EASE_BACK_OUT,
|
||||
EASE_BACK_IN_OUT,
|
||||
EASE_BOUNCE_OUT,
|
||||
EASE_BOUNCE_IN,
|
||||
EASE_BOUNCE_IN_OUT,
|
||||
EASE_ELASTIC_IN,
|
||||
EASE_ELASTIC_OUT,
|
||||
EASE_ELASTIC_IN_OUT,
|
||||
NUM_EASING_TYPES,
|
||||
EASING_NONE = NUM_EASING_TYPES
|
||||
};
|
||||
|
||||
typedef struct EasingFuncs {
|
||||
const char *name;
|
||||
float (*func)(float, float, float, float);
|
||||
} EasingFuncs;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
// Function used when "no easing" is selected for any axis
|
||||
static float NoEase(float t, float b, float c, float d);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Easing functions reference data
|
||||
static const EasingFuncs easings[] = {
|
||||
[EASE_LINEAR_NONE] = { .name = "EaseLinearNone", .func = EaseLinearNone },
|
||||
[EASE_LINEAR_IN] = { .name = "EaseLinearIn", .func = EaseLinearIn },
|
||||
[EASE_LINEAR_OUT] = { .name = "EaseLinearOut", .func = EaseLinearOut },
|
||||
[EASE_LINEAR_IN_OUT] = { .name = "EaseLinearInOut", .func = EaseLinearInOut },
|
||||
[EASE_SINE_IN] = { .name = "EaseSineIn", .func = EaseSineIn },
|
||||
[EASE_SINE_OUT] = { .name = "EaseSineOut", .func = EaseSineOut },
|
||||
[EASE_SINE_IN_OUT] = { .name = "EaseSineInOut", .func = EaseSineInOut },
|
||||
[EASE_CIRC_IN] = { .name = "EaseCircIn", .func = EaseCircIn },
|
||||
[EASE_CIRC_OUT] = { .name = "EaseCircOut", .func = EaseCircOut },
|
||||
[EASE_CIRC_IN_OUT] = { .name = "EaseCircInOut", .func = EaseCircInOut },
|
||||
[EASE_CUBIC_IN] = { .name = "EaseCubicIn", .func = EaseCubicIn },
|
||||
[EASE_CUBIC_OUT] = { .name = "EaseCubicOut", .func = EaseCubicOut },
|
||||
[EASE_CUBIC_IN_OUT] = { .name = "EaseCubicInOut", .func = EaseCubicInOut },
|
||||
[EASE_QUAD_IN] = { .name = "EaseQuadIn", .func = EaseQuadIn },
|
||||
[EASE_QUAD_OUT] = { .name = "EaseQuadOut", .func = EaseQuadOut },
|
||||
[EASE_QUAD_IN_OUT] = { .name = "EaseQuadInOut", .func = EaseQuadInOut },
|
||||
[EASE_EXPO_IN] = { .name = "EaseExpoIn", .func = EaseExpoIn },
|
||||
[EASE_EXPO_OUT] = { .name = "EaseExpoOut", .func = EaseExpoOut },
|
||||
[EASE_EXPO_IN_OUT] = { .name = "EaseExpoInOut", .func = EaseExpoInOut },
|
||||
[EASE_BACK_IN] = { .name = "EaseBackIn", .func = EaseBackIn },
|
||||
[EASE_BACK_OUT] = { .name = "EaseBackOut", .func = EaseBackOut },
|
||||
[EASE_BACK_IN_OUT] = { .name = "EaseBackInOut", .func = EaseBackInOut },
|
||||
[EASE_BOUNCE_OUT] = { .name = "EaseBounceOut", .func = EaseBounceOut },
|
||||
[EASE_BOUNCE_IN] = { .name = "EaseBounceIn", .func = EaseBounceIn },
|
||||
[EASE_BOUNCE_IN_OUT] = { .name = "EaseBounceInOut", .func = EaseBounceInOut },
|
||||
[EASE_ELASTIC_IN] = { .name = "EaseElasticIn", .func = EaseElasticIn },
|
||||
[EASE_ELASTIC_OUT] = { .name = "EaseElasticOut", .func = EaseElasticOut },
|
||||
[EASE_ELASTIC_IN_OUT] = { .name = "EaseElasticInOut", .func = EaseElasticInOut },
|
||||
[EASING_NONE] = { .name = "None", .func = NoEase },
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - easings testbed");
|
||||
|
||||
Vector2 ballPosition = { 100.0f, 100.0f };
|
||||
|
||||
float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
|
||||
float d = 300.0f; // Total time it should take to complete (duration)
|
||||
bool paused = true;
|
||||
bool boundedT = true; // If true, t will stop when d >= td, otherwise t will keep adding td to its value every loop
|
||||
|
||||
int easingX = EASING_NONE; // Easing selected for x axis
|
||||
int easingY = EASING_NONE; // Easing selected for y axis
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_T)) boundedT = !boundedT;
|
||||
|
||||
// Choose easing for the X axis
|
||||
if (IsKeyPressed(KEY_RIGHT))
|
||||
{
|
||||
easingX++;
|
||||
|
||||
if (easingX > EASING_NONE) easingX = 0;
|
||||
}
|
||||
else if (IsKeyPressed(KEY_LEFT))
|
||||
{
|
||||
if (easingX == 0) easingX = EASING_NONE;
|
||||
else easingX--;
|
||||
}
|
||||
|
||||
// Choose easing for the Y axis
|
||||
if (IsKeyPressed(KEY_DOWN))
|
||||
{
|
||||
easingY++;
|
||||
|
||||
if (easingY > EASING_NONE) easingY = 0;
|
||||
}
|
||||
else if (IsKeyPressed(KEY_UP))
|
||||
{
|
||||
if (easingY == 0) easingY = EASING_NONE;
|
||||
else easingY--;
|
||||
}
|
||||
|
||||
// Change d (duration) value
|
||||
if (IsKeyPressed(KEY_W) && (d < D_MAX - D_STEP)) d += D_STEP;
|
||||
else if (IsKeyPressed(KEY_Q) && (d > D_MIN + D_STEP)) d -= D_STEP;
|
||||
|
||||
if (IsKeyDown(KEY_S) && (d < D_MAX - D_STEP_FINE)) d += D_STEP_FINE;
|
||||
else if (IsKeyDown(KEY_A) && (d > D_MIN + D_STEP_FINE)) d -= D_STEP_FINE;
|
||||
|
||||
// Play, pause and restart controls
|
||||
if (IsKeyPressed(KEY_SPACE) || IsKeyPressed(KEY_T) ||
|
||||
IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_LEFT) ||
|
||||
IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_UP) ||
|
||||
IsKeyPressed(KEY_W) || IsKeyPressed(KEY_Q) ||
|
||||
IsKeyDown(KEY_S) || IsKeyDown(KEY_A) ||
|
||||
(IsKeyPressed(KEY_ENTER) && (boundedT == true) && (t >= d)))
|
||||
{
|
||||
t = 0.0f;
|
||||
ballPosition.x = 100.0f;
|
||||
ballPosition.y = 100.0f;
|
||||
paused = true;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_ENTER)) paused = !paused;
|
||||
|
||||
// Movement computation
|
||||
if (!paused && ((boundedT && t < d) || !boundedT))
|
||||
{
|
||||
ballPosition.x = easings[easingX].func(t, 100.0f, 700.0f - 170.0f, d);
|
||||
ballPosition.y = easings[easingY].func(t, 100.0f, 400.0f - 170.0f, d);
|
||||
t += 1.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw information text
|
||||
DrawText(TextFormat("Easing x: %s", easings[easingX].name), 20, FONT_SIZE, FONT_SIZE, LIGHTGRAY);
|
||||
DrawText(TextFormat("Easing y: %s", easings[easingY].name), 20, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
||||
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 20, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
||||
|
||||
// Draw instructions text
|
||||
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 20, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
|
||||
DrawText("Use Q and W or A and S keys to change duration", 20, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
|
||||
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 20, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
|
||||
DrawText("Use UP or DOWN keys to choose easing for the y axis", 20, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
|
||||
|
||||
// Draw ball
|
||||
DrawCircleV(ballPosition, 16.0f, MAROON);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
// NoEase function, used when "no easing" is selected for any axis
|
||||
// It just ignores all parameters besides b
|
||||
static float NoEase(float t, float b, float c, float d)
|
||||
{
|
||||
// Hack to avoid compiler warning (about unused variables)
|
||||
float burn = t + b + c + d;
|
||||
d += burn;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,133 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - ellipse collision
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Ziya (@Monjaris)
|
||||
*
|
||||
* 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 Ziya (@Monjaris)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
// Check if point is inside ellipse
|
||||
static bool CheckCollisionPointEllipse(Vector2 point, Vector2 center, float rx, float ry)
|
||||
{
|
||||
float dx = (point.x - center.x)/rx;
|
||||
float dy = (point.y - center.y)/ry;
|
||||
return (dx*dx + dy*dy) <= 1.0f;
|
||||
}
|
||||
|
||||
// Check if two ellipses collide
|
||||
// Uses radial boundary distance in the direction between centers — scales correctly with radii
|
||||
static bool CheckCollisionEllipses(Vector2 c1, float rx1, float ry1, Vector2 c2, float rx2, float ry2)
|
||||
{
|
||||
float dx = c2.x - c1.x;
|
||||
float dy = c2.y - c1.y;
|
||||
float dist = sqrtf(dx*dx + dy*dy);
|
||||
|
||||
// Ellipses are on top of each other
|
||||
if (dist == 0.0f) return true;
|
||||
|
||||
float theta = atan2f(dy, dx);
|
||||
float cosT = cosf(theta);
|
||||
float sinT = sinf(theta);
|
||||
|
||||
// Radial distance from center to ellipse boundary in direction theta
|
||||
// r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2)
|
||||
float r1 = (rx1*ry1)/sqrtf((ry1*cosT)*(ry1*cosT) + (rx1*sinT)*(rx1*sinT));
|
||||
float r2 = (rx2*ry2)/sqrtf((ry2*cosT)*(ry2*cosT) + (rx2*sinT)*(rx2*sinT));
|
||||
|
||||
return dist <= (r1 + r2);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
|
||||
SetTargetFPS(60);
|
||||
|
||||
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };
|
||||
float ellipseARx = 120.0f;
|
||||
float ellipseARy = 70.0f;
|
||||
|
||||
Vector2 ellipseBCenter = { (float)screenWidth*3/4, (float)screenHeight/2 };
|
||||
float ellipseBRx = 90.0f;
|
||||
float ellipseBRy = 140.0f;
|
||||
|
||||
// 0 = controlling A, 1 = controlling B
|
||||
int controlled = 0;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_A)) controlled = 0;
|
||||
if (IsKeyPressed(KEY_B)) controlled = 1;
|
||||
|
||||
if (controlled == 0) ellipseACenter = GetMousePosition();
|
||||
else ellipseBCenter = GetMousePosition();
|
||||
|
||||
bool ellipsesCollide = CheckCollisionEllipses(
|
||||
ellipseACenter, ellipseARx, ellipseARy,
|
||||
ellipseBCenter, ellipseBRx, ellipseBRy
|
||||
);
|
||||
|
||||
bool mouseInA = CheckCollisionPointEllipse(GetMousePosition(), ellipseACenter, ellipseARx, ellipseARy);
|
||||
bool mouseInB = CheckCollisionPointEllipse(GetMousePosition(), ellipseBCenter, ellipseBRx, ellipseBRy);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawEllipse((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, ellipsesCollide ? RED : BLUE);
|
||||
|
||||
DrawEllipse((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, ellipsesCollide ? RED : GREEN);
|
||||
|
||||
DrawEllipseLines((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, WHITE);
|
||||
|
||||
DrawEllipseLines((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, WHITE);
|
||||
|
||||
DrawCircleV(ellipseACenter, 4, WHITE);
|
||||
DrawCircleV(ellipseBCenter, 4, WHITE);
|
||||
|
||||
if (ellipsesCollide) DrawText("ELLIPSES COLLIDE", screenWidth/2 - 120, 40, 28, RED);
|
||||
else DrawText("NO COLLISION", screenWidth/2 - 80, 40, 28, DARKGRAY);
|
||||
|
||||
DrawText(controlled == 0 ? "Controlling: A" : "Controlling: B", 20, screenHeight - 40, 20, YELLOW);
|
||||
|
||||
if (mouseInA && controlled != 0) DrawText("Mouse inside ellipse A", 20, screenHeight - 70, 20, BLUE);
|
||||
if (mouseInB && controlled != 1) DrawText("Mouse inside ellipse B", 20, screenHeight - 70, 20, GREEN);
|
||||
|
||||
DrawText("Press [A] or [B] to switch control", 20, 20, 20, GRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
CloseWindow();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,111 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - following eyes
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* 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) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <math.h> // Required for: atan2f()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - following eyes");
|
||||
|
||||
Vector2 scleraLeftPosition = { GetScreenWidth()/2.0f - 100.0f, GetScreenHeight()/2.0f };
|
||||
Vector2 scleraRightPosition = { GetScreenWidth()/2.0f + 100.0f, GetScreenHeight()/2.0f };
|
||||
float scleraRadius = 80;
|
||||
|
||||
Vector2 irisLeftPosition = { GetScreenWidth()/2.0f - 100.0f, GetScreenHeight()/2.0f };
|
||||
Vector2 irisRightPosition = { GetScreenWidth()/2.0f + 100.0f, GetScreenHeight()/2.0f };
|
||||
float irisRadius = 24;
|
||||
|
||||
float angle = 0.0f;
|
||||
float dx = 0.0f, dy = 0.0f, dxx = 0.0f, dyy = 0.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
|
||||
//----------------------------------------------------------------------------------
|
||||
irisLeftPosition = GetMousePosition();
|
||||
irisRightPosition = GetMousePosition();
|
||||
|
||||
// Check not inside the left eye sclera
|
||||
if (!CheckCollisionPointCircle(irisLeftPosition, scleraLeftPosition, scleraRadius - irisRadius))
|
||||
{
|
||||
dx = irisLeftPosition.x - scleraLeftPosition.x;
|
||||
dy = irisLeftPosition.y - scleraLeftPosition.y;
|
||||
|
||||
angle = atan2f(dy, dx);
|
||||
|
||||
dxx = (scleraRadius - irisRadius)*cosf(angle);
|
||||
dyy = (scleraRadius - irisRadius)*sinf(angle);
|
||||
|
||||
irisLeftPosition.x = scleraLeftPosition.x + dxx;
|
||||
irisLeftPosition.y = scleraLeftPosition.y + dyy;
|
||||
}
|
||||
|
||||
// Check not inside the right eye sclera
|
||||
if (!CheckCollisionPointCircle(irisRightPosition, scleraRightPosition, scleraRadius - irisRadius))
|
||||
{
|
||||
dx = irisRightPosition.x - scleraRightPosition.x;
|
||||
dy = irisRightPosition.y - scleraRightPosition.y;
|
||||
|
||||
angle = atan2f(dy, dx);
|
||||
|
||||
dxx = (scleraRadius - irisRadius)*cosf(angle);
|
||||
dyy = (scleraRadius - irisRadius)*sinf(angle);
|
||||
|
||||
irisRightPosition.x = scleraRightPosition.x + dxx;
|
||||
irisRightPosition.y = scleraRightPosition.y + dyy;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawCircleV(scleraLeftPosition, scleraRadius, LIGHTGRAY);
|
||||
DrawCircleV(irisLeftPosition, irisRadius, BROWN);
|
||||
DrawCircleV(irisLeftPosition, 10, BLACK);
|
||||
|
||||
DrawCircleV(scleraRightPosition, scleraRadius, LIGHTGRAY);
|
||||
DrawCircleV(irisRightPosition, irisRadius, DARKGREEN);
|
||||
DrawCircleV(irisRightPosition, 10, BLACK);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,196 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - hilbert curve
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.6, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Hamza RAHAL (@hmz-rhl) 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 Hamza RAHAL (@hmz-rhl)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static Vector2 *LoadHilbertPath(int order, float size, int *strokeCount);
|
||||
static void UnloadHilbertPath(Vector2 *hilbertPath);
|
||||
static Vector2 ComputeHilbertStep(int order, int index);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - hilbert curve");
|
||||
|
||||
int order = 2;
|
||||
float size = (float)GetScreenHeight();
|
||||
int strokeCount = 0;
|
||||
Vector2 *hilbertPath = LoadHilbertPath(order, size, &strokeCount);
|
||||
|
||||
int prevOrder = order;
|
||||
int prevSize = (int)size; // NOTE: Size from slider is float but for comparison we use int
|
||||
int counter = 0;
|
||||
float thick = 2.0f;
|
||||
bool animate = true;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
// Check if order or size have changed to regenerate
|
||||
// NOTE: Size from slider is float but for comparison we use int
|
||||
if ((prevOrder != order) || (prevSize != (int)size))
|
||||
{
|
||||
UnloadHilbertPath(hilbertPath);
|
||||
hilbertPath = LoadHilbertPath(order, size, &strokeCount);
|
||||
|
||||
if (animate) counter = 0;
|
||||
else counter = strokeCount;
|
||||
|
||||
prevOrder = order;
|
||||
prevSize = (int)size;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (counter < strokeCount)
|
||||
{
|
||||
// Draw Hilbert path animation, one stroke every frame
|
||||
for (int i = 1; i <= counter; i++)
|
||||
{
|
||||
DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
counter += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw full Hilbert path
|
||||
for (int i = 1; i < strokeCount; i++)
|
||||
{
|
||||
DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw UI using raygui
|
||||
GuiCheckBox((Rectangle){ 450, 50, 20, 20 }, "ANIMATE GENERATION ON CHANGE", &animate);
|
||||
GuiSpinner((Rectangle){ 585, 100, 180, 30 }, "HILBERT CURVE ORDER: ", &order, 2, 8, false);
|
||||
GuiSlider((Rectangle){ 524, 150, 240, 24 }, "THICKNESS: ", NULL, &thick, 1.0f, 10.0f);
|
||||
GuiSlider((Rectangle){ 524, 190, 240, 24 }, "TOTAL SIZE: ", NULL, &size, 10.0f, GetScreenHeight()*1.5f);
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadHilbertPath(hilbertPath);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Load the whole Hilbert Path (including each U and their link)
|
||||
static Vector2 *LoadHilbertPath(int order, float size, int *strokeCount)
|
||||
{
|
||||
int N = 1 << order;
|
||||
float len = size/N;
|
||||
*strokeCount = N*N;
|
||||
|
||||
Vector2 *hilbertPath = (Vector2 *)RL_CALLOC(*strokeCount, sizeof(Vector2));
|
||||
|
||||
for (int i = 0; i < *strokeCount; i++)
|
||||
{
|
||||
hilbertPath[i] = ComputeHilbertStep(order, i);
|
||||
hilbertPath[i].x = hilbertPath[i].x*len + len/2.0f;
|
||||
hilbertPath[i].y = hilbertPath[i].y*len + len/2.0f;
|
||||
}
|
||||
|
||||
return hilbertPath;
|
||||
}
|
||||
|
||||
// Unload Hilbert path data
|
||||
static void UnloadHilbertPath(Vector2 *hilbertPath)
|
||||
{
|
||||
RL_FREE(hilbertPath);
|
||||
}
|
||||
|
||||
// Compute Hilbert path U positions
|
||||
static Vector2 ComputeHilbertStep(int order, int index)
|
||||
{
|
||||
// Hilbert points base pattern
|
||||
static const Vector2 hilbertPoints[4] = {
|
||||
[0] = { .x = 0, .y = 0 },
|
||||
[1] = { .x = 0, .y = 1 },
|
||||
[2] = { .x = 1, .y = 1 },
|
||||
[3] = { .x = 1, .y = 0 },
|
||||
};
|
||||
|
||||
int hilbertIndex = index&3;
|
||||
Vector2 vect = hilbertPoints[hilbertIndex];
|
||||
float temp = 0.0f;
|
||||
int len = 0;
|
||||
|
||||
for (int j = 1; j < order; j++)
|
||||
{
|
||||
index = index >> 2;
|
||||
hilbertIndex = index&3;
|
||||
len = 1 << j;
|
||||
|
||||
switch (hilbertIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
temp = vect.x;
|
||||
vect.x = vect.y;
|
||||
vect.y = temp;
|
||||
} break;
|
||||
case 2: vect.x += len;
|
||||
case 1: vect.y += len; break;
|
||||
case 3:
|
||||
{
|
||||
temp = len - 1 - vect.x;
|
||||
vect.x = 2*len - 1 - vect.y;
|
||||
vect.y = temp;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return vect;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,172 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - kaleidoscope
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Hugo ARNAL (@hugoarnal) 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 Hugo ARNAL (@hugoarnal) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <string.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#define MAX_DRAW_LINES 8192
|
||||
|
||||
// Line data type
|
||||
typedef struct {
|
||||
Vector2 start;
|
||||
Vector2 end;
|
||||
} Line;
|
||||
|
||||
// Lines array as a global static variable to be stored
|
||||
// in heap and avoid potential stack overflow (on Web platform)
|
||||
static Line lines[MAX_DRAW_LINES] = { 0 };
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - kaleidoscope");
|
||||
|
||||
// Line drawing properties
|
||||
int symmetry = 6;
|
||||
float angle = 360.0f/(float)symmetry;
|
||||
float thickness = 3.0f;
|
||||
Rectangle resetButtonRec = { screenWidth - 55.0f, 5.0f, 50, 25 };
|
||||
Rectangle backButtonRec = { screenWidth - 55.0f, screenHeight - 30.0f, 25, 25 };
|
||||
Rectangle nextButtonRec = { screenWidth - 30.0f, screenHeight - 30.0f, 25, 25 };
|
||||
Vector2 mousePos = { 0 };
|
||||
Vector2 prevMousePos = { 0 };
|
||||
Vector2 scaleVector = { 1.0f, -1.0f };
|
||||
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){ 0 };
|
||||
camera.offset = offset;
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
int currentLineCounter = 0;
|
||||
int totalLineCounter = 0;
|
||||
int resetButtonClicked = false;
|
||||
int backButtonClicked = false;
|
||||
int nextButtonClicked = false;
|
||||
|
||||
SetTargetFPS(20);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
prevMousePos = mousePos;
|
||||
mousePos = GetMousePosition();
|
||||
|
||||
Vector2 lineStart = Vector2Subtract(mousePos, offset);
|
||||
Vector2 lineEnd = Vector2Subtract(prevMousePos, offset);
|
||||
|
||||
if (
|
||||
IsMouseButtonDown(MOUSE_LEFT_BUTTON)
|
||||
&& (CheckCollisionPointRec(mousePos, resetButtonRec) == false)
|
||||
&& (CheckCollisionPointRec(mousePos, backButtonRec) == false)
|
||||
&& (CheckCollisionPointRec(mousePos, nextButtonRec) == false)
|
||||
)
|
||||
{
|
||||
for (int s = 0; (s < symmetry) && (totalLineCounter < (MAX_DRAW_LINES - 1)); s++)
|
||||
{
|
||||
lineStart = Vector2Rotate(lineStart, angle*DEG2RAD);
|
||||
lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD);
|
||||
|
||||
// Store mouse line
|
||||
lines[totalLineCounter].start = lineStart;
|
||||
lines[totalLineCounter].end = lineEnd;
|
||||
|
||||
// Store reflective line
|
||||
lines[totalLineCounter + 1].start = Vector2Multiply(lineStart, scaleVector);
|
||||
lines[totalLineCounter + 1].end = Vector2Multiply(lineEnd, scaleVector);
|
||||
|
||||
totalLineCounter += 2;
|
||||
currentLineCounter = totalLineCounter;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetButtonClicked)
|
||||
{
|
||||
memset(&lines, 0, sizeof(Line)*MAX_DRAW_LINES);
|
||||
currentLineCounter = 0;
|
||||
totalLineCounter = 0;
|
||||
}
|
||||
|
||||
if (backButtonClicked && (currentLineCounter > 0))
|
||||
{
|
||||
currentLineCounter -= 1;
|
||||
}
|
||||
|
||||
if (nextButtonClicked && (currentLineCounter < MAX_DRAW_LINES) && ((currentLineCounter + 1) <= totalLineCounter))
|
||||
{
|
||||
currentLineCounter += 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
BeginMode2D(camera);
|
||||
|
||||
for (int s = 0; s < symmetry; s++)
|
||||
{
|
||||
for (int i = 0; i < currentLineCounter; i += 2)
|
||||
{
|
||||
DrawLineEx(lines[i].start, lines[i].end, thickness, BLACK);
|
||||
DrawLineEx(lines[i + 1].start, lines[i + 1].end, thickness, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
EndMode2D();
|
||||
|
||||
if ((currentLineCounter - 1) < 0) GuiDisable();
|
||||
|
||||
backButtonClicked = GuiButton(backButtonRec, "<");
|
||||
GuiEnable();
|
||||
|
||||
if ((currentLineCounter + 1) > totalLineCounter) GuiDisable();
|
||||
|
||||
nextButtonClicked = GuiButton(nextButtonRec, ">");
|
||||
GuiEnable();
|
||||
resetButtonClicked = GuiButton(resetButtonRec, "Reset");
|
||||
|
||||
DrawText(TextFormat("LINES: %i/%i", currentLineCounter, MAX_DRAW_LINES), 10, screenHeight - 30, 20, MAROON);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 81 KiB |
@ -0,0 +1,87 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - lines bezier
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.7, last time updated with raylib 1.7
|
||||
*
|
||||
* 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) 2017-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - lines bezier");
|
||||
|
||||
Vector2 startPoint = { 30, 30 };
|
||||
Vector2 endPoint = { (float)screenWidth - 30, (float)screenHeight - 30 };
|
||||
bool moveStartPoint = false;
|
||||
bool moveEndPoint = 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
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mouse = GetMousePosition();
|
||||
|
||||
if (CheckCollisionPointCircle(mouse, startPoint, 10.0f) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) moveStartPoint = true;
|
||||
else if (CheckCollisionPointCircle(mouse, endPoint, 10.0f) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) moveEndPoint = true;
|
||||
|
||||
if (moveStartPoint)
|
||||
{
|
||||
startPoint = mouse;
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) moveStartPoint = false;
|
||||
}
|
||||
|
||||
if (moveEndPoint)
|
||||
{
|
||||
endPoint = mouse;
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) moveEndPoint = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("MOVE START-END POINTS WITH MOUSE", 15, 20, 20, GRAY);
|
||||
|
||||
// Draw line Cubic Bezier, in-out interpolation (easing), no control points
|
||||
DrawLineBezier(startPoint, endPoint, 4.0f, BLUE);
|
||||
|
||||
// Draw start-end spline circles with some details
|
||||
DrawCircleV(startPoint, CheckCollisionPointCircle(mouse, startPoint, 10.0f)? 14.0f : 8.0f, moveStartPoint? RED : BLUE);
|
||||
DrawCircleV(endPoint, CheckCollisionPointCircle(mouse, endPoint, 10.0f)? 14.0f : 8.0f, moveEndPoint? RED : BLUE);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,137 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - lines drawing
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Robin (@RobinsAviary) 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 Robin (@RobinsAviary)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - lines drawing");
|
||||
|
||||
// Hint text that shows before you click the screen
|
||||
bool startText = true;
|
||||
|
||||
// The mouse's position on the previous frame
|
||||
Vector2 mousePositionPrevious = GetMousePosition();
|
||||
|
||||
// The canvas to draw lines on
|
||||
RenderTexture canvas = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// The line's thickness
|
||||
float lineThickness = 8.0f;
|
||||
// The lines hue (in HSV, from 0-360)
|
||||
float lineHue = 0.0f;
|
||||
|
||||
// Clear the canvas to the background color
|
||||
BeginTextureMode(canvas);
|
||||
ClearBackground(RAYWHITE);
|
||||
EndTextureMode();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Disable the hint text once the user clicks
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) startText = false;
|
||||
|
||||
// Clear the canvas when the user middle-clicks
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
||||
{
|
||||
BeginTextureMode(canvas);
|
||||
ClearBackground(RAYWHITE);
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
// Store whether the left and right buttons are down
|
||||
bool leftButtonDown = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
|
||||
bool rightButtonDown = IsMouseButtonDown(MOUSE_BUTTON_RIGHT);
|
||||
|
||||
if (leftButtonDown || rightButtonDown)
|
||||
{
|
||||
// The color for the line
|
||||
Color drawColor = WHITE;
|
||||
|
||||
if (leftButtonDown)
|
||||
{
|
||||
// Increase the hue value by the distance our cursor has moved since the last frame (divided by 3)
|
||||
lineHue += Vector2Distance(mousePositionPrevious, GetMousePosition())/3.0f;
|
||||
|
||||
// While the hue is >=360, subtract it to bring it down into the range 0-360
|
||||
// This is more visually accurate than resetting to zero
|
||||
while (lineHue >= 360.0f) lineHue -= 360.0f;
|
||||
|
||||
// Create the final color
|
||||
drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f);
|
||||
}
|
||||
else if (rightButtonDown) drawColor = RAYWHITE; // Use the background color as an "eraser"
|
||||
|
||||
// Draw the line onto the canvas
|
||||
BeginTextureMode(canvas);
|
||||
// Circles act as "caps", smoothing corners
|
||||
DrawCircleV(mousePositionPrevious, lineThickness/2.0f, drawColor);
|
||||
DrawCircleV(GetMousePosition(), lineThickness/2.0f, drawColor);
|
||||
DrawLineEx(mousePositionPrevious, GetMousePosition(), lineThickness, drawColor);
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
// Update line thickness based on mousewheel
|
||||
lineThickness += GetMouseWheelMove();
|
||||
lineThickness = Clamp(lineThickness, 1.0, 500.0f);
|
||||
|
||||
// Update mouse's previous position
|
||||
mousePositionPrevious = GetMousePosition();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
// Draw the render texture to the screen, flipped vertically to make it appear top-side up
|
||||
DrawTextureRec(canvas.texture, (Rectangle){ 0.0f, 0.0f, (float)canvas.texture.width,(float)-canvas.texture.height }, Vector2Zero(), WHITE);
|
||||
|
||||
// Draw the preview circle
|
||||
if (!leftButtonDown) DrawCircleLinesV(GetMousePosition(), lineThickness/2.0f, (Color){ 127, 127, 127, 127 });
|
||||
|
||||
// Draw the hint text
|
||||
if (startText) DrawText("try clicking and dragging!", 275, 215, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(canvas); // Unload the canvas render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,63 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - logo raylib
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - logo raylib");
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawRectangle(screenWidth/2 - 128, screenHeight/2 - 128, 256, 256, BLACK);
|
||||
DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, RAYWHITE);
|
||||
DrawText("raylib", screenWidth/2 - 44, screenHeight/2 + 48, 50, BLACK);
|
||||
|
||||
DrawText("this is NOT a texture!", 350, 370, 10, GRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,167 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - logo raylib anim
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - logo raylib anim");
|
||||
|
||||
int logoPositionX = screenWidth/2 - 128;
|
||||
int logoPositionY = screenHeight/2 - 128;
|
||||
|
||||
int framesCounter = 0;
|
||||
int lettersCount = 0;
|
||||
|
||||
int topSideRecWidth = 16;
|
||||
int leftSideRecHeight = 16;
|
||||
|
||||
int bottomSideRecWidth = 16;
|
||||
int rightSideRecHeight = 16;
|
||||
|
||||
int state = 0; // Tracking animation states (State Machine)
|
||||
float alpha = 1.0f; // Useful for fading
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (state == 0) // State 0: Small box blinking
|
||||
{
|
||||
framesCounter++;
|
||||
|
||||
if (framesCounter == 120)
|
||||
{
|
||||
state = 1;
|
||||
framesCounter = 0; // Reset counter... will be used later...
|
||||
}
|
||||
}
|
||||
else if (state == 1) // State 1: Top and left bars growing
|
||||
{
|
||||
topSideRecWidth += 4;
|
||||
leftSideRecHeight += 4;
|
||||
|
||||
if (topSideRecWidth == 256) state = 2;
|
||||
}
|
||||
else if (state == 2) // State 2: Bottom and right bars growing
|
||||
{
|
||||
bottomSideRecWidth += 4;
|
||||
rightSideRecHeight += 4;
|
||||
|
||||
if (bottomSideRecWidth == 256) state = 3;
|
||||
}
|
||||
else if (state == 3) // State 3: Letters appearing (one by one)
|
||||
{
|
||||
framesCounter++;
|
||||
|
||||
if (framesCounter/12) // Every 12 frames, one more letter!
|
||||
{
|
||||
lettersCount++;
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (lettersCount >= 10) // When all letters have appeared, just fade out everything
|
||||
{
|
||||
alpha -= 0.02f;
|
||||
|
||||
if (alpha <= 0.0f)
|
||||
{
|
||||
alpha = 0.0f;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == 4) // State 4: Reset and Replay
|
||||
{
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
framesCounter = 0;
|
||||
lettersCount = 0;
|
||||
|
||||
topSideRecWidth = 16;
|
||||
leftSideRecHeight = 16;
|
||||
|
||||
bottomSideRecWidth = 16;
|
||||
rightSideRecHeight = 16;
|
||||
|
||||
alpha = 1.0f;
|
||||
state = 0; // Return to State 0
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
if ((framesCounter/15)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
|
||||
}
|
||||
else if (state == 1)
|
||||
{
|
||||
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
|
||||
DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
|
||||
}
|
||||
else if (state == 2)
|
||||
{
|
||||
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
|
||||
DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
|
||||
|
||||
DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
|
||||
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
|
||||
}
|
||||
else if (state == 3)
|
||||
{
|
||||
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
|
||||
DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
|
||||
|
||||
DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
|
||||
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
|
||||
|
||||
DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
|
||||
|
||||
DrawText(TextSubtext("raylib", 0, lettersCount), GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
|
||||
}
|
||||
else if (state == 4)
|
||||
{
|
||||
DrawText("[R] REPLAY", 340, 200, 20, GRAY);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@ -0,0 +1,105 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - math angle rotation
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Kris (@krispy-snacc) 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 Kris (@krispy-snacc)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h" // for DEG2RAD
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 720;
|
||||
const int screenHeight = 400;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math angle rotation");
|
||||
SetTargetFPS(60);
|
||||
|
||||
Vector2 center = { screenWidth/2.0f, screenHeight/2.0f };
|
||||
const float lineLength = 150.0f;
|
||||
|
||||
// Predefined angles for fixed lines
|
||||
int angles[] = { 0, 30, 60, 90 };
|
||||
int numAngles = sizeof(angles)/sizeof(angles[0]);
|
||||
|
||||
float totalAngle = 0.0f; // Animated rotation angle
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
totalAngle += 1.0f; // degrees per frame
|
||||
if (totalAngle >= 360.0f) totalAngle -= 360.0f;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(WHITE);
|
||||
|
||||
DrawText("Fixed angles + rotating line", 10, 10, 20, LIGHTGRAY);
|
||||
|
||||
// Draw fixed-angle lines with colorful gradient
|
||||
for (int i = 0; i < numAngles; i++)
|
||||
{
|
||||
float rad = angles[i]*DEG2RAD;
|
||||
Vector2 end = { center.x + cosf(rad)*lineLength,
|
||||
center.y + sinf(rad)*lineLength };
|
||||
|
||||
// Gradient color from green → cyan → blue → magenta
|
||||
Color col;
|
||||
switch(i)
|
||||
{
|
||||
case 0: col = GREEN; break;
|
||||
case 1: col = ORANGE; break;
|
||||
case 2: col = BLUE; break;
|
||||
case 3: col = MAGENTA; break;
|
||||
default: col = WHITE; break;
|
||||
}
|
||||
|
||||
DrawLineEx(center, end, 5.0f, col);
|
||||
|
||||
// Draw angle label slightly offset along the line
|
||||
Vector2 textPos = { center.x + cosf(rad)*(lineLength + 20),
|
||||
center.y + sinf(rad)*(lineLength + 20) };
|
||||
DrawText(TextFormat("%d°", angles[i]), (int)textPos.x, (int)textPos.y, 20, col);
|
||||
}
|
||||
|
||||
// Draw animated rotating line with changing color
|
||||
float animRad = totalAngle*DEG2RAD;
|
||||
Vector2 animEnd = { center.x + cosf(animRad)*lineLength,
|
||||
center.y + sinf(animRad)*lineLength };
|
||||
|
||||
// Cycle through HSV colors for animated line
|
||||
Color animCol = ColorFromHSV(fmodf(totalAngle, 360.0f), 0.8f, 0.9f);
|
||||
DrawLineEx(center, animEnd, 5.0f, animCol);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@ -0,0 +1,177 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - math sine cosine
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Jopestpe (@jopestpe) 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 Jopestpe (@jopestpe)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
#include "raymath.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
// Wave points for sine/cosine visualization
|
||||
#define WAVE_POINTS 36
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math sine cosine");
|
||||
|
||||
Vector2 sinePoints[WAVE_POINTS];
|
||||
Vector2 cosPoints[WAVE_POINTS];
|
||||
Vector2 center = { (screenWidth/2.0f) - 30.0f, screenHeight/2.0f };
|
||||
Rectangle start = { 20.0f, screenHeight - 120.f , 200.0f, 100.0f};
|
||||
float radius = 130.0f;
|
||||
float angle = 0.0f;
|
||||
bool pause = false;
|
||||
|
||||
for (int i = 0; i < WAVE_POINTS; i++)
|
||||
{
|
||||
float t = i/(float)(WAVE_POINTS - 1);
|
||||
float currentAngle = t*360.0f*DEG2RAD;
|
||||
sinePoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - sinf(currentAngle)*(start.height/2.0f) };
|
||||
cosPoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - cosf(currentAngle)*(start.height/2.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
|
||||
//----------------------------------------------------------------------------------
|
||||
float angleRad = angle*DEG2RAD;
|
||||
float cosRad = cosf(angleRad);
|
||||
float sinRad = sinf(angleRad);
|
||||
|
||||
Vector2 point = { center.x + cosRad*radius, center.y - sinRad*radius };
|
||||
Vector2 limitMin = { center.x - radius, center.y - radius };
|
||||
Vector2 limitMax = { center.x + radius, center.y + radius };
|
||||
|
||||
float complementary = 90.0f - angle;
|
||||
float supplementary = 180.0f - angle;
|
||||
float explementary = 360.0f - angle;
|
||||
|
||||
float tangent = Clamp(tanf(angleRad), -10.0f, 10.0f);
|
||||
float cotangent = (fabsf(tangent) > 0.001f) ? Clamp(1.0f/tangent, -radius, radius) : 0.0f;
|
||||
Vector2 tangentPoint = { center.x + radius, center.y - tangent*radius };
|
||||
Vector2 cotangentPoint = { center.x + cotangent*radius, center.y - radius };
|
||||
|
||||
angle = Wrap(angle + (!pause ? 1.0f : 0.0f), 0.0f, 360.0f);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Cotangent (orange)
|
||||
DrawLineEx((Vector2){ center.x , limitMin.y }, (Vector2){ cotangentPoint.x, limitMin.y }, 2.0f, ORANGE);
|
||||
DrawLineDashed(center, cotangentPoint, 10, 4, ORANGE);
|
||||
|
||||
// Side background
|
||||
DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 });
|
||||
DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 });
|
||||
|
||||
// Base circle and axes
|
||||
DrawCircleLinesV(center, radius, GRAY);
|
||||
DrawLineEx((Vector2){ center.x, limitMin.y }, (Vector2){ center.x, limitMax.y }, 1.0f, GRAY);
|
||||
DrawLineEx((Vector2){ limitMin.x, center.y }, (Vector2){ limitMax.x, center.y }, 1.0f, GRAY);
|
||||
|
||||
// Wave graph axes
|
||||
DrawLineEx((Vector2){ start.x , start.y }, (Vector2){ start.x , start.y + start.height }, 2.0f, GRAY);
|
||||
DrawLineEx((Vector2){ start.x + start.width, start.y }, (Vector2){ start.x + start.width, start.y + start.height }, 2.0f, GRAY);
|
||||
DrawLineEx((Vector2){ start.x, start.y + start.height/2 }, (Vector2){ start.x + start.width, start.y + start.height/2 }, 2.0f, GRAY);
|
||||
|
||||
// Wave graph axis labels
|
||||
DrawText("1", (int)start.x - 8, (int)start.y, 6, GRAY);
|
||||
DrawText("0", (int)start.x - 8, (int)start.y + (int)start.height/2 - 6, 6, GRAY);
|
||||
DrawText("-1", (int)start.x - 12, (int)start.y + (int)start.height - 8, 6, GRAY);
|
||||
DrawText("0", (int)start.x - 2, (int)start.y + (int)start.height + 4, 6, GRAY);
|
||||
DrawText("360", (int)start.x + (int)start.width - 8, (int)start.y + (int)start.height + 4, 6, GRAY);
|
||||
|
||||
// Sine (red - vertical)
|
||||
DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ center.x, point.y }, 2.0f, RED);
|
||||
DrawLineDashed((Vector2){ point.x, center.y }, (Vector2){ point.x, point.y }, 10, 4, RED);
|
||||
DrawText(TextFormat("Sine %.2f", sinRad), 640, 190, 6, RED);
|
||||
DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-sinRad + 1)*start.height/2.0f) }, 4.0f, RED);
|
||||
DrawSplineLinear(sinePoints, WAVE_POINTS, 1.0f, RED);
|
||||
|
||||
// Cosine (blue - horizontal)
|
||||
DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ point.x, center.y }, 2.0f, BLUE);
|
||||
DrawLineDashed((Vector2){ center.x , point.y }, (Vector2){ point.x, point.y }, 10, 4, BLUE);
|
||||
DrawText(TextFormat("Cosine %.2f", cosRad), 640, 210, 6, BLUE);
|
||||
DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-cosRad + 1)*start.height/2.0f) }, 4.0f, BLUE);
|
||||
DrawSplineLinear(cosPoints, WAVE_POINTS, 1.0f, BLUE);
|
||||
|
||||
// Tangent (purple)
|
||||
DrawLineEx((Vector2){ limitMax.x , center.y }, (Vector2){ limitMax.x, tangentPoint.y }, 2.0f, PURPLE);
|
||||
DrawLineDashed(center, tangentPoint, 10, 4, PURPLE);
|
||||
DrawText(TextFormat("Tangent %.2f", tangent), 640, 230, 6, PURPLE);
|
||||
|
||||
// Cotangent (orange)
|
||||
DrawText(TextFormat("Cotangent %.2f", cotangent), 640, 250, 6, ORANGE);
|
||||
|
||||
// Complementary angle (beige)
|
||||
DrawCircleSectorLines(center, radius*0.6f , -angle, -90.0f , 36, BEIGE);
|
||||
DrawText(TextFormat("Complementary %0.f°",complementary), 640, 150, 6, BEIGE);
|
||||
|
||||
// Supplementary angle (darkblue)
|
||||
DrawCircleSectorLines(center, radius*0.5f , -angle, -180.0f , 36, DARKBLUE);
|
||||
DrawText(TextFormat("Supplementary %0.f°",supplementary), 640, 130, 6, DARKBLUE);
|
||||
|
||||
// Explementary angle (pink)
|
||||
DrawCircleSectorLines(center, radius*0.4f , -angle, -360.0f , 36, PINK);
|
||||
DrawText(TextFormat("Explementary %0.f°",explementary), 640, 170, 6, PINK);
|
||||
|
||||
// Current angle - arc (lime), radius (black), endpoint (black)
|
||||
DrawCircleSectorLines(center, radius*0.7f , -angle, 0.0f, 36, LIME);
|
||||
DrawLineEx((Vector2){ center.x , center.y }, point, 2.0f, BLACK);
|
||||
DrawCircleV(point, 4.0f, BLACK);
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GRAY));
|
||||
GuiToggle((Rectangle){ 640, 70, 120, 20}, TextFormat("Pause"), &pause);
|
||||
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(LIME));
|
||||
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f°", angle), &angle, 0.0f, 360.0f);
|
||||
|
||||
// Angle values panel
|
||||
GuiGroupBox((Rectangle){ 620, 110, 140, 170}, "Angle Values");
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,102 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - Draw a mouse trail (position history)
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.6
|
||||
*
|
||||
* Example contributed by Balamurugan R (@Bala050814]) 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 Balamurugan R (@Bala050814)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
// Define the maximum number of positions to store in the trail
|
||||
#define MAX_TRAIL_LENGTH 30
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - mouse trail");
|
||||
|
||||
// Array to store the history of mouse positions (our fixed-size queue)
|
||||
Vector2 trailPositions[MAX_TRAIL_LENGTH] = { 0 };
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
|
||||
// Shift all existing positions backward by one slot in the array
|
||||
// The last element (the oldest position) is dropped
|
||||
for (int i = MAX_TRAIL_LENGTH - 1; i > 0; i--)
|
||||
{
|
||||
trailPositions[i] = trailPositions[i - 1];
|
||||
}
|
||||
|
||||
// Store the new, current mouse position at the start of the array (Index 0)
|
||||
trailPositions[0] = mousePosition;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
// Draw the trail by looping through the history array
|
||||
for (int i = 0; i < MAX_TRAIL_LENGTH; i++)
|
||||
{
|
||||
// Ensure we skip drawing if the array hasn't been fully filled on startup
|
||||
if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f))
|
||||
{
|
||||
// Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old)
|
||||
float ratio = (float)(MAX_TRAIL_LENGTH - i)/MAX_TRAIL_LENGTH;
|
||||
|
||||
// Fade effect: oldest positions are more transparent
|
||||
// Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio
|
||||
Color trailColor = Fade(SKYBLUE, ratio*0.5f + 0.5f);
|
||||
|
||||
// Size effect: oldest positions are smaller
|
||||
float trailRadius = 15.0f*ratio;
|
||||
|
||||
DrawCircleV(trailPositions[i], trailRadius, trailColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a distinct white circle for the current mouse position (Index 0)
|
||||
DrawCircleV(mousePosition, 15.0f, WHITE);
|
||||
|
||||
DrawText("Move the mouse to see the trail effect!", 10, screenHeight - 30, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
@ -0,0 +1,271 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - penrose tile
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
* Based on: https://processing.org/examples/penrosetile.html
|
||||
*
|
||||
* Example contributed by David Buzatto (@davidbuzatto) 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 David Buzatto (@davidbuzatto)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define STR_MAX_SIZE 10000
|
||||
#define TURTLE_STACK_MAX_SIZE 50
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct TurtleState {
|
||||
Vector2 origin;
|
||||
float angle;
|
||||
} TurtleState;
|
||||
|
||||
typedef struct PenroseLSystem {
|
||||
int steps;
|
||||
char *production;
|
||||
const char *ruleW;
|
||||
const char *ruleX;
|
||||
const char *ruleY;
|
||||
const char *ruleZ;
|
||||
float drawLength;
|
||||
float theta;
|
||||
} PenroseLSystem;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static TurtleState turtleStack[TURTLE_STACK_MAX_SIZE];
|
||||
static int turtleTop = -1;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void PushTurtleState(TurtleState state);
|
||||
static TurtleState PopTurtleState(void);
|
||||
static PenroseLSystem CreatePenroseLSystem(float drawLength);
|
||||
static void BuildProductionStep(PenroseLSystem *ls);
|
||||
static void DrawPenroseLSystem(PenroseLSystem *ls);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - penrose tile");
|
||||
|
||||
float drawLength = 460.0f;
|
||||
int minGenerations = 0;
|
||||
int maxGenerations = 4;
|
||||
int generations = 0;
|
||||
|
||||
// Initializee new penrose tile
|
||||
PenroseLSystem ls = CreatePenroseLSystem(drawLength*(generations/(float)maxGenerations));
|
||||
for (int i = 0; i < generations; i++) BuildProductionStep(&ls);
|
||||
|
||||
SetTargetFPS(120); // Set our game to run at 120 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
bool rebuild = false;
|
||||
if (IsKeyPressed(KEY_UP))
|
||||
{
|
||||
if (generations < maxGenerations)
|
||||
{
|
||||
generations++;
|
||||
rebuild = true;
|
||||
}
|
||||
}
|
||||
else if (IsKeyPressed(KEY_DOWN))
|
||||
{
|
||||
if (generations > minGenerations)
|
||||
{
|
||||
generations--;
|
||||
if (generations > 0) rebuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rebuild)
|
||||
{
|
||||
RL_FREE(ls.production); // Free previous production for re-creation
|
||||
ls = CreatePenroseLSystem(drawLength*(generations/(float)maxGenerations));
|
||||
for (int i = 0; i < generations; i++) BuildProductionStep(&ls);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground( RAYWHITE );
|
||||
|
||||
if (generations > 0) DrawPenroseLSystem(&ls);
|
||||
|
||||
DrawText("penrose l-system", 10, 10, 20, DARKGRAY);
|
||||
DrawText("press up or down to change generations", 10, 30, 20, DARKGRAY);
|
||||
DrawText(TextFormat("generations: %d", generations), 10, 50, 20, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Push turtle state for next step
|
||||
static void PushTurtleState(TurtleState state)
|
||||
{
|
||||
if (turtleTop < (TURTLE_STACK_MAX_SIZE - 1)) turtleStack[++turtleTop] = state;
|
||||
else TraceLog(LOG_WARNING, "TURTLE STACK OVERFLOW!");
|
||||
}
|
||||
|
||||
// Pop turtle state step
|
||||
static TurtleState PopTurtleState(void)
|
||||
{
|
||||
if (turtleTop >= 0) return turtleStack[turtleTop--];
|
||||
else TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
|
||||
|
||||
return (TurtleState){ 0 };
|
||||
}
|
||||
|
||||
// Create a new penrose tile structure
|
||||
static PenroseLSystem CreatePenroseLSystem(float drawLength)
|
||||
{
|
||||
// TODO: Review constant values assignment on recreation?
|
||||
PenroseLSystem ls = {
|
||||
.steps = 0,
|
||||
.ruleW = "YF++ZF4-XF[-YF4-WF]++",
|
||||
.ruleX = "+YF--ZF[3-WF--XF]+",
|
||||
.ruleY = "-WF++XF[+++YF++ZF]-",
|
||||
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
|
||||
.drawLength = drawLength,
|
||||
.theta = 36.0f // Degrees
|
||||
};
|
||||
|
||||
ls.production = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
||||
ls.production[0] = '\0';
|
||||
strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE);
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
// Build next penrose step
|
||||
static void BuildProductionStep(PenroseLSystem *ls)
|
||||
{
|
||||
char *newProduction = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
|
||||
newProduction[0] = '\0';
|
||||
|
||||
int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE);
|
||||
|
||||
for (int i = 0; i < productionLength; i++)
|
||||
{
|
||||
char step = ls->production[i];
|
||||
int remainingSpace = STR_MAX_SIZE - (int)strnlen(newProduction, STR_MAX_SIZE) - 1;
|
||||
switch (step)
|
||||
{
|
||||
case 'W': strncat(newProduction, ls->ruleW, remainingSpace); break;
|
||||
case 'X': strncat(newProduction, ls->ruleX, remainingSpace); break;
|
||||
case 'Y': strncat(newProduction, ls->ruleY, remainingSpace); break;
|
||||
case 'Z': strncat(newProduction, ls->ruleZ, remainingSpace); break;
|
||||
default:
|
||||
{
|
||||
if (step != 'F')
|
||||
{
|
||||
int t = (int)strnlen(newProduction, STR_MAX_SIZE);
|
||||
newProduction[t] = step;
|
||||
newProduction[t + 1] = '\0';
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
ls->drawLength *= 0.5f;
|
||||
strncpy(ls->production, newProduction, STR_MAX_SIZE);
|
||||
|
||||
RL_FREE(newProduction);
|
||||
}
|
||||
|
||||
// Draw penrose tile lines
|
||||
static void DrawPenroseLSystem(PenroseLSystem *ls)
|
||||
{
|
||||
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
|
||||
|
||||
TurtleState turtle = {
|
||||
.origin = { 0 },
|
||||
.angle = -90.0f
|
||||
};
|
||||
|
||||
int repeats = 1;
|
||||
int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE);
|
||||
ls->steps += 12;
|
||||
|
||||
if (ls->steps > productionLength) ls->steps = productionLength;
|
||||
|
||||
for (int i = 0; i < ls->steps; i++)
|
||||
{
|
||||
char step = ls->production[i];
|
||||
if (step == 'F')
|
||||
{
|
||||
for (int j = 0; j < repeats; j++)
|
||||
{
|
||||
Vector2 startPosWorld = turtle.origin;
|
||||
float radAngle = DEG2RAD*turtle.angle;
|
||||
turtle.origin.x += ls->drawLength*cosf(radAngle);
|
||||
turtle.origin.y += ls->drawLength*sinf(radAngle);
|
||||
Vector2 startPosScreen = { startPosWorld.x + screenCenter.x, startPosWorld.y + screenCenter.y };
|
||||
Vector2 endPosScreen = { turtle.origin.x + screenCenter.x, turtle.origin.y + screenCenter.y };
|
||||
|
||||
DrawLineEx(startPosScreen, endPosScreen, 2, Fade(BLACK, 0.2f));
|
||||
}
|
||||
|
||||
repeats = 1;
|
||||
}
|
||||
else if (step == '+')
|
||||
{
|
||||
for (int j = 0; j < repeats; j++) turtle.angle += ls->theta;
|
||||
|
||||
repeats = 1;
|
||||
}
|
||||
else if (step == '-')
|
||||
{
|
||||
for (int j = 0; j < repeats; j++) turtle.angle += -ls->theta;
|
||||
|
||||
repeats = 1;
|
||||
}
|
||||
else if (step == '[') PushTurtleState(turtle);
|
||||
else if (step == ']') turtle = PopTurtleState();
|
||||
else if ((step >= 48) && (step <= 57)) repeats = (int) step - 48;
|
||||
}
|
||||
|
||||
turtleTop = -1;
|
||||
}
|
||||
|
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,228 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - pie chart
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Gideon Serfontein (@GideonSerf) 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 Gideon Serfontein (@GideonSerf)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#define MAX_PIE_SLICES 10 // Max pie slices
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - pie chart");
|
||||
|
||||
int sliceCount = 7;
|
||||
float donutInnerRadius = 25.0f;
|
||||
float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values
|
||||
char labels[MAX_PIE_SLICES][32] = { 0 };
|
||||
bool editingLabel[MAX_PIE_SLICES] = { 0 };
|
||||
|
||||
for (int i = 0; i < MAX_PIE_SLICES; i++)
|
||||
snprintf(labels[i], 32, "Slice %02i", i + 1);
|
||||
|
||||
bool showValues = true;
|
||||
bool showPercentages = false;
|
||||
bool showDonut = false;
|
||||
int hoveredSlice = -1;
|
||||
Rectangle scrollPanelBounds = { 0 };
|
||||
Vector2 scrollContentOffset = { 0 };
|
||||
Rectangle view = { 0 };
|
||||
|
||||
// UI layout parameters
|
||||
const int panelWidth = 270;
|
||||
const int panelMargin = 5;
|
||||
|
||||
// UI Panel top-left anchor
|
||||
const Vector2 panelPos = {
|
||||
(float)screenWidth - panelMargin - panelWidth,
|
||||
(float)panelMargin
|
||||
};
|
||||
|
||||
// UI Panel rectangle
|
||||
const Rectangle panelRect = {
|
||||
panelPos.x, panelPos.y,
|
||||
(float)panelWidth,
|
||||
(float)screenHeight - 2.0f*panelMargin
|
||||
};
|
||||
|
||||
// Pie chart geometry
|
||||
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
|
||||
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f};
|
||||
const float radius = 205.0f;
|
||||
|
||||
// Total value for percentage calculations
|
||||
float totalValue = 0.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Calculate total value for percentage calculations
|
||||
totalValue = 0.0f;
|
||||
for (int i = 0; i < sliceCount; i++) totalValue += values[i];
|
||||
|
||||
// Check for mouse hover over slices
|
||||
hoveredSlice = -1; // Reset hovered slice
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
|
||||
{
|
||||
float dx = mousePos.x - center.x;
|
||||
float dy = mousePos.y - center.y;
|
||||
float distance = sqrtf(dx*dx + dy*dy);
|
||||
|
||||
if (distance <= radius) // Inside the pie radius
|
||||
{
|
||||
float angle = atan2f(dy, dx)*RAD2DEG;
|
||||
if (angle < 0) angle += 360;
|
||||
|
||||
float currentAngle = 0.0f;
|
||||
for (int i = 0; i < sliceCount; i++)
|
||||
{
|
||||
float sweep = (totalValue > 0)? (values[i]/totalValue)*360.0f : 0.0f;
|
||||
|
||||
if ((angle >= currentAngle) && (angle < (currentAngle + sweep)))
|
||||
{
|
||||
hoveredSlice = i;
|
||||
break;
|
||||
}
|
||||
|
||||
currentAngle += sweep;
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw the pie chart on the canvas
|
||||
float startAngle = 0.0f;
|
||||
for (int i = 0; i < sliceCount; i++)
|
||||
{
|
||||
float sweepAngle = (totalValue > 0)? (values[i]/totalValue)*360.0f : 0.0f;
|
||||
float midAngle = startAngle + sweepAngle/2.0f; // Middle angle for label positioning
|
||||
|
||||
Color color = ColorFromHSV((float)i/sliceCount*360.0f, 0.75f, 0.9f);
|
||||
float currentRadius = radius;
|
||||
|
||||
// Make the hovered slice pop out by adding 5 pixels to its radius
|
||||
if (i == hoveredSlice) currentRadius += 20.0f;
|
||||
|
||||
// Draw the pie slice using raylib's DrawCircleSector function
|
||||
DrawCircleSector(center, currentRadius, startAngle, startAngle + sweepAngle, 120, color);
|
||||
|
||||
// Draw the label for the current slice
|
||||
if (values[i] > 0)
|
||||
{
|
||||
char labelText[64] = { 0 };
|
||||
if (showValues && showPercentages) snprintf(labelText, 64, "%.1f (%.0f%%)", values[i], (values[i]/totalValue)*100.0f);
|
||||
else if (showValues) snprintf(labelText, 64, "%.1f", values[i]);
|
||||
else if (showPercentages) snprintf(labelText, 64, "%.0f%%", (values[i]/totalValue)*100.0f);
|
||||
else labelText[0] = '\0';
|
||||
|
||||
Vector2 textSize = MeasureTextEx(GetFontDefault(), labelText, 20, 1);
|
||||
float labelRadius = radius*0.7f;
|
||||
Vector2 labelPos = { center.x + cosf(midAngle*DEG2RAD)*labelRadius - textSize.x/2.0f,
|
||||
center.y + sinf(midAngle*DEG2RAD)*labelRadius - textSize.y/2.0f };
|
||||
DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 20, WHITE);
|
||||
}
|
||||
|
||||
// Draw inner circle to create donut effect
|
||||
// TODO: This is a hacky solution, better use DrawRing()
|
||||
if (showDonut) DrawCircleV(center, donutInnerRadius, RAYWHITE);
|
||||
|
||||
startAngle += sweepAngle;
|
||||
}
|
||||
|
||||
// UI control panel
|
||||
DrawRectangleRec(panelRect, Fade(LIGHTGRAY, 0.5f));
|
||||
DrawRectangleLinesEx(panelRect, 1.0f, GRAY);
|
||||
|
||||
GuiSpinner((Rectangle){ panelPos.x + 95, (float)panelPos.y + 12, 125, 25 }, "Slices ", &sliceCount, 1, MAX_PIE_SLICES, false);
|
||||
GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 40, 20, 20 }, "Show Values", &showValues);
|
||||
GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 70, 20, 20 }, "Show Percentages", &showPercentages);
|
||||
GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 100, 20, 20 }, "Make Donut", &showDonut);
|
||||
|
||||
if (showDonut) GuiDisable();
|
||||
GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 },
|
||||
"Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f);
|
||||
GuiEnable();
|
||||
|
||||
GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL);
|
||||
|
||||
// Scrollable area for slice editors
|
||||
scrollPanelBounds = (Rectangle){
|
||||
panelPos.x + panelMargin,
|
||||
(float)panelPos.y + 12 + 190,
|
||||
panelRect.width - panelMargin*2,
|
||||
panelRect.y + panelRect.height - panelPos.y + 12 + 190 - panelMargin
|
||||
};
|
||||
int contentHeight = sliceCount*35;
|
||||
|
||||
GuiScrollPanel(scrollPanelBounds, NULL,
|
||||
(Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
|
||||
&scrollContentOffset, &view);
|
||||
|
||||
const float contentX = view.x + scrollContentOffset.x; // Left of content
|
||||
const float contentY = view.y + scrollContentOffset.y; // Top of content
|
||||
|
||||
BeginScissorMode((int)view.x, (int)view.y, (int)view.width, (int)view.height);
|
||||
|
||||
for (int i = 0; i < sliceCount; i++)
|
||||
{
|
||||
const int rowY = (int)(contentY + 5 + i*35);
|
||||
|
||||
// Color indicator
|
||||
Color color = ColorFromHSV((float)i/sliceCount*360.0f, 0.75f, 0.9f);
|
||||
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);
|
||||
|
||||
// Label textbox
|
||||
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i];
|
||||
|
||||
GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f);
|
||||
}
|
||||
|
||||
EndScissorMode();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,358 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - rectangle advanced
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Everton Jr. (@evertonse) 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) 2024-2025 Everton Jr. (@evertonse) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "rlgl.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Draw rectangle with rounded edges and horizontal gradient, with options to choose side of roundness
|
||||
static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle advanced");
|
||||
|
||||
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 rectangle bounds
|
||||
//----------------------------------------------------------------------------------
|
||||
float width = GetScreenWidth()/2.0f, height = GetScreenHeight()/6.0f;
|
||||
Rectangle rec = {
|
||||
GetScreenWidth()/2.0f - width/2,
|
||||
GetScreenHeight()/2.0f - 5*(height/2),
|
||||
width, height
|
||||
};
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw All Rectangles with different roundess for each side and different gradients
|
||||
DrawRectangleRoundedGradientH(rec, 0.8f, 0.8f, 36, BLUE, RED);
|
||||
|
||||
rec.y += rec.height + 1;
|
||||
DrawRectangleRoundedGradientH(rec, 0.5f, 1.0f, 36, RED, PINK);
|
||||
|
||||
rec.y += rec.height + 1;
|
||||
DrawRectangleRoundedGradientH(rec, 1.0f, 0.5f, 36, RED, BLUE);
|
||||
|
||||
rec.y += rec.height + 1;
|
||||
DrawRectangleRoundedGradientH(rec, 0.0f, 1.0f, 36, BLUE, BLACK);
|
||||
|
||||
rec.y += rec.height + 1;
|
||||
DrawRectangleRoundedGradientH(rec, 1.0f, 0.0f, 36, BLUE, PINK);
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Draw rectangle with rounded edges and horizontal gradient, with options to choose side of roundness
|
||||
// NOTE: Adapted from both 'DrawRectangleRounded()' and 'DrawRectangleGradientH()' raylib [rshapes] implementations
|
||||
static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right)
|
||||
{
|
||||
// Neither side is rounded
|
||||
if ((roundnessLeft <= 0.0f && roundnessRight <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
|
||||
{
|
||||
DrawRectangleGradientEx(rec, left, left, right, right);
|
||||
return;
|
||||
}
|
||||
|
||||
if (roundnessLeft >= 1.0f) roundnessLeft = 1.0f;
|
||||
if (roundnessRight >= 1.0f) roundnessRight = 1.0f;
|
||||
|
||||
// Calculate corner radius both from right and left
|
||||
float recSize = rec.width > rec.height ? rec.height : rec.width;
|
||||
float radiusLeft = (recSize*roundnessLeft)/2;
|
||||
float radiusRight = (recSize*roundnessRight)/2;
|
||||
|
||||
if (radiusLeft <= 0.0f) radiusLeft = 0.0f;
|
||||
if (radiusRight <= 0.0f) radiusRight = 0.0f;
|
||||
|
||||
if (radiusRight <= 0.0f && radiusLeft <= 0.0f) return;
|
||||
|
||||
float stepLength = 90.0f/(float)segments;
|
||||
|
||||
/*
|
||||
Diagram Copied here for reference, original at 'DrawRectangleRounded()' source code
|
||||
|
||||
P0____________________P1
|
||||
/| |\
|
||||
/1| 2 |3\
|
||||
P7 /__|____________________|__\ P2
|
||||
| |P8 P9| |
|
||||
| 8 | 9 | 4 |
|
||||
| __|____________________|__ |
|
||||
P6 \ |P11 P10| / P3
|
||||
\7| 6 |5/
|
||||
\|____________________|/
|
||||
P5 P4
|
||||
*/
|
||||
|
||||
// Coordinates of the 12 points also apdated from `DrawRectangleRounded`
|
||||
const Vector2 point[12] = {
|
||||
// PO, P1, P2
|
||||
{(float)rec.x + radiusLeft, rec.y}, {(float)(rec.x + rec.width) - radiusRight, rec.y}, { rec.x + rec.width, (float)rec.y + radiusRight },
|
||||
// P3, P4
|
||||
{rec.x + rec.width, (float)(rec.y + rec.height) - radiusRight}, {(float)(rec.x + rec.width) - radiusRight, rec.y + rec.height},
|
||||
// P5, P6, P7
|
||||
{(float)rec.x + radiusLeft, rec.y + rec.height}, { rec.x, (float)(rec.y + rec.height) - radiusLeft}, {rec.x, (float)rec.y + radiusLeft},
|
||||
// P8, P9
|
||||
{(float)rec.x + radiusLeft, (float)rec.y + radiusLeft}, {(float)(rec.x + rec.width) - radiusRight, (float)rec.y + radiusRight},
|
||||
// P10, P11
|
||||
{(float)(rec.x + rec.width) - radiusRight, (float)(rec.y + rec.height) - radiusRight}, {(float)rec.x + radiusLeft, (float)(rec.y + rec.height) - radiusLeft}
|
||||
};
|
||||
|
||||
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
||||
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||
|
||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||
rlSetTexture(GetShapesTexture().id);
|
||||
Rectangle shapeRect = GetShapesTextureRectangle();
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
// Draw all the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
Color color;
|
||||
float radius;
|
||||
if (k == 0) color = left, radius = radiusLeft; // [1] Upper Left Corner
|
||||
if (k == 1) color = right, radius = radiusRight; // [3] Upper Right Corner
|
||||
if (k == 2) color = right, radius = radiusRight; // [5] Lower Right Corner
|
||||
if (k == 3) color = left, radius = radiusLeft; // [7] Lower Left Corner
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
|
||||
for (int i = 0; i < segments/2; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x, center.y);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||
|
||||
angle += (stepLength*2);
|
||||
}
|
||||
|
||||
// End one even segments
|
||||
if ( segments%2)
|
||||
{
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x, center.y);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x, center.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Here we use the 'Diagram' to guide ourselves to which point receives what color
|
||||
// By choosing the color correctly associated with a pointe the gradient effect
|
||||
// will naturally come from OpenGL interpolation
|
||||
|
||||
// [2] Upper Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
|
||||
// [4] Left Rectangle
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// [6] Bottom Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
|
||||
// [8] left Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
|
||||
// [9] Middle Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
|
||||
rlEnd();
|
||||
rlSetTexture(0);
|
||||
#else
|
||||
|
||||
// Here we use the 'Diagram' to guide ourselves to which point receives what color
|
||||
// By choosing the color correctly associated with a pointe the gradient effect
|
||||
// will naturally come from OpenGL interpolation
|
||||
// But this time instead of Quad, we think in triangles
|
||||
|
||||
rlBegin(RL_TRIANGLES);
|
||||
// Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
Color color = { 0 };
|
||||
float radius = 0.0f;
|
||||
if (k == 0) color = left, radius = radiusLeft; // [1] Upper Left Corner
|
||||
if (k == 1) color = right, radius = radiusRight; // [3] Upper Right Corner
|
||||
if (k == 2) color = right, radius = radiusRight; // [5] Lower Right Corner
|
||||
if (k == 3) color = left, radius = radiusLeft; // [7] Lower Left Corner
|
||||
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||
angle += stepLength;
|
||||
}
|
||||
}
|
||||
|
||||
// [2] Upper Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
|
||||
// [4] Right Rectangle
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// [6] Bottom Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
|
||||
// [8] Left Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
|
||||
// [9] Middle Rectangle
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlColor4ub(left.r, left.g, left.b, left.a);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlColor4ub(right.r, right.g, right.b, right.a);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlEnd();
|
||||
#endif
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,105 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - rectangle scaling
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) 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) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MOUSE_SCALE_MARK_SIZE 12
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle scaling");
|
||||
|
||||
Rectangle rec = { 100, 100, 200, 80 };
|
||||
|
||||
Vector2 mousePosition = { 0 };
|
||||
|
||||
bool mouseScaleReady = false;
|
||||
bool mouseScaleMode = 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
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePosition = GetMousePosition();
|
||||
|
||||
if (CheckCollisionPointRec(mousePosition, (Rectangle){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE, MOUSE_SCALE_MARK_SIZE }))
|
||||
{
|
||||
mouseScaleReady = true;
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) mouseScaleMode = true;
|
||||
}
|
||||
else mouseScaleReady = false;
|
||||
|
||||
if (mouseScaleMode)
|
||||
{
|
||||
mouseScaleReady = true;
|
||||
|
||||
rec.width = (mousePosition.x - rec.x);
|
||||
rec.height = (mousePosition.y - rec.y);
|
||||
|
||||
// Check minimum rec size
|
||||
if (rec.width < MOUSE_SCALE_MARK_SIZE) rec.width = MOUSE_SCALE_MARK_SIZE;
|
||||
if (rec.height < MOUSE_SCALE_MARK_SIZE) rec.height = MOUSE_SCALE_MARK_SIZE;
|
||||
|
||||
// Check maximum rec size
|
||||
if (rec.width > (GetScreenWidth() - rec.x)) rec.width = GetScreenWidth() - rec.x;
|
||||
if (rec.height > (GetScreenHeight() - rec.y)) rec.height = GetScreenHeight() - rec.y;
|
||||
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) mouseScaleMode = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Scale rectangle dragging from bottom-right corner!", 10, 10, 20, GRAY);
|
||||
|
||||
DrawRectangleRec(rec, Fade(GREEN, 0.5f));
|
||||
|
||||
if (mouseScaleReady)
|
||||
{
|
||||
DrawRectangleLinesEx(rec, 1, RED);
|
||||
DrawTriangle((Vector2){ rec.x + rec.width - MOUSE_SCALE_MARK_SIZE, rec.y + rec.height },
|
||||
(Vector2){ rec.x + rec.width, rec.y + rec.height },
|
||||
(Vector2){ rec.x + rec.width, rec.y + rec.height - MOUSE_SCALE_MARK_SIZE }, RED);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,132 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - recursive tree
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* 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) 2025 Jopestpe (@jopestpe)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
#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;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - recursive tree");
|
||||
|
||||
Vector2 start = { (screenWidth/2.0f) - 125.0f, (float)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, floorf(treeDepth)));
|
||||
Branch branches[1030] = { 0 };
|
||||
int count = 0;
|
||||
|
||||
Vector2 initialEnd = { start.x + length*sinf(0.0f), start.y - length*cosf(0.0f) };
|
||||
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;
|
||||
|
||||
float angle1 = branch.angle + theta;
|
||||
Vector2 branchEnd1 = { branchStart.x + nextLength*sinf(angle1), branchStart.y - nextLength*cosf(angle1) };
|
||||
branches[count++] = (Branch){branchStart, branchEnd1, angle1, nextLength};
|
||||
|
||||
float angle2 = branch.angle - theta;
|
||||
Vector2 branchEnd2 = { branchStart.x + nextLength*sinf(angle2), branchStart.y - nextLength*cosf(angle2) };
|
||||
branches[count++] = (Branch){branchStart, branchEnd2, angle2, nextLength};
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Branch branch = branches[i];
|
||||
if (branch.length >= 2)
|
||||
{
|
||||
if (bezier) DrawLineBezier(branch.start, branch.end, thick, RED);
|
||||
else DrawLineEx(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.0f);
|
||||
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;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,102 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - ring drawing
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) 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) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ring drawing");
|
||||
|
||||
Vector2 center = {(GetScreenWidth() - 300)/2.0f, GetScreenHeight()/2.0f };
|
||||
|
||||
float innerRadius = 80.0f;
|
||||
float outerRadius = 190.0f;
|
||||
|
||||
float startAngle = 0.0f;
|
||||
float endAngle = 360.0f;
|
||||
float segments = 0.0f;
|
||||
|
||||
bool drawRing = true;
|
||||
bool drawRingLines = false;
|
||||
bool drawCircleLines = 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
|
||||
//----------------------------------------------------------------------------------
|
||||
// NOTE: All variables update happens inside GUI control functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawLine(500, 0, 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.6f));
|
||||
DrawRectangle(500, 0, GetScreenWidth() - 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
if (drawRing) DrawRing(center, innerRadius, outerRadius, startAngle, endAngle, (int)segments, Fade(MAROON, 0.3f));
|
||||
if (drawRingLines) DrawRingLines(center, innerRadius, outerRadius, startAngle, endAngle, (int)segments, Fade(BLACK, 0.4f));
|
||||
if (drawCircleLines) DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, (int)segments, Fade(BLACK, 0.4f));
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
GuiSliderBar((Rectangle){ 600, 40, 120, 20 }, "StartAngle", TextFormat("%.2f", startAngle), &startAngle, -450, 450);
|
||||
GuiSliderBar((Rectangle){ 600, 70, 120, 20 }, "EndAngle", TextFormat("%.2f", endAngle), &endAngle, -450, 450);
|
||||
|
||||
GuiSliderBar((Rectangle){ 600, 140, 120, 20 }, "InnerRadius", TextFormat("%.2f", innerRadius), &innerRadius, 0, 100);
|
||||
GuiSliderBar((Rectangle){ 600, 170, 120, 20 }, "OuterRadius", TextFormat("%.2f", outerRadius), &outerRadius, 0, 200);
|
||||
|
||||
GuiSliderBar((Rectangle){ 600, 240, 120, 20 }, "Segments", TextFormat("%.2f", segments), &segments, 0, 100);
|
||||
|
||||
GuiCheckBox((Rectangle){ 600, 320, 20, 20 }, "Draw Ring", &drawRing);
|
||||
GuiCheckBox((Rectangle){ 600, 350, 20, 20 }, "Draw RingLines", &drawRingLines);
|
||||
GuiCheckBox((Rectangle){ 600, 380, 20, 20 }, "Draw CircleLines", &drawCircleLines);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int minSegments = (int)ceilf((endAngle - startAngle)/90);
|
||||
DrawText(TextFormat("MODE: %s", (segments >= minSegments)? "MANUAL" : "AUTO"), 600, 270, 10, (segments >= minSegments)? MAROON : DARKGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,274 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - rlgl color wheel
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Robin (@RobinsAviary) 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 Robin (@RobinsAviary)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rlgl.h"
|
||||
#include "raymath.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// The minimum/maximum points the circle can have
|
||||
const unsigned int pointsMin = 3;
|
||||
const unsigned int pointsMax = 256;
|
||||
|
||||
// The current number of points and the radius of the circle
|
||||
unsigned int triangleCount = 64;
|
||||
float pointScale = 150.0f;
|
||||
|
||||
// Slider value, literally maps to value in HSV
|
||||
float value = 1.0f;
|
||||
|
||||
// The center of the screen
|
||||
Vector2 center = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
|
||||
// The location of the color wheel
|
||||
Vector2 circlePosition = center;
|
||||
|
||||
// The currently selected color
|
||||
Color color = { 255, 255, 255, 255 };
|
||||
|
||||
// Indicates if the slider is being clicked
|
||||
bool sliderClicked = false;
|
||||
|
||||
// Indicates if the current color going to be updated, as well as the handle position
|
||||
bool settingColor = false;
|
||||
|
||||
// How the color wheel will be rendered
|
||||
unsigned int renderType = RL_TRIANGLES;
|
||||
|
||||
// Enable anti-aliasing
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl color wheel");
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
triangleCount += (unsigned int)GetMouseWheelMove();
|
||||
triangleCount = (unsigned int)Clamp((float)triangleCount, (float)pointsMin, (float)pointsMax);
|
||||
|
||||
Rectangle sliderRectangle = { 42.0f, 16.0f + 64.0f + 45.0f, 64.0f, 16.0f };
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
|
||||
// Checks if the user is hovering over the value slider
|
||||
bool sliderHover = (mousePosition.x >= sliderRectangle.x && mousePosition.y >= sliderRectangle.y && mousePosition.x < sliderRectangle.x + sliderRectangle.width && mousePosition.y < sliderRectangle.y + sliderRectangle.height);
|
||||
|
||||
// Copy color as hex
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
|
||||
{
|
||||
if (IsKeyPressed(KEY_C))
|
||||
{
|
||||
SetClipboardText(TextFormat("#%02X%02X%02X", color.r, color.g, color.b));
|
||||
}
|
||||
}
|
||||
|
||||
// Scale up the color wheel, adjusting the handle visually
|
||||
if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
pointScale *= 1.025f;
|
||||
|
||||
if (pointScale > (float)screenHeight/2.0f)
|
||||
{
|
||||
pointScale = (float)screenHeight/2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 1.025f, 1.025f }), center);
|
||||
}
|
||||
}
|
||||
|
||||
// Scale down the wheel, adjusting the handle visually
|
||||
if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
pointScale *= 0.975f;
|
||||
|
||||
if (pointScale < 32.0f)
|
||||
{
|
||||
pointScale = 32.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
circlePosition = Vector2Add(Vector2Multiply(Vector2Subtract(circlePosition, center), (Vector2){ 0.975f, 0.975f }), center);
|
||||
}
|
||||
|
||||
float distance = Vector2Distance(center, circlePosition)/pointScale;
|
||||
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
|
||||
|
||||
if (distance > 1.0f)
|
||||
{
|
||||
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI*2.0f))*pointScale }, center);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if the user clicked on the color wheel
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && Vector2Distance(GetMousePosition(), center) <= pointScale + 10.0f)
|
||||
{
|
||||
settingColor = true;
|
||||
}
|
||||
|
||||
// Update flag when mouse button is released
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) settingColor = false;
|
||||
|
||||
// Check if the user clicked/released the slider for the color's value
|
||||
if (sliderHover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) sliderClicked = true;
|
||||
|
||||
if (sliderClicked && IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) sliderClicked = false;
|
||||
|
||||
// Update render mode accordingly
|
||||
if (IsKeyPressed(KEY_SPACE)) renderType = RL_LINES;
|
||||
|
||||
if (IsKeyReleased(KEY_SPACE)) renderType = RL_TRIANGLES;
|
||||
|
||||
// If the slider or the wheel was clicked, update the current color
|
||||
if (settingColor || sliderClicked)
|
||||
{
|
||||
if (settingColor) circlePosition = GetMousePosition();
|
||||
|
||||
float distance = Vector2Distance(center, circlePosition)/pointScale;
|
||||
|
||||
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
|
||||
if (settingColor && distance > 1.0f) circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI* 2.0f))*pointScale }, center);
|
||||
|
||||
float angle360 = angle*360.0f;
|
||||
float valueActual = Clamp(distance, 0.0f, 1.0f);
|
||||
color = ColorLerp((Color){ (int)(value*255.0f), (int)(value*255.0f), (int)(value*255.0f), 255 }, ColorFromHSV(angle360, Clamp(distance, 0.0f, 1.0f), 1.0f), valueActual);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Begin rendering color wheel
|
||||
rlBegin(renderType);
|
||||
for (unsigned int i = 0; i < triangleCount; i++)
|
||||
{
|
||||
float angleOffset = ((PI*2.0f)/(float)triangleCount);
|
||||
float angle = angleOffset*(float)i;
|
||||
float angleOffsetCalculated = ((float)i + 1)*angleOffset;
|
||||
Vector2 scale = (Vector2){ pointScale, pointScale };
|
||||
|
||||
Vector2 offset = Vector2Multiply((Vector2){ sinf(angle), -cosf(angle) }, scale);
|
||||
Vector2 offset2 = Vector2Multiply((Vector2){ sinf(angleOffsetCalculated), -cosf(angleOffsetCalculated) }, scale);
|
||||
|
||||
Vector2 position = Vector2Add(center, offset);
|
||||
Vector2 position2 = Vector2Add(center, offset2);
|
||||
|
||||
float angleNonRadian = (angle/(2.0f*PI))*360.0f;
|
||||
float angleNonRadianOffset = (angleOffset/(2.0f*PI))*360.0f;
|
||||
|
||||
Color currentColor = ColorFromHSV(angleNonRadian, 1.0f, 1.0f);
|
||||
Color offsetColor = ColorFromHSV(angleNonRadian + angleNonRadianOffset, 1.0f, 1.0f);
|
||||
|
||||
// Input vertices differently depending on mode
|
||||
if (renderType == RL_TRIANGLES)
|
||||
{
|
||||
// RL_TRIANGLES expects three vertices per triangle
|
||||
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
|
||||
rlVertex2f(position.x, position.y);
|
||||
rlColor4f(value, value, value, 1.0f);
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
|
||||
rlVertex2f(position2.x, position2.y);
|
||||
}
|
||||
else if (renderType == RL_LINES)
|
||||
{
|
||||
// RL_LINES expects two vertices per line
|
||||
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
|
||||
rlVertex2f(position.x, position.y);
|
||||
rlColor4ub(WHITE.r, WHITE.g, WHITE.b, WHITE.a);
|
||||
rlVertex2f(center.x, center.y);
|
||||
|
||||
rlVertex2f(center.x, center.y);
|
||||
rlColor4ub(offsetColor.r, offsetColor.g, offsetColor.b, offsetColor.a);
|
||||
rlVertex2f(position2.x, position2.y);
|
||||
|
||||
rlVertex2f(position2.x, position2.y);
|
||||
rlColor4ub(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
|
||||
rlVertex2f(position.x, position.y);
|
||||
}
|
||||
}
|
||||
rlEnd();
|
||||
|
||||
// Make the handle slightly more visible overtop darker colors
|
||||
Color handleColor = BLACK;
|
||||
|
||||
if (Vector2Distance(center, circlePosition)/pointScale <= 0.5f && value <= 0.5f)
|
||||
{
|
||||
handleColor = DARKGRAY;
|
||||
}
|
||||
|
||||
// Draw the color handle
|
||||
DrawCircleLinesV(circlePosition, 4.0f, handleColor);
|
||||
|
||||
// Draw the color in a preview, with a darkened outline.
|
||||
DrawRectangleV((Vector2){ 8.0f, 8.0f }, (Vector2){ 64.0f, 64.0f }, color);
|
||||
DrawRectangleLinesEx((Rectangle){ 8.0f, 8.0f, 64.0f, 64.0f }, 2.0f, ColorLerp(color, BLACK, 0.5f));
|
||||
|
||||
// Draw current color as hex and decimal
|
||||
DrawText(TextFormat("#%02X%02X%02X\n(%d, %d, %d)", color.r, color.g, color.b, color.r, color.g, color.b), 8, 8 + 64 + 8, 20, DARKGRAY);
|
||||
|
||||
// Update the visuals for the copying text
|
||||
Color copyColor = DARKGRAY;
|
||||
unsigned int offset = 0;
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyDown(KEY_C))
|
||||
{
|
||||
copyColor = DARKGREEN;
|
||||
offset = 4;
|
||||
}
|
||||
|
||||
// Draw the copying text
|
||||
DrawText("press ctrl+c to copy!", 8, 425 - offset, 20, copyColor);
|
||||
|
||||
// Display the number of rendered triangles
|
||||
DrawText(TextFormat("triangle count: %d", triangleCount), 8, 395, 20, DARKGRAY);
|
||||
|
||||
// Slider to change color's value
|
||||
GuiSliderBar(sliderRectangle, "value: ", "", &value, 0.0f, 1.0f);
|
||||
|
||||
// Draw FPS next to outlined color preview
|
||||
DrawFPS(64 + 16, 8);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 67 KiB |
@ -0,0 +1,169 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - rlgl triangle
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Robin (@RobinsAviary) 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 Robin (@RobinsAviary)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "rlgl.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl triangle");
|
||||
|
||||
// Starting postions and rendered triangle positions
|
||||
Vector2 startingPositions[3] = {{ 400.0f, 150.0f }, { 300.0f, 300.0f }, { 500.0f, 300.0f }};
|
||||
Vector2 trianglePositions[3] = { startingPositions[0], startingPositions[1], startingPositions[2] };
|
||||
|
||||
// Currently selected vertex, -1 means none
|
||||
int triangleIndex = -1;
|
||||
bool linesMode = false;
|
||||
float handleRadius = 8.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE)) linesMode = !linesMode;
|
||||
|
||||
// Check selected vertex
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
// If the mouse is within the handle circle
|
||||
if (CheckCollisionPointCircle(GetMousePosition(), trianglePositions[i], handleRadius) &&
|
||||
IsMouseButtonDown(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
triangleIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user has selected a vertex, offset it by the mouse's delta this frame
|
||||
if (triangleIndex != -1)
|
||||
{
|
||||
Vector2 *position = &trianglePositions[triangleIndex];
|
||||
|
||||
Vector2 mouseDelta = GetMouseDelta();
|
||||
position->x += mouseDelta.x;
|
||||
position->y += mouseDelta.y;
|
||||
}
|
||||
|
||||
// Reset index on release
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) triangleIndex = -1;
|
||||
|
||||
// Enable/disable backface culling (2-sided triangles, slower to render)
|
||||
if (IsKeyPressed(KEY_LEFT)) rlEnableBackfaceCulling();
|
||||
if (IsKeyPressed(KEY_RIGHT)) rlDisableBackfaceCulling();
|
||||
|
||||
// Reset triangle vertices to starting positions and reset backface culling
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
trianglePositions[0] = startingPositions[0];
|
||||
trianglePositions[1] = startingPositions[1];
|
||||
trianglePositions[2] = startingPositions[2];
|
||||
|
||||
rlEnableBackfaceCulling();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (linesMode)
|
||||
{
|
||||
// Draw triangle with lines
|
||||
rlBegin(RL_LINES);
|
||||
// Three lines, six points
|
||||
// Define color for next vertex
|
||||
rlColor4ub(255, 0, 0, 255);
|
||||
// Define vertex
|
||||
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
|
||||
rlColor4ub(0, 255, 0, 255);
|
||||
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
|
||||
|
||||
rlColor4ub(0, 255, 0, 255);
|
||||
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
|
||||
rlColor4ub(0, 0, 255, 255);
|
||||
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
|
||||
|
||||
rlColor4ub(0, 0, 255, 255);
|
||||
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
|
||||
rlColor4ub(255, 0, 0, 255);
|
||||
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
|
||||
rlEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw triangle as a triangle
|
||||
rlBegin(RL_TRIANGLES);
|
||||
// One triangle, three points
|
||||
// Define color for next vertex
|
||||
rlColor4ub(255, 0, 0, 255);
|
||||
// Define vertex
|
||||
rlVertex2f(trianglePositions[0].x, trianglePositions[0].y);
|
||||
rlColor4ub(0, 255, 0, 255);
|
||||
rlVertex2f(trianglePositions[1].x, trianglePositions[1].y);
|
||||
rlColor4ub(0, 0, 255, 255);
|
||||
rlVertex2f(trianglePositions[2].x, trianglePositions[2].y);
|
||||
rlEnd();
|
||||
}
|
||||
|
||||
// Render the vertex handles, reacting to mouse movement/input
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
// Draw handle fill focused by mouse
|
||||
if (CheckCollisionPointCircle(GetMousePosition(), trianglePositions[i], handleRadius))
|
||||
DrawCircleV(trianglePositions[i], handleRadius, ColorAlpha(DARKGRAY, 0.5f));
|
||||
|
||||
// Draw handle fill selected
|
||||
if (i == triangleIndex) DrawCircleV(trianglePositions[i], handleRadius, DARKGRAY);
|
||||
|
||||
// Draw handle outline
|
||||
DrawCircleLinesV(trianglePositions[i], handleRadius, BLACK);
|
||||
}
|
||||
|
||||
// Draw controls
|
||||
DrawText("SPACE: Toggle lines mode", 10, 10, 20, DARKGRAY);
|
||||
DrawText("LEFT-RIGHT: Toggle backface culling", 10, 40, 20, DARKGRAY);
|
||||
DrawText("MOUSE: Click and drag vertex points", 10, 70, 20, DARKGRAY);
|
||||
DrawText("R: Reset triangle to start positions", 10, 100, 20, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,96 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - rounded rectangle drawing
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) 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) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rounded rectangle drawing");
|
||||
|
||||
float roundness = 0.2f;
|
||||
float width = 200.0f;
|
||||
float height = 100.0f;
|
||||
float segments = 0.0f;
|
||||
float lineThick = 1.0f;
|
||||
|
||||
bool drawRect = false;
|
||||
bool drawRoundedRect = true;
|
||||
bool drawRoundedLines = 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
|
||||
//----------------------------------------------------------------------------------
|
||||
Rectangle rec = { ((float)GetScreenWidth() - width - 250)/2, (GetScreenHeight() - height)/2.0f, (float)width, (float)height };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawLine(560, 0, 560, GetScreenHeight(), Fade(LIGHTGRAY, 0.6f));
|
||||
DrawRectangle(560, 0, GetScreenWidth() - 500, GetScreenHeight(), Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
if (drawRect) DrawRectangleRec(rec, Fade(GOLD, 0.6f));
|
||||
if (drawRoundedRect) DrawRectangleRounded(rec, roundness, (int)segments, Fade(MAROON, 0.2f));
|
||||
if (drawRoundedLines) DrawRectangleRoundedLinesEx(rec, roundness, (int)segments, lineThick, Fade(MAROON, 0.4f));
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
GuiSliderBar((Rectangle){ 640, 40, 105, 20 }, "Width", TextFormat("%.2f", width), &width, 0, (float)GetScreenWidth() - 300);
|
||||
GuiSliderBar((Rectangle){ 640, 70, 105, 20 }, "Height", TextFormat("%.2f", height), &height, 0, (float)GetScreenHeight() - 50);
|
||||
GuiSliderBar((Rectangle){ 640, 140, 105, 20 }, "Roundness", TextFormat("%.2f", roundness), &roundness, 0.0f, 1.0f);
|
||||
GuiSliderBar((Rectangle){ 640, 170, 105, 20 }, "Thickness", TextFormat("%.2f", lineThick), &lineThick, 0, 20);
|
||||
GuiSliderBar((Rectangle){ 640, 240, 105, 20}, "Segments", TextFormat("%.2f", segments), &segments, 0, 60);
|
||||
|
||||
GuiCheckBox((Rectangle){ 640, 320, 20, 20 }, "DrawRoundedRect", &drawRoundedRect);
|
||||
GuiCheckBox((Rectangle){ 640, 350, 20, 20 }, "DrawRoundedLines", &drawRoundedLines);
|
||||
GuiCheckBox((Rectangle){ 640, 380, 20, 20}, "DrawRect", &drawRect);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DrawText(TextFormat("MODE: %s", (segments >= 4)? "MANUAL" : "AUTO"), 640, 280, 10, (segments >= 4)? MAROON : DARKGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,284 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - simple particles
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.6, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Jordi Santonja (@JordSant)
|
||||
*
|
||||
* 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 Jordi Santonja (@JordSant)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
#include <math.h> // Required for: cosf(), sinf()
|
||||
|
||||
#define MAX_PARTICLES 3000 // Max number of particles
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef enum ParticleType {
|
||||
WATER = 0,
|
||||
SMOKE,
|
||||
FIRE
|
||||
} ParticleType;
|
||||
|
||||
static const char particleTypeNames[3][10] = { "WATER", "SMOKE", "FIRE" };
|
||||
|
||||
typedef struct Particle {
|
||||
ParticleType type; // Particle type (WATER, SMOKE, FIRE)
|
||||
Vector2 position; // Particle position on screen
|
||||
Vector2 velocity; // Particle current speed and direction
|
||||
float radius; // Particle radius
|
||||
Color color; // Particle color
|
||||
|
||||
float lifeTime; // Particle life time
|
||||
bool alive; // Particle alive: inside screen and life time
|
||||
} Particle;
|
||||
|
||||
typedef struct CircularBuffer {
|
||||
int head; // Index for the next write
|
||||
int tail; // Index for the next read
|
||||
Particle *buffer; // Particle buffer array
|
||||
} CircularBuffer;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition, ParticleType type);
|
||||
static Particle *AddToCircularBuffer(CircularBuffer *circularBuffer);
|
||||
static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight);
|
||||
static void UpdateCircularBuffer(CircularBuffer *circularBuffer);
|
||||
static void DrawParticles(CircularBuffer *circularBuffer);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - simple particles");
|
||||
|
||||
// Definition of particles
|
||||
Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array
|
||||
CircularBuffer circularBuffer = { 0, 0, particles };
|
||||
|
||||
// Particle emitter parameters
|
||||
int emissionRate = -2; // Negative: on average every -X frames. Positive: particles per frame
|
||||
ParticleType currentType = WATER;
|
||||
Vector2 emitterPosition = { screenWidth/2.0f, screenHeight/2.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
|
||||
//----------------------------------------------------------------------------------
|
||||
// Emit new particles: when emissionRate is 1, emit every frame
|
||||
if (emissionRate < 0)
|
||||
{
|
||||
if (rand()%(-emissionRate) == 0) EmitParticle(&circularBuffer, emitterPosition, currentType);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i <= emissionRate; i++) EmitParticle(&circularBuffer, emitterPosition, currentType);
|
||||
}
|
||||
|
||||
// Update the parameters of each particle
|
||||
UpdateParticles(&circularBuffer, screenWidth, screenHeight);
|
||||
|
||||
// Remove dead particles from the circular buffer
|
||||
UpdateCircularBuffer(&circularBuffer);
|
||||
|
||||
// Change Particle Emission Rate (UP/DOWN arrows)
|
||||
if (IsKeyPressed(KEY_UP)) emissionRate++;
|
||||
if (IsKeyPressed(KEY_DOWN)) emissionRate--;
|
||||
|
||||
// Change Particle Type (LEFT/RIGHT arrows)
|
||||
if (IsKeyPressed(KEY_RIGHT)) (currentType == FIRE)? (currentType = WATER) : currentType++;
|
||||
if (IsKeyPressed(KEY_LEFT)) (currentType == WATER)? (currentType = FIRE) : currentType--;
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) emitterPosition = GetMousePosition();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Call the function with a loop to draw all particles
|
||||
DrawParticles(&circularBuffer);
|
||||
|
||||
// Draw UI and Instructions
|
||||
DrawRectangle(5, 5, 315, 75, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(5, 5, 315, 75, BLUE);
|
||||
|
||||
DrawText("CONTROLS:", 15, 15, 10, BLACK);
|
||||
DrawText("UP/DOWN: Change Particle Emission Rate", 15, 35, 10, BLACK);
|
||||
DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK);
|
||||
|
||||
if (emissionRate < 0) DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY);
|
||||
else DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY);
|
||||
|
||||
DrawFPS(screenWidth - 80, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
RL_FREE(particles); // Free particles array data
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition, ParticleType type)
|
||||
{
|
||||
Particle *newParticle = AddToCircularBuffer(circularBuffer);
|
||||
|
||||
// If buffer is full, newParticle is NULL
|
||||
if (newParticle != NULL)
|
||||
{
|
||||
// Fill particle properties
|
||||
newParticle->position = emitterPosition;
|
||||
newParticle->alive = true;
|
||||
newParticle->lifeTime = 0.0f;
|
||||
newParticle->type = type;
|
||||
float speed = (float)(rand()%10)/5.0f;
|
||||
switch (type)
|
||||
{
|
||||
case WATER:
|
||||
{
|
||||
newParticle->radius = 5.0f;
|
||||
newParticle->color = BLUE;
|
||||
} break;
|
||||
case SMOKE:
|
||||
{
|
||||
newParticle->radius = 7.0f;
|
||||
newParticle->color = GRAY;
|
||||
} break;
|
||||
case FIRE:
|
||||
{
|
||||
newParticle->radius = 10.0f;
|
||||
newParticle->color = YELLOW;
|
||||
speed /= 10.0f;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
float direction = (float)(rand()%360);
|
||||
newParticle->velocity = (Vector2){ speed*cosf(direction*DEG2RAD), speed*sinf(direction*DEG2RAD) };
|
||||
}
|
||||
}
|
||||
|
||||
static Particle *AddToCircularBuffer(CircularBuffer *circularBuffer)
|
||||
{
|
||||
Particle *particle = NULL;
|
||||
|
||||
// Check if buffer full
|
||||
if (((circularBuffer->head + 1)%MAX_PARTICLES) != circularBuffer->tail)
|
||||
{
|
||||
// Add new particle to the head position and advance head
|
||||
particle = &circularBuffer->buffer[circularBuffer->head];
|
||||
circularBuffer->head = (circularBuffer->head + 1)%MAX_PARTICLES;
|
||||
}
|
||||
|
||||
return particle;
|
||||
}
|
||||
|
||||
static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight)
|
||||
{
|
||||
for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES)
|
||||
{
|
||||
// Update particle life and positions
|
||||
circularBuffer->buffer[i].lifeTime += 1.0f/60.0f; // 60 FPS -> 1/60 seconds per frame
|
||||
|
||||
switch (circularBuffer->buffer[i].type)
|
||||
{
|
||||
case WATER:
|
||||
{
|
||||
circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x;
|
||||
circularBuffer->buffer[i].velocity.y += 0.2f; // Gravity
|
||||
circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y;
|
||||
} break;
|
||||
case SMOKE:
|
||||
{
|
||||
circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x;
|
||||
circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards
|
||||
circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y;
|
||||
circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands
|
||||
circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades
|
||||
|
||||
// If alpha transparent, particle dies
|
||||
if (circularBuffer->buffer[i].color.a < 4) circularBuffer->buffer[i].alive = false;
|
||||
} break;
|
||||
case FIRE:
|
||||
{
|
||||
// Add a little horizontal oscillation to fire particles
|
||||
circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f);
|
||||
circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards
|
||||
circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y;
|
||||
circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks
|
||||
circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow
|
||||
|
||||
// If radius too small, particle dies
|
||||
if (circularBuffer->buffer[i].radius <= 0.02f) circularBuffer->buffer[i].alive = false;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Disable particle when out of screen
|
||||
Vector2 center = circularBuffer->buffer[i].position;
|
||||
float radius = circularBuffer->buffer[i].radius;
|
||||
|
||||
if ((center.x < -radius) || (center.x > (screenWidth + radius)) ||
|
||||
(center.y < -radius) || (center.y > (screenHeight + radius)))
|
||||
{
|
||||
circularBuffer->buffer[i].alive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateCircularBuffer(CircularBuffer *circularBuffer)
|
||||
{
|
||||
// Update circular buffer: advance tail over dead particles
|
||||
while ((circularBuffer->tail != circularBuffer->head) && !circularBuffer->buffer[circularBuffer->tail].alive)
|
||||
{
|
||||
circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawParticles(CircularBuffer *circularBuffer)
|
||||
{
|
||||
for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES)
|
||||
{
|
||||
if (circularBuffer->buffer[i].alive)
|
||||
{
|
||||
DrawCircleV(circularBuffer->buffer[i].position,
|
||||
circularBuffer->buffer[i].radius,
|
||||
circularBuffer->buffer[i].color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,288 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - splines drawing
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* 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) 2023-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for UI controls
|
||||
|
||||
#include <stdlib.h> // Required for: NULL
|
||||
|
||||
#define MAX_SPLINE_POINTS 32
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Cubic Bezier spline control points
|
||||
// NOTE: Every segment has two control points
|
||||
typedef struct {
|
||||
Vector2 start;
|
||||
Vector2 end;
|
||||
} ControlPoint;
|
||||
|
||||
// Spline types
|
||||
typedef enum {
|
||||
SPLINE_LINEAR = 0, // Linear
|
||||
SPLINE_BASIS, // B-Spline
|
||||
SPLINE_CATMULLROM, // Catmull-Rom
|
||||
SPLINE_BEZIER // Cubic Bezier
|
||||
} SplineType;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - splines drawing");
|
||||
|
||||
Vector2 points[MAX_SPLINE_POINTS] = {
|
||||
{ 50.0f, 400.0f },
|
||||
{ 160.0f, 220.0f },
|
||||
{ 340.0f, 380.0f },
|
||||
{ 520.0f, 60.0f },
|
||||
{ 710.0f, 260.0f },
|
||||
};
|
||||
|
||||
// Array required for spline bezier-cubic,
|
||||
// including control points interleaved with start-end segment points
|
||||
Vector2 pointsInterleaved[3*(MAX_SPLINE_POINTS - 1) + 1] = { 0 };
|
||||
|
||||
int pointCount = 5;
|
||||
int selectedPoint = -1;
|
||||
int focusedPoint = -1;
|
||||
Vector2 *selectedControlPoint = NULL;
|
||||
Vector2 *focusedControlPoint = NULL;
|
||||
|
||||
// Cubic Bezier control points initialization
|
||||
ControlPoint control[MAX_SPLINE_POINTS-1] = { 0 };
|
||||
for (int i = 0; i < pointCount - 1; i++)
|
||||
{
|
||||
control[i].start = (Vector2){ points[i].x + 50, points[i].y };
|
||||
control[i].end = (Vector2){ points[i + 1].x - 50, points[i + 1].y };
|
||||
}
|
||||
|
||||
// Spline config variables
|
||||
float splineThickness = 8.0f;
|
||||
int splineTypeActive = SPLINE_LINEAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier
|
||||
bool splineTypeEditMode = false;
|
||||
bool splineHelpersActive = true;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
// Spline points creation logic (at the end of spline)
|
||||
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && (pointCount < MAX_SPLINE_POINTS))
|
||||
{
|
||||
points[pointCount] = GetMousePosition();
|
||||
int i = pointCount - 1;
|
||||
control[i].start = (Vector2){ points[i].x + 50, points[i].y };
|
||||
control[i].end = (Vector2){ points[i + 1].x - 50, points[i + 1].y };
|
||||
pointCount++;
|
||||
}
|
||||
|
||||
// Spline point focus and selection logic
|
||||
if ((selectedPoint == -1) && ((splineTypeActive != SPLINE_BEZIER) || (selectedControlPoint == NULL)))
|
||||
{
|
||||
focusedPoint = -1;
|
||||
for (int i = 0; i < pointCount; i++)
|
||||
{
|
||||
if (CheckCollisionPointCircle(GetMousePosition(), points[i], 8.0f))
|
||||
{
|
||||
focusedPoint = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) selectedPoint = focusedPoint;
|
||||
}
|
||||
|
||||
// Spline point movement logic
|
||||
if (selectedPoint >= 0)
|
||||
{
|
||||
points[selectedPoint] = GetMousePosition();
|
||||
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedPoint = -1;
|
||||
}
|
||||
|
||||
// Cubic Bezier spline control points logic
|
||||
if ((splineTypeActive == SPLINE_BEZIER) && (focusedPoint == -1))
|
||||
{
|
||||
// Spline control point focus and selection logic
|
||||
if (selectedControlPoint == NULL)
|
||||
{
|
||||
focusedControlPoint = NULL;
|
||||
for (int i = 0; i < pointCount - 1; i++)
|
||||
{
|
||||
if (CheckCollisionPointCircle(GetMousePosition(), control[i].start, 6.0f))
|
||||
{
|
||||
focusedControlPoint = &control[i].start;
|
||||
break;
|
||||
}
|
||||
else if (CheckCollisionPointCircle(GetMousePosition(), control[i].end, 6.0f))
|
||||
{
|
||||
focusedControlPoint = &control[i].end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) selectedControlPoint = focusedControlPoint;
|
||||
}
|
||||
|
||||
// Spline control point movement logic
|
||||
if (selectedControlPoint != NULL)
|
||||
{
|
||||
*selectedControlPoint = GetMousePosition();
|
||||
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedControlPoint = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Spline selection logic
|
||||
if (IsKeyPressed(KEY_ONE)) splineTypeActive = 0;
|
||||
else if (IsKeyPressed(KEY_TWO)) splineTypeActive = 1;
|
||||
else if (IsKeyPressed(KEY_THREE)) splineTypeActive = 2;
|
||||
else if (IsKeyPressed(KEY_FOUR)) splineTypeActive = 3;
|
||||
|
||||
// Clear selection when changing to a spline without control points
|
||||
if (IsKeyPressed(KEY_ONE) || IsKeyPressed(KEY_TWO) || IsKeyPressed(KEY_THREE)) selectedControlPoint = NULL;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (splineTypeActive == SPLINE_LINEAR)
|
||||
{
|
||||
// Draw spline: linear
|
||||
DrawSplineLinear(points, pointCount, splineThickness, RED);
|
||||
}
|
||||
else if (splineTypeActive == SPLINE_BASIS)
|
||||
{
|
||||
// Draw spline: basis
|
||||
DrawSplineBasis(points, pointCount, splineThickness, RED); // Provide connected points array
|
||||
|
||||
/*
|
||||
for (int i = 0; i < (pointCount - 3); i++)
|
||||
{
|
||||
// Drawing individual segments, not considering thickness connection compensation
|
||||
DrawSplineSegmentBasis(points[i], points[i + 1], points[i + 2], points[i + 3], splineThickness, MAROON);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (splineTypeActive == SPLINE_CATMULLROM)
|
||||
{
|
||||
// Draw spline: catmull-rom
|
||||
DrawSplineCatmullRom(points, pointCount, splineThickness, RED); // Provide connected points array
|
||||
|
||||
/*
|
||||
for (int i = 0; i < (pointCount - 3); i++)
|
||||
{
|
||||
// Drawing individual segments, not considering thickness connection compensation
|
||||
DrawSplineSegmentCatmullRom(points[i], points[i + 1], points[i + 2], points[i + 3], splineThickness, MAROON);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (splineTypeActive == SPLINE_BEZIER)
|
||||
{
|
||||
// NOTE: Cubic-bezier spline requires the 2 control points of each segnment to be
|
||||
// provided interleaved with the start and end point of every segment
|
||||
for (int i = 0; i < (pointCount - 1); i++)
|
||||
{
|
||||
pointsInterleaved[3*i] = points[i];
|
||||
pointsInterleaved[3*i + 1] = control[i].start;
|
||||
pointsInterleaved[3*i + 2] = control[i].end;
|
||||
}
|
||||
|
||||
pointsInterleaved[3*(pointCount - 1)] = points[pointCount - 1];
|
||||
|
||||
// Draw spline: cubic-bezier (with control points)
|
||||
DrawSplineBezierCubic(pointsInterleaved, 3*(pointCount - 1) + 1, splineThickness, RED);
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 3*(pointCount - 1); i += 3)
|
||||
{
|
||||
// Drawing individual segments, not considering thickness connection compensation
|
||||
DrawSplineSegmentBezierCubic(pointsInterleaved[i], pointsInterleaved[i + 1], pointsInterleaved[i + 2], pointsInterleaved[i + 3], splineThickness, MAROON);
|
||||
}
|
||||
*/
|
||||
|
||||
// Draw spline control points
|
||||
for (int i = 0; i < pointCount - 1; i++)
|
||||
{
|
||||
// Every cubic bezier point have two control points
|
||||
DrawCircleV(control[i].start, 6, GOLD);
|
||||
DrawCircleV(control[i].end, 6, GOLD);
|
||||
if (focusedControlPoint == &control[i].start) DrawCircleV(control[i].start, 8, GREEN);
|
||||
else if (focusedControlPoint == &control[i].end) DrawCircleV(control[i].end, 8, GREEN);
|
||||
DrawLineEx(points[i], control[i].start, 1.0f, LIGHTGRAY);
|
||||
DrawLineEx(points[i + 1], control[i].end, 1.0f, LIGHTGRAY);
|
||||
|
||||
// Draw spline control lines
|
||||
DrawLineV(points[i], control[i].start, GRAY);
|
||||
//DrawLineV(control[i].start, control[i].end, LIGHTGRAY);
|
||||
DrawLineV(control[i].end, points[i + 1], GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
if (splineHelpersActive)
|
||||
{
|
||||
// Draw spline point helpers
|
||||
for (int i = 0; i < pointCount; i++)
|
||||
{
|
||||
DrawCircleLinesV(points[i], (focusedPoint == i)? 12.0f : 8.0f, (focusedPoint == i)? BLUE: DARKBLUE);
|
||||
if ((splineTypeActive != SPLINE_LINEAR) &&
|
||||
(splineTypeActive != SPLINE_BEZIER) &&
|
||||
(i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY);
|
||||
|
||||
DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), (int)points[i].x, (int)points[i].y + 10, 10, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
// Check all possible UI states that require controls lock
|
||||
if (splineTypeEditMode || (selectedPoint != -1) || (selectedControlPoint != NULL)) GuiLock();
|
||||
|
||||
// Draw spline config
|
||||
GuiLabel((Rectangle){ 12, 62, 140, 24 }, TextFormat("Spline thickness: %i", (int)splineThickness));
|
||||
GuiSliderBar((Rectangle){ 12, 60 + 24, 140, 16 }, NULL, NULL, &splineThickness, 1.0f, 40.0f);
|
||||
|
||||
GuiCheckBox((Rectangle){ 12, 110, 20, 20 }, "Show point helpers", &splineHelpersActive);
|
||||
|
||||
if (splineTypeEditMode) GuiUnlock();
|
||||
|
||||
GuiLabel((Rectangle){ 12, 10, 140, 24 }, "Spline type:");
|
||||
if (GuiDropdownBox((Rectangle){ 12, 8 + 24, 140, 28 }, "LINEAR;BSPLINE;CATMULLROM;BEZIER", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode;
|
||||
|
||||
GuiUnlock();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,146 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - starfield effect
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
*
|
||||
* 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 effect");
|
||||
|
||||
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 = (float)GetRandomValue(-screenWidth / 2, (int)screenWidth / 2);
|
||||
stars[i].y = (float)GetRandomValue(-screenHeight / 2, (int)screenHeight / 2);
|
||||
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 mouse
|
||||
float mouseMove = GetMouseWheelMove();
|
||||
if ((int)mouseMove != 0) speed += 2.0f*mouseMove/9.0f;
|
||||
if (speed < 0.0f) speed = 0.1f;
|
||||
else if (speed > 2.0f) speed = 2.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*0.5f + stars[i].x/stars[i].z,
|
||||
screenHeight*0.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 = (float)GetRandomValue(-screenWidth / 2, screenWidth / 2);
|
||||
stars[i].y = (float)GetRandomValue(-screenHeight / 2, screenHeight / 2);
|
||||
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*0.5f + stars[i].x/t,
|
||||
screenHeight*0.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);
|
||||
}
|
||||
}
|
||||
|
||||
DrawText(TextFormat("[MOUSE WHEEL] Current Speed: %.0f", 9.0f*speed/2.0f), 10, 40, 20, RAYWHITE);
|
||||
DrawText(TextFormat("[SPACE] Current draw mode: %s", drawLines ? "Lines" : "Circles"), 10, 70, 20, RAYWHITE);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,382 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - top down lights
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) 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) 2022-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
#include "rlgl.h"
|
||||
|
||||
// Custom Blend Modes
|
||||
#define RLGL_SRC_ALPHA 0x0302
|
||||
#define RLGL_MIN 0x8007
|
||||
#define RLGL_MAX 0x8008
|
||||
|
||||
#define MAX_BOXES 20
|
||||
#define MAX_SHADOWS MAX_BOXES*3 // MAX_BOXES*3 - Each box can cast up to two shadow volumes for the edges it is away from, and one for the box itself
|
||||
#define MAX_LIGHTS 16
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Shadow geometry type
|
||||
typedef struct ShadowGeometry {
|
||||
Vector2 vertices[4];
|
||||
} ShadowGeometry;
|
||||
|
||||
// Light info type
|
||||
typedef struct LightInfo {
|
||||
bool active; // Is this light slot active?
|
||||
bool dirty; // Does this light need to be updated?
|
||||
bool valid; // Is this light in a valid position?
|
||||
|
||||
Vector2 position; // Light position
|
||||
RenderTexture mask; // Alpha mask for the light
|
||||
float outerRadius; // The distance the light touches
|
||||
Rectangle bounds; // A cached rectangle of the light bounds to help with culling
|
||||
|
||||
ShadowGeometry shadows[MAX_SHADOWS];
|
||||
int shadowCount;
|
||||
} LightInfo;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
static LightInfo lights[MAX_LIGHTS] = { 0 };
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
// Move a light and mark it as dirty so that we update it's mask next frame
|
||||
static void MoveLight(int slot, float x, float y);
|
||||
// Compute a shadow volume for the edge
|
||||
static void ComputeShadowVolumeForEdge(int slot, Vector2 sp, Vector2 ep);
|
||||
// Draw the light and shadows to the mask for a light
|
||||
static void DrawLightMask(int slot);
|
||||
// Setup a light
|
||||
static void SetupLight(int slot, float x, float y, float radius);
|
||||
// See if a light needs to update it's mask
|
||||
static bool UpdateLight(int slot, Rectangle* boxes, int count);
|
||||
// Set up some boxes
|
||||
static void SetupBoxes(Rectangle *boxes, int *count);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - top down lights");
|
||||
|
||||
// Initialize our 'world' of boxes
|
||||
int boxCount = 0;
|
||||
Rectangle boxes[MAX_BOXES] = { 0 };
|
||||
SetupBoxes(boxes, &boxCount);
|
||||
|
||||
// Create a checkerboard ground texture
|
||||
Image img = GenImageChecked(64, 64, 32, 32, DARKBROWN, DARKGRAY);
|
||||
Texture2D backgroundTexture = LoadTextureFromImage(img);
|
||||
UnloadImage(img);
|
||||
|
||||
// Create a global light mask to hold all the blended lights
|
||||
RenderTexture lightMask = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
|
||||
// Setup initial light
|
||||
SetupLight(0, 600, 400, 300);
|
||||
int nextLight = 1;
|
||||
|
||||
bool showLines = 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
|
||||
//----------------------------------------------------------------------------------
|
||||
// Drag light 0
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) MoveLight(0, GetMousePosition().x, GetMousePosition().y);
|
||||
|
||||
// Make a new light
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) && (nextLight < MAX_LIGHTS))
|
||||
{
|
||||
SetupLight(nextLight, GetMousePosition().x, GetMousePosition().y, 200);
|
||||
nextLight++;
|
||||
}
|
||||
|
||||
// Toggle debug info
|
||||
if (IsKeyPressed(KEY_F1)) showLines = !showLines;
|
||||
|
||||
// Update the lights and keep track if any were dirty so we know if we need to update the master light mask
|
||||
bool dirtyLights = false;
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
if (UpdateLight(i, boxes, boxCount)) dirtyLights = true;
|
||||
}
|
||||
|
||||
// Update the light mask
|
||||
if (dirtyLights)
|
||||
{
|
||||
// Build up the light mask
|
||||
BeginTextureMode(lightMask);
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
// Force the blend mode to only set the alpha of the destination
|
||||
rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MIN);
|
||||
rlSetBlendMode(BLEND_CUSTOM);
|
||||
|
||||
// Merge in all the light masks
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
if (lights[i].active) DrawTextureRec(lights[i].mask.texture, (Rectangle){ 0, 0, (float)GetScreenWidth(), -(float)GetScreenHeight() }, Vector2Zero(), WHITE);
|
||||
}
|
||||
|
||||
rlDrawRenderBatchActive();
|
||||
|
||||
// Go back to normal blend
|
||||
rlSetBlendMode(BLEND_ALPHA);
|
||||
EndTextureMode();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
// Draw the tile background
|
||||
DrawTextureRec(backgroundTexture, (Rectangle){ 0, 0, (float)GetScreenWidth(), (float)GetScreenHeight() }, Vector2Zero(), WHITE);
|
||||
|
||||
// Overlay the shadows from all the lights
|
||||
DrawTextureRec(lightMask.texture, (Rectangle){ 0, 0, (float)GetScreenWidth(), -(float)GetScreenHeight() }, Vector2Zero(), ColorAlpha(WHITE, showLines? 0.75f : 1.0f));
|
||||
|
||||
// Draw the lights
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
if (lights[i].active) DrawCircle((int)lights[i].position.x, (int)lights[i].position.y, 10, (i == 0)? YELLOW : WHITE);
|
||||
}
|
||||
|
||||
if (showLines)
|
||||
{
|
||||
for (int s = 0; s < lights[0].shadowCount; s++)
|
||||
{
|
||||
DrawTriangleFan(lights[0].shadows[s].vertices, 4, DARKPURPLE);
|
||||
}
|
||||
|
||||
for (int b = 0; b < boxCount; b++)
|
||||
{
|
||||
if (CheckCollisionRecs(boxes[b],lights[0].bounds)) DrawRectangleRec(boxes[b], PURPLE);
|
||||
|
||||
DrawRectangleLines((int)boxes[b].x, (int)boxes[b].y, (int)boxes[b].width, (int)boxes[b].height, DARKBLUE);
|
||||
}
|
||||
|
||||
DrawText("(F1) Hide Shadow Volumes", 10, 50, 10, GREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("(F1) Show Shadow Volumes", 10, 50, 10, GREEN);
|
||||
}
|
||||
|
||||
DrawFPS(screenWidth - 80, 10);
|
||||
DrawText("Drag to move light #1", 10, 10, 10, DARKGREEN);
|
||||
DrawText("Right click to add new light", 10, 30, 10, DARKGREEN);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(backgroundTexture);
|
||||
UnloadRenderTexture(lightMask);
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
if (lights[i].active) UnloadRenderTexture(lights[i].mask);
|
||||
}
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Move a light and mark it as dirty so that we update it's mask next frame
|
||||
static void MoveLight(int slot, float x, float y)
|
||||
{
|
||||
lights[slot].dirty = true;
|
||||
lights[slot].position.x = x;
|
||||
lights[slot].position.y = y;
|
||||
|
||||
// update the cached bounds
|
||||
lights[slot].bounds.x = x - lights[slot].outerRadius;
|
||||
lights[slot].bounds.y = y - lights[slot].outerRadius;
|
||||
}
|
||||
|
||||
// Compute a shadow volume for the edge
|
||||
// It takes the edge and projects it back by the light radius and turns it into a quad
|
||||
static void ComputeShadowVolumeForEdge(int slot, Vector2 sp, Vector2 ep)
|
||||
{
|
||||
if (lights[slot].shadowCount >= MAX_SHADOWS) return;
|
||||
|
||||
float extension = lights[slot].outerRadius*2;
|
||||
|
||||
Vector2 spVector = Vector2Normalize(Vector2Subtract(sp, lights[slot].position));
|
||||
Vector2 spProjection = Vector2Add(sp, Vector2Scale(spVector, extension));
|
||||
|
||||
Vector2 epVector = Vector2Normalize(Vector2Subtract(ep, lights[slot].position));
|
||||
Vector2 epProjection = Vector2Add(ep, Vector2Scale(epVector, extension));
|
||||
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[0] = sp;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[1] = ep;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[2] = epProjection;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[3] = spProjection;
|
||||
|
||||
lights[slot].shadowCount++;
|
||||
}
|
||||
|
||||
// Setup a light
|
||||
static void SetupLight(int slot, float x, float y, float radius)
|
||||
{
|
||||
lights[slot].active = true;
|
||||
lights[slot].valid = false; // The light must prove it is valid
|
||||
lights[slot].mask = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||
lights[slot].outerRadius = radius;
|
||||
|
||||
lights[slot].bounds.width = radius*2;
|
||||
lights[slot].bounds.height = radius*2;
|
||||
|
||||
MoveLight(slot, x, y);
|
||||
|
||||
// Force the render texture to have something in it
|
||||
DrawLightMask(slot);
|
||||
}
|
||||
|
||||
// See if a light needs to update it's mask
|
||||
static bool UpdateLight(int slot, Rectangle* boxes, int count)
|
||||
{
|
||||
if (!lights[slot].active || !lights[slot].dirty) return false;
|
||||
|
||||
lights[slot].dirty = false;
|
||||
lights[slot].shadowCount = 0;
|
||||
lights[slot].valid = false;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Are we in a box? if so we are not valid
|
||||
if (CheckCollisionPointRec(lights[slot].position, boxes[i])) return false;
|
||||
|
||||
// If this box is outside our bounds, we can skip it
|
||||
if (!CheckCollisionRecs(lights[slot].bounds, boxes[i])) continue;
|
||||
|
||||
// Check the edges that are on the same side we are, and cast shadow volumes out from them
|
||||
|
||||
// Top
|
||||
Vector2 sp = (Vector2){ boxes[i].x, boxes[i].y };
|
||||
Vector2 ep = (Vector2){ boxes[i].x + boxes[i].width, boxes[i].y };
|
||||
|
||||
if (lights[slot].position.y > ep.y) ComputeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Right
|
||||
sp = ep;
|
||||
ep.y += boxes[i].height;
|
||||
if (lights[slot].position.x < ep.x) ComputeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Bottom
|
||||
sp = ep;
|
||||
ep.x -= boxes[i].width;
|
||||
if (lights[slot].position.y < ep.y) ComputeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Left
|
||||
sp = ep;
|
||||
ep.y -= boxes[i].height;
|
||||
if (lights[slot].position.x > ep.x) ComputeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// The box itself
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[0] = (Vector2){ boxes[i].x, boxes[i].y };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[1] = (Vector2){ boxes[i].x, boxes[i].y + boxes[i].height };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[2] = (Vector2){ boxes[i].x + boxes[i].width, boxes[i].y + boxes[i].height };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[3] = (Vector2){ boxes[i].x + boxes[i].width, boxes[i].y };
|
||||
lights[slot].shadowCount++;
|
||||
}
|
||||
|
||||
lights[slot].valid = true;
|
||||
|
||||
DrawLightMask(slot);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Draw the light and shadows to the mask for a light
|
||||
static void DrawLightMask(int slot)
|
||||
{
|
||||
// Use the light mask
|
||||
BeginTextureMode(lights[slot].mask);
|
||||
|
||||
ClearBackground(WHITE);
|
||||
|
||||
// Force the blend mode to only set the alpha of the destination
|
||||
rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MIN);
|
||||
rlSetBlendMode(BLEND_CUSTOM);
|
||||
|
||||
// If we are valid, then draw the light radius to the alpha mask
|
||||
if (lights[slot].valid) DrawCircleGradient(lights[slot].position, lights[slot].outerRadius, ColorAlpha(WHITE, 0), WHITE);
|
||||
|
||||
rlDrawRenderBatchActive();
|
||||
|
||||
// Cut out the shadows from the light radius by forcing the alpha to maximum
|
||||
rlSetBlendMode(BLEND_ALPHA);
|
||||
rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MAX);
|
||||
rlSetBlendMode(BLEND_CUSTOM);
|
||||
|
||||
// Draw the shadows to the alpha mask
|
||||
for (int i = 0; i < lights[slot].shadowCount; i++)
|
||||
{
|
||||
DrawTriangleFan(lights[slot].shadows[i].vertices, 4, WHITE);
|
||||
}
|
||||
|
||||
rlDrawRenderBatchActive();
|
||||
|
||||
// Go back to normal blend mode
|
||||
rlSetBlendMode(BLEND_ALPHA);
|
||||
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
// Set up some boxes
|
||||
static void SetupBoxes(Rectangle *boxes, int *count)
|
||||
{
|
||||
boxes[0] = (Rectangle){ 150,80, 40, 40 };
|
||||
boxes[1] = (Rectangle){ 1200, 700, 40, 40 };
|
||||
boxes[2] = (Rectangle){ 200, 600, 40, 40 };
|
||||
boxes[3] = (Rectangle){ 1000, 50, 40, 40 };
|
||||
boxes[4] = (Rectangle){ 500, 350, 40, 40 };
|
||||
|
||||
for (int i = 5; i < MAX_BOXES; i++)
|
||||
{
|
||||
boxes[i] = (Rectangle){(float)GetRandomValue(0,GetScreenWidth()), (float)GetRandomValue(0,GetScreenHeight()), (float)GetRandomValue(10,100), (float)GetRandomValue(10,100) };
|
||||
}
|
||||
|
||||
*count = MAX_BOXES;
|
||||
}
|
||||
|
After Width: | Height: | Size: 71 KiB |
@ -0,0 +1,111 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - triangle strip
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* 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) 2025 Jopestpe (@jopestpe)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip");
|
||||
|
||||
Vector2 points[122] = { 0 };
|
||||
Vector2 center = { (screenWidth/2.0f) - 125.0f, screenHeight/2.0f };
|
||||
float segments = 6.0f;
|
||||
float insideRadius = 100.0f;
|
||||
float outsideRadius = 150.0f;
|
||||
bool outline = true;
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
int pointCount = (int)(segments);
|
||||
float angleStep = (360.0f/pointCount)*DEG2RAD;
|
||||
|
||||
for (int i = 0, i2 = 0; i < pointCount; i++, i2 += 2)
|
||||
{
|
||||
float angle1 = i*angleStep;
|
||||
points[i2] = (Vector2){ center.x + cosf(angle1)*insideRadius, center.y + sinf(angle1)*insideRadius };
|
||||
float angle2 = angle1 + angleStep/2.0f;
|
||||
points[i2 + 1] = (Vector2){ center.x + cosf(angle2)*outsideRadius, center.y + sinf(angle2)*outsideRadius };
|
||||
}
|
||||
|
||||
points[pointCount*2] = points[0];
|
||||
points[pointCount*2 + 1] = points[1];
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
for (int i = 0; i < pointCount; i++)
|
||||
{
|
||||
Vector2 a = points[i*2];
|
||||
Vector2 b = points[i*2 + 1];
|
||||
Vector2 c = points[i*2 + 2];
|
||||
Vector2 d = points[i*2 + 3];
|
||||
|
||||
float angle1 = i*angleStep;
|
||||
DrawTriangle(c, b, a, ColorFromHSV(angle1*RAD2DEG, 1.0f, 1.0f));
|
||||
DrawTriangle(d, b, c, ColorFromHSV((angle1 + angleStep/2)*RAD2DEG, 1.0f, 1.0f));
|
||||
|
||||
if (outline)
|
||||
{
|
||||
DrawTriangleLines(a, b, c, BLACK);
|
||||
DrawTriangleLines(c, b, d, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
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}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.0f);
|
||||
GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,125 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - vector angle
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 5.0
|
||||
*
|
||||
* 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) 2023-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h" // Required for: Vector2LineAngle()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - vector angle");
|
||||
|
||||
Vector2 v0 = { screenWidth/2.0f, screenHeight/2.0f };
|
||||
Vector2 v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f });
|
||||
Vector2 v2 = { 0 }; // Updated with mouse position
|
||||
|
||||
float angle = 0.0f; // Angle in degrees
|
||||
int angleMode = 0; // 0-Vector2Angle(), 1-Vector2LineAngle()
|
||||
|
||||
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 startangle = 0.0f;
|
||||
|
||||
if (angleMode == 0) startangle = -Vector2LineAngle(v0, v1)*RAD2DEG;
|
||||
if (angleMode == 1) startangle = 0.0f;
|
||||
|
||||
v2 = GetMousePosition();
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) angleMode = !angleMode;
|
||||
|
||||
if ((angleMode == 0) && IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) v1 = GetMousePosition();
|
||||
|
||||
if (angleMode == 0)
|
||||
{
|
||||
// Calculate angle between two vectors, considering a common origin (v0)
|
||||
Vector2 v1Normal = Vector2Normalize(Vector2Subtract(v1, v0));
|
||||
Vector2 v2Normal = Vector2Normalize(Vector2Subtract(v2, v0));
|
||||
|
||||
angle = Vector2Angle(v1Normal, v2Normal)*RAD2DEG;
|
||||
}
|
||||
else if (angleMode == 1)
|
||||
{
|
||||
// Calculate angle defined by a two vectors line, in reference to horizontal line
|
||||
angle = Vector2LineAngle(v0, v2)*RAD2DEG;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (angleMode == 0)
|
||||
{
|
||||
DrawText("MODE 0: Angle between V1 and V2", 10, 10, 20, BLACK);
|
||||
DrawText("Right Click to Move V2", 10, 30, 20, DARKGRAY);
|
||||
|
||||
DrawLineEx(v0, v1, 2.0f, BLACK);
|
||||
DrawLineEx(v0, v2, 2.0f, RED);
|
||||
|
||||
DrawCircleSector(v0, 40.0f, startangle, startangle + angle, 32, Fade(GREEN, 0.6f));
|
||||
}
|
||||
else if (angleMode == 1)
|
||||
{
|
||||
DrawText("MODE 1: Angle formed by line V1 to V2", 10, 10, 20, BLACK);
|
||||
|
||||
DrawLine(0, screenHeight/2, screenWidth, screenHeight/2, LIGHTGRAY);
|
||||
DrawLineEx(v0, v2, 2.0f, RED);
|
||||
|
||||
DrawCircleSector(v0, 40.0f, startangle, startangle - angle, 32, Fade(GREEN, 0.6f));
|
||||
}
|
||||
|
||||
DrawText("v0", (int)v0.x, (int)v0.y, 10, DARKGRAY);
|
||||
|
||||
// If the line from v0 to v1 would overlap the text, move it's position up 10
|
||||
if (angleMode == 0 && Vector2Subtract(v0, v1).y > 0.0f) DrawText("v1", (int)v1.x, (int)v1.y-10, 10, DARKGRAY);
|
||||
if (angleMode == 0 && Vector2Subtract(v0, v1).y < 0.0f) DrawText("v1", (int)v1.x, (int)v1.y, 10, DARKGRAY);
|
||||
|
||||
// If angle mode 1, use v1 to emphasize the horizontal line
|
||||
if (angleMode == 1) DrawText("v1", (int)v0.x + 40, (int)v0.y, 10, DARKGRAY);
|
||||
|
||||
// position adjusted by -10 so it isn't hidden by cursor
|
||||
DrawText("v2", (int)v2.x-10, (int)v2.y-10, 10, DARKGRAY);
|
||||
|
||||
DrawText("Press SPACE to change MODE", 460, 10, 20, DARKGRAY);
|
||||
DrawText(TextFormat("ANGLE: %2.2f", angle), 10, 70, 20, LIME);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |