Gitignore zig crap

This commit is contained in:
2026-05-05 23:14:53 +02:00
parent c7897e55a8
commit 823d0ae29b
1533 changed files with 19 additions and 642271 deletions

View File

@ -1,144 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.5, last time updated with raylib 3.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) 2016-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
#define MAX_BUILDINGS 100
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
Rectangle player = { 400, 280, 40, 40 };
Rectangle buildings[MAX_BUILDINGS] = { 0 };
Color buildColors[MAX_BUILDINGS] = { 0 };
int spacing = 0;
for (int i = 0; i < MAX_BUILDINGS; i++)
{
buildings[i].width = (float)GetRandomValue(50, 200);
buildings[i].height = (float)GetRandomValue(100, 800);
buildings[i].y = screenHeight - 130.0f - buildings[i].height;
buildings[i].x = -6000.0f + spacing;
spacing += (int)buildings[i].width;
buildColors[i] = (Color){
(unsigned char)GetRandomValue(200, 240),
(unsigned char)GetRandomValue(200, 240),
(unsigned char)GetRandomValue(200, 250),
255};
}
Camera2D camera = { 0 };
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 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
//----------------------------------------------------------------------------------
// Player movement
if (IsKeyDown(KEY_RIGHT)) player.x += 2;
else if (IsKeyDown(KEY_LEFT)) player.x -= 2;
// Camera target follows player
camera.target = (Vector2){ player.x + 20, player.y + 20 };
// Camera rotation controls
if (IsKeyDown(KEY_A)) camera.rotation--;
else if (IsKeyDown(KEY_S)) camera.rotation++;
// Limit camera rotation to 80 degrees (-40 to 40)
if (camera.rotation > 40) camera.rotation = 40;
else if (camera.rotation < -40) camera.rotation = -40;
// Camera zoom controls
// Uses log scaling to provide consistent zoom speed
camera.zoom = expf(logf(camera.zoom) + ((float)GetMouseWheelMove()*0.1f));
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
else if (camera.zoom < 0.1f) camera.zoom = 0.1f;
// Camera reset (zoom and rotation)
if (IsKeyPressed(KEY_R))
{
camera.zoom = 1.0f;
camera.rotation = 0.0f;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode2D(camera);
DrawRectangle(-6000, 320, 13000, 8000, DARKGRAY);
for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(buildings[i], buildColors[i]);
DrawRectangleRec(player, RED);
DrawLine((int)camera.target.x, -screenHeight*10, (int)camera.target.x, screenHeight*10, GREEN);
DrawLine(-screenWidth*10, (int)camera.target.y, screenWidth*10, (int)camera.target.y, GREEN);
EndMode2D();
DrawText("SCREEN AREA", 640, 10, 20, RED);
DrawRectangle(0, 0, screenWidth, 5, RED);
DrawRectangle(0, 5, 5, screenHeight - 10, RED);
DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, RED);
DrawRectangle(0, screenHeight - 5, screenWidth, 5, RED);
DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f));
DrawRectangleLines( 10, 10, 250, 113, BLUE);
DrawText("Free 2D camera controls:", 20, 20, 10, BLACK);
DrawText("- Right/Left to move player", 40, 40, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY);
DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY);
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,146 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera mouse zoom
*
* Example complexity rating: [★★☆☆] 2/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 "rlgl.h"
#include "raymath.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera mouse zoom");
Camera2D camera = { 0 };
camera.zoom = 1.0f;
int zoomMode = 0; // 0-Mouse Wheel, 1-Mouse Move
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_ONE)) zoomMode = 0;
else if (IsKeyPressed(KEY_TWO)) zoomMode = 1;
// Translate based on mouse right click
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
Vector2 delta = GetMouseDelta();
delta = Vector2Scale(delta, -1.0f/camera.zoom);
camera.target = Vector2Add(camera.target, delta);
}
if (zoomMode == 0)
{
// Zoom based on mouse wheel
float wheel = GetMouseWheelMove();
if (wheel != 0)
{
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom
camera.target = mouseWorldPos;
// Zoom increment
// Uses log scaling to provide consistent zoom speed
float scale = 0.2f*wheel;
camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
}
}
else
{
// Zoom based on mouse right click
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom
camera.target = mouseWorldPos;
}
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
{
// Zoom increment
// Uses log scaling to provide consistent zoom speed
float deltaX = GetMouseDelta().x;
float scale = 0.005f*deltaX;
camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode2D(camera);
// Draw the 3d grid, rotated 90 degrees and centered around 0,0
// just so we have something in the XY plane
rlPushMatrix();
rlTranslatef(0, 25*50, 0);
rlRotatef(90, 1, 0, 0);
DrawGrid(100, 50);
rlPopMatrix();
// Draw a reference circle
DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON);
EndMode2D();
// Draw mouse reference
//Vector2 mousePos = GetWorldToScreen2D(GetMousePosition(), camera)
DrawCircleV(GetMousePosition(), 4, DARKGRAY);
DrawTextEx(GetFontDefault(), TextFormat("[%i, %i]", GetMouseX(), GetMouseY()),
Vector2Add(GetMousePosition(), (Vector2){ -44, -24 }), 20, 2, BLACK);
DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, DARKGRAY);
if (zoomMode == 0) DrawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY);
else DrawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,307 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera platformer
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 2.5, last time updated with raylib 3.0
*
* Example contributed by arvyy (@arvyy) 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 arvyy (@arvyy)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define G 400
#define PLAYER_JUMP_SPD 350.0f
#define PLAYER_HOR_SPD 200.0f
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct Player {
Vector2 position;
float speed;
bool canJump;
} Player;
typedef struct EnvItem {
Rectangle rect;
int blocking;
Color color;
} EnvItem;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdatePlayer(Player *player, EnvItem *envItems, int envItemsLength, float delta);
void UpdateCameraCenter(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
void UpdateCameraEvenOutOnLanding(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
void UpdateCameraPlayerBoundsPush(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera platformer");
Player player = { 0 };
player.position = (Vector2){ 400, 280 };
player.speed = 0;
player.canJump = false;
EnvItem envItems[] = {
{{ 0, 0, 1000, 400 }, 0, LIGHTGRAY },
{{ 0, 400, 1000, 200 }, 1, GRAY },
{{ 300, 200, 400, 10 }, 1, GRAY },
{{ 250, 300, 100, 10 }, 1, GRAY },
{{ 650, 300, 100, 10 }, 1, GRAY }
};
int envItemsLength = sizeof(envItems)/sizeof(envItems[0]);
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
// Store pointers to the multiple update camera functions
void (*cameraUpdaters[])(Camera2D*, Player*, EnvItem*, int, float, int, int) = {
UpdateCameraCenter,
UpdateCameraCenterInsideMap,
UpdateCameraCenterSmoothFollow,
UpdateCameraEvenOutOnLanding,
UpdateCameraPlayerBoundsPush
};
int cameraOption = 0;
int cameraUpdatersLength = sizeof(cameraUpdaters)/sizeof(cameraUpdaters[0]);
char *cameraDescriptions[] = {
"Follow player center",
"Follow player center, but clamp to map edges",
"Follow player center; smoothed",
"Follow player center horizontally; update player center vertically after landing",
"Player push camera on getting too close to screen edge"
};
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
float deltaTime = GetFrameTime();
UpdatePlayer(&player, envItems, envItemsLength, deltaTime);
camera.zoom += ((float)GetMouseWheelMove()*0.05f);
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
if (IsKeyPressed(KEY_R))
{
camera.zoom = 1.0f;
player.position = (Vector2){ 400, 280 };
}
if (IsKeyPressed(KEY_C)) cameraOption = (cameraOption + 1)%cameraUpdatersLength;
// Call update camera function by its pointer
cameraUpdaters[cameraOption](&camera, &player, envItems, envItemsLength, deltaTime, screenWidth, screenHeight);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(LIGHTGRAY);
BeginMode2D(camera);
for (int i = 0; i < envItemsLength; i++) DrawRectangleRec(envItems[i].rect, envItems[i].color);
Rectangle playerRect = { player.position.x - 20, player.position.y - 40, 40.0f, 40.0f };
DrawRectangleRec(playerRect, RED);
DrawCircleV(player.position, 5.0f, GOLD);
EndMode2D();
DrawText("Controls:", 20, 20, 10, BLACK);
DrawText("- Right/Left to move", 40, 40, 10, DARKGRAY);
DrawText("- Space to jump", 40, 60, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out", 40, 80, 10, DARKGRAY);
DrawText("- R to reset position + zoom", 40, 100, 10, DARKGRAY);
DrawText("- C to change camera mode", 40, 120, 10, DARKGRAY);
DrawText("Current camera mode:", 20, 140, 10, BLACK);
DrawText(cameraDescriptions[cameraOption], 40, 160, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
void UpdatePlayer(Player *player, EnvItem *envItems, int envItemsLength, float delta)
{
if (IsKeyDown(KEY_LEFT)) player->position.x -= PLAYER_HOR_SPD*delta;
if (IsKeyDown(KEY_RIGHT)) player->position.x += PLAYER_HOR_SPD*delta;
if (IsKeyDown(KEY_SPACE) && player->canJump)
{
player->speed = -PLAYER_JUMP_SPD;
player->canJump = false;
}
bool hitObstacle = false;
for (int i = 0; i < envItemsLength; i++)
{
EnvItem *ei = envItems + i;
Vector2 *p = &(player->position);
if (ei->blocking &&
ei->rect.x <= p->x &&
ei->rect.x + ei->rect.width >= p->x &&
ei->rect.y >= p->y &&
ei->rect.y <= p->y + player->speed*delta)
{
hitObstacle = true;
player->speed = 0.0f;
p->y = ei->rect.y;
break;
}
}
if (!hitObstacle)
{
player->position.y += player->speed*delta;
player->speed += G*delta;
player->canJump = false;
}
else player->canJump = true;
}
void UpdateCameraCenter(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
{
camera->offset = (Vector2){ width/2.0f, height/2.0f };
camera->target = player->position;
}
void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
{
camera->target = player->position;
camera->offset = (Vector2){ width/2.0f, height/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
for (int i = 0; i < envItemsLength; i++)
{
EnvItem *ei = envItems + i;
minX = fminf(ei->rect.x, minX);
maxX = fmaxf(ei->rect.x + ei->rect.width, maxX);
minY = fminf(ei->rect.y, minY);
maxY = fmaxf(ei->rect.y + ei->rect.height, maxY);
}
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
if (max.x < width) camera->offset.x = width - (max.x - (float)width/2);
if (max.y < height) camera->offset.y = height - (max.y - (float)height/2);
if (min.x > 0) camera->offset.x = (float)width/2 - min.x;
if (min.y > 0) camera->offset.y = (float)height/2 - min.y;
}
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
{
static float minSpeed = 30;
static float minEffectLength = 10;
static float fractionSpeed = 0.8f;
camera->offset = (Vector2){ width/2.0f, height/2.0f };
Vector2 diff = Vector2Subtract(player->position, camera->target);
float length = Vector2Length(diff);
if (length > minEffectLength)
{
float speed = fmaxf(fractionSpeed*length, minSpeed);
camera->target = Vector2Add(camera->target, Vector2Scale(diff, speed*delta/length));
}
}
void UpdateCameraEvenOutOnLanding(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
{
static float evenOutSpeed = 700;
static int eveningOut = false;
static float evenOutTarget;
camera->offset = (Vector2){ width/2.0f, height/2.0f };
camera->target.x = player->position.x;
if (eveningOut)
{
if (evenOutTarget > camera->target.y)
{
camera->target.y += evenOutSpeed*delta;
if (camera->target.y > evenOutTarget)
{
camera->target.y = evenOutTarget;
eveningOut = 0;
}
}
else
{
camera->target.y -= evenOutSpeed*delta;
if (camera->target.y < evenOutTarget)
{
camera->target.y = evenOutTarget;
eveningOut = 0;
}
}
}
else
{
if (player->canJump && (player->speed == 0) && (player->position.y != camera->target.y))
{
eveningOut = 1;
evenOutTarget = player->position.y;
}
}
}
void UpdateCameraPlayerBoundsPush(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
{
static Vector2 bbox = { 0.2f, 0.2f };
Vector2 bboxWorldMin = GetScreenToWorld2D((Vector2){ (1 - bbox.x)*0.5f*width, (1 - bbox.y)*0.5f*height }, *camera);
Vector2 bboxWorldMax = GetScreenToWorld2D((Vector2){ (1 + bbox.x)*0.5f*width, (1 + bbox.y)*0.5f*height }, *camera);
camera->offset = (Vector2){ (1 - bbox.x)*0.5f*width, (1 - bbox.y)*0.5f*height };
if (player->position.x < bboxWorldMin.x) camera->target.x = player->position.x;
if (player->position.y < bboxWorldMin.y) camera->target.y = player->position.y;
if (player->position.x > bboxWorldMax.x) camera->target.x = bboxWorldMin.x + (player->position.x - bboxWorldMax.x);
if (player->position.y > bboxWorldMax.y) camera->target.y = bboxWorldMin.y + (player->position.y - bboxWorldMax.y);
}

View File

@ -1,169 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera split screen
*
* Example complexity rating: [★★★★] 4/4
*
* Addapted from the core_3d_camera_split_screen example:
* https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by Gabriel dos Santos Sanches (@gabrielssanches) 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) 2023-2025 Gabriel dos Santos Sanches (@gabrielssanches)
*
********************************************************************************************/
#include "raylib.h"
#define PLAYER_SIZE 40
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 440;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera split screen");
Rectangle player1 = { 200, 200, PLAYER_SIZE, PLAYER_SIZE };
Rectangle player2 = { 250, 200, PLAYER_SIZE, PLAYER_SIZE };
Camera2D camera1 = { 0 };
camera1.target = (Vector2){ player1.x, player1.y };
camera1.offset = (Vector2){ 200.0f, 200.0f };
camera1.rotation = 0.0f;
camera1.zoom = 1.0f;
Camera2D camera2 = { 0 };
camera2.target = (Vector2){ player2.x, player2.y };
camera2.offset = (Vector2){ 200.0f, 200.0f };
camera2.rotation = 0.0f;
camera2.zoom = 1.0f;
RenderTexture screenCamera1 = LoadRenderTexture(screenWidth/2, screenHeight);
RenderTexture screenCamera2 = LoadRenderTexture(screenWidth/2, screenHeight);
// Build a flipped rectangle the size of the split view to use for drawing later
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenCamera1.texture.width, (float)-screenCamera1.texture.height };
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 (IsKeyDown(KEY_S)) player1.y += 3.0f;
else if (IsKeyDown(KEY_W)) player1.y -= 3.0f;
if (IsKeyDown(KEY_D)) player1.x += 3.0f;
else if (IsKeyDown(KEY_A)) player1.x -= 3.0f;
if (IsKeyDown(KEY_UP)) player2.y -= 3.0f;
else if (IsKeyDown(KEY_DOWN)) player2.y += 3.0f;
if (IsKeyDown(KEY_RIGHT)) player2.x += 3.0f;
else if (IsKeyDown(KEY_LEFT)) player2.x -= 3.0f;
camera1.target = (Vector2){ player1.x, player1.y };
camera2.target = (Vector2){ player2.x, player2.y };
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(screenCamera1);
ClearBackground(RAYWHITE);
BeginMode2D(camera1);
// Draw full scene with first camera
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){(float)PLAYER_SIZE*i, 0}, (Vector2){ (float)PLAYER_SIZE*i, (float)screenHeight}, LIGHTGRAY);
}
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){0, (float)PLAYER_SIZE*i}, (Vector2){ (float)screenWidth, (float)PLAYER_SIZE*i}, LIGHTGRAY);
}
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
{
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
{
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
}
}
DrawRectangleRec(player1, RED);
DrawRectangleRec(player2, BLUE);
EndMode2D();
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
DrawText("PLAYER1: W/S/A/D to move", 10, 10, 10, MAROON);
EndTextureMode();
BeginTextureMode(screenCamera2);
ClearBackground(RAYWHITE);
BeginMode2D(camera2);
// Draw full scene with second camera
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){ (float)PLAYER_SIZE*i, 0}, (Vector2){ (float)PLAYER_SIZE*i, (float)screenHeight}, LIGHTGRAY);
}
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
{
DrawLineV((Vector2){0, (float)PLAYER_SIZE*i}, (Vector2){ (float)screenWidth, (float)PLAYER_SIZE*i}, LIGHTGRAY);
}
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
{
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
{
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
}
}
DrawRectangleRec(player1, RED);
DrawRectangleRec(player2, BLUE);
EndMode2D();
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
DrawText("PLAYER2: UP/DOWN/LEFT/RIGHT to move", 10, 10, 10, DARKBLUE);
EndTextureMode();
// Draw both views render textures to the screen side by side
BeginDrawing();
ClearBackground(BLACK);
DrawTextureRec(screenCamera1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
DrawTextureRec(screenCamera2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
EndDrawing();
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(screenCamera1); // Unload render texture
UnloadRenderTexture(screenCamera2); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,207 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d camera first person
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.3, last time updated with raylib 1.3
*
* 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "rcamera.h"
#define MAX_COLUMNS 20
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person");
// Define the camera to look into our 3d world (position, target, up vector)
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 2.0f, 4.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 60.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
int cameraMode = CAMERA_FIRST_PERSON;
// Generates some random columns
float heights[MAX_COLUMNS] = { 0 };
Vector3 positions[MAX_COLUMNS] = { 0 };
Color colors[MAX_COLUMNS] = { 0 };
for (int i = 0; i < MAX_COLUMNS; i++)
{
heights[i] = (float)GetRandomValue(1, 12);
positions[i] = (Vector3){ (float)GetRandomValue(-15, 15), heights[i]/2.0f, (float)GetRandomValue(-15, 15) };
colors[i] = (Color){ GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 };
}
DisableCursor(); // Limit cursor to relative movement inside the window
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 camera mode
if (IsKeyPressed(KEY_ONE))
{
cameraMode = CAMERA_FREE;
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
}
if (IsKeyPressed(KEY_TWO))
{
cameraMode = CAMERA_FIRST_PERSON;
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
}
if (IsKeyPressed(KEY_THREE))
{
cameraMode = CAMERA_THIRD_PERSON;
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
}
if (IsKeyPressed(KEY_FOUR))
{
cameraMode = CAMERA_ORBITAL;
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
}
// Switch camera projection
if (IsKeyPressed(KEY_P))
{
if (camera.projection == CAMERA_PERSPECTIVE)
{
// Create isometric view
cameraMode = CAMERA_THIRD_PERSON;
// Note: The target distance is related to the render distance in the orthographic projection
camera.position = (Vector3){ 0.0f, 2.0f, -100.0f };
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.projection = CAMERA_ORTHOGRAPHIC;
camera.fovy = 20.0f; // near plane width in CAMERA_ORTHOGRAPHIC
CameraYaw(&camera, -135*DEG2RAD, true);
CameraPitch(&camera, -45*DEG2RAD, true, true, false);
}
else if (camera.projection == CAMERA_ORTHOGRAPHIC)
{
// Reset to default view
cameraMode = CAMERA_THIRD_PERSON;
camera.position = (Vector3){ 0.0f, 2.0f, 10.0f };
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.projection = CAMERA_PERSPECTIVE;
camera.fovy = 60.0f;
}
}
// Update camera computes movement internally depending on the camera mode
// Some default standard keyboard/mouse inputs are hardcoded to simplify use
// For advanced camera controls, it's recommended to compute camera movement manually
UpdateCamera(&camera, cameraMode); // Update camera
/*
// Camera PRO usage example (EXPERIMENTAL)
// This new camera function allows custom movement/rotation values to be directly provided
// as input parameters, with this approach, rcamera module is internally independent of raylib inputs
UpdateCameraPro(&camera,
(Vector3){
(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward
(IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f,
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - // Move right-left
(IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f,
0.0f // Move up-down
},
(Vector3){
GetMouseDelta().x*0.05f, // Rotation: yaw
GetMouseDelta().y*0.05f, // Rotation: pitch
0.0f // Rotation: roll
},
GetMouseWheelMove()*2.0f); // Move to target (zoom)
*/
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawPlane((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f }, LIGHTGRAY); // Draw ground
DrawCube((Vector3){ -16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall
DrawCube((Vector3){ 16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall
DrawCube((Vector3){ 0.0f, 2.5f, 16.0f }, 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall
// Draw some cubes around
for (int i = 0; i < MAX_COLUMNS; i++)
{
DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON);
}
// Draw player cube
if (cameraMode == CAMERA_THIRD_PERSON)
{
DrawCube(camera.target, 0.5f, 0.5f, 0.5f, PURPLE);
DrawCubeWires(camera.target, 0.5f, 0.5f, 0.5f, DARKPURPLE);
}
EndMode3D();
// Draw info boxes
DrawRectangle(5, 5, 330, 100, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(5, 5, 330, 100, BLUE);
DrawText("Camera controls:", 15, 15, 10, BLACK);
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
DrawText("- Camera mode keys: 1, 2, 3, 4", 15, 60, 10, BLACK);
DrawText("- Zoom keys: num-plus, num-minus or mouse scroll", 15, 75, 10, BLACK);
DrawText("- Camera projection key: P", 15, 90, 10, BLACK);
DrawRectangle(600, 5, 195, 100, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(600, 5, 195, 100, BLUE);
DrawText("Camera status:", 610, 15, 10, BLACK);
DrawText(TextFormat("- Mode: %s", (cameraMode == CAMERA_FREE) ? "FREE" :
(cameraMode == CAMERA_FIRST_PERSON) ? "FIRST_PERSON" :
(cameraMode == CAMERA_THIRD_PERSON) ? "THIRD_PERSON" :
(cameraMode == CAMERA_ORBITAL) ? "ORBITAL" : "CUSTOM"), 610, 30, 10, BLACK);
DrawText(TextFormat("- Projection: %s", (camera.projection == CAMERA_PERSPECTIVE) ? "PERSPECTIVE" :
(camera.projection == CAMERA_ORTHOGRAPHIC) ? "ORTHOGRAPHIC" : "CUSTOM"), 610, 45, 10, BLACK);
DrawText(TextFormat("- Position: (%06.3f, %06.3f, %06.3f)", camera.position.x, camera.position.y, camera.position.z), 610, 60, 10, BLACK);
DrawText(TextFormat("- Target: (%06.3f, %06.3f, %06.3f)", camera.target.x, camera.target.y, camera.target.z), 610, 75, 10, BLACK);
DrawText(TextFormat("- Up: (%06.3f, %06.3f, %06.3f)", camera.up.x, camera.up.y, camera.up.z), 610, 90, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,329 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d camera fps
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Agnis Aldiņš (@nezvers) 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 Agnis Aldiņš (@nezvers)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Movement constants
#define GRAVITY 32.0f
#define MAX_SPEED 20.0f
#define CROUCH_SPEED 5.0f
#define JUMP_FORCE 12.0f
#define MAX_ACCEL 150.0f
// Grounded drag
#define FRICTION 0.86f
// Increasing air drag, increases strafing speed
#define AIR_DRAG 0.98f
// Responsiveness for turning movement direction to looked direction
#define CONTROL 15.0f
#define CROUCH_HEIGHT 0.0f
#define STAND_HEIGHT 1.0f
#define BOTTOM_HEIGHT 0.5f
#define NORMALIZE_INPUT 0
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Body structure
typedef struct {
Vector3 position;
Vector3 velocity;
Vector3 dir;
bool isGrounded;
} Body;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static Vector2 sensitivity = { 0.001f, 0.001f };
static Body player = { 0 };
static Vector2 lookRotation = { 0 };
static float headTimer = 0.0f;
static float walkLerp = 0.0f;
static float headLerp = STAND_HEIGHT;
static Vector2 lean = { 0 };
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static void DrawLevel(void);
static void UpdateCameraFPS(Camera *camera);
static void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera fps");
// Initialize camera variables
// NOTE: UpdateCameraFPS() takes care of the rest
Camera camera = { 0 };
camera.fovy = 60.0f;
camera.projection = CAMERA_PERSPECTIVE;
camera.position = (Vector3){
player.position.x,
player.position.y + (BOTTOM_HEIGHT + headLerp),
player.position.z,
};
UpdateCameraFPS(&camera); // Update camera parameters
DisableCursor(); // Limit cursor to relative movement inside the window
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 mouseDelta = GetMouseDelta();
lookRotation.x -= mouseDelta.x*sensitivity.x;
lookRotation.y += mouseDelta.y*sensitivity.y;
char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A));
char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S));
bool crouching = IsKeyDown(KEY_LEFT_CONTROL);
UpdateBody(&player, lookRotation.x, sideway, forward, IsKeyPressed(KEY_SPACE), crouching);
float delta = GetFrameTime();
headLerp = Lerp(headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.0f*delta);
camera.position = (Vector3){
player.position.x,
player.position.y + (BOTTOM_HEIGHT + headLerp),
player.position.z,
};
if (player.isGrounded && ((forward != 0) || (sideway != 0)))
{
headTimer += delta*3.0f;
walkLerp = Lerp(walkLerp, 1.0f, 10.0f*delta);
camera.fovy = Lerp(camera.fovy, 55.0f, 5.0f*delta);
}
else
{
walkLerp = Lerp(walkLerp, 0.0f, 10.0f*delta);
camera.fovy = Lerp(camera.fovy, 60.0f, 5.0f*delta);
}
lean.x = Lerp(lean.x, sideway*0.02f, 10.0f*delta);
lean.y = Lerp(lean.y, forward*0.015f, 10.0f*delta);
UpdateCameraFPS(&camera);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawLevel();
EndMode3D();
// Draw info box
DrawRectangle(5, 5, 330, 75, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(5, 5, 330, 75, BLUE);
DrawText("Camera controls:", 15, 15, 10, BLACK);
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
DrawText(TextFormat("- Velocity Len: (%06.3f)", Vector2Length((Vector2){ player.velocity.x, player.velocity.z })), 15, 60, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Update body considering current world state
void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
{
Vector2 input = (Vector2){ (float)side, (float)-forward };
#if defined(NORMALIZE_INPUT)
// Slow down diagonal movement
if ((side != 0) && (forward != 0)) input = Vector2Normalize(input);
#endif
float delta = GetFrameTime();
if (!body->isGrounded) body->velocity.y -= GRAVITY*delta;
if (body->isGrounded && jumpPressed)
{
body->velocity.y = JUMP_FORCE;
body->isGrounded = false;
// Sound can be played at this moment
//SetSoundPitch(fxJump, 1.0f + (GetRandomValue(-100, 100)*0.001));
//PlaySound(fxJump);
}
Vector3 front = (Vector3){ sinf(rot), 0.f, cosf(rot) };
Vector3 right = (Vector3){ cosf(-rot), 0.f, sinf(-rot) };
Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, };
body->dir = Vector3Lerp(body->dir, desiredDir, CONTROL*delta);
float decel = (body->isGrounded ? FRICTION : AIR_DRAG);
Vector3 hvel = (Vector3){ body->velocity.x*decel, 0.0f, body->velocity.z*decel };
float hvelLength = Vector3Length(hvel); // Magnitude
if (hvelLength < (MAX_SPEED*0.01f)) hvel = (Vector3){ 0 };
// This is what creates strafing
float speed = Vector3DotProduct(hvel, body->dir);
// Whenever the amount of acceleration to add is clamped by the maximum acceleration constant,
// a Player can make the speed faster by bringing the direction closer to horizontal velocity angle
// More info here: https://youtu.be/v3zT3Z5apaM?t=165
float maxSpeed = (crouchHold? CROUCH_SPEED : MAX_SPEED);
float accel = Clamp(maxSpeed - speed, 0.f, MAX_ACCEL*delta);
hvel.x += body->dir.x*accel;
hvel.z += body->dir.z*accel;
body->velocity.x = hvel.x;
body->velocity.z = hvel.z;
body->position.x += body->velocity.x*delta;
body->position.y += body->velocity.y*delta;
body->position.z += body->velocity.z*delta;
// Fancy collision system against the floor
if (body->position.y <= 0.0f)
{
body->position.y = 0.0f;
body->velocity.y = 0.0f;
body->isGrounded = true; // Enable jumping
}
}
// Update camera for FPS behaviour
static void UpdateCameraFPS(Camera *camera)
{
const Vector3 up = (Vector3){ 0.0f, 1.0f, 0.0f };
const Vector3 targetOffset = (Vector3){ 0.0f, 0.0f, -1.0f };
// Left and right
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.x);
// Clamp view up
float maxAngleUp = Vector3Angle(up, yaw);
maxAngleUp -= 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) > maxAngleUp) { lookRotation.y = -maxAngleUp; }
// Clamp view down
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
maxAngleDown *= -1.0f; // Downwards angle is negative
maxAngleDown += 0.001f; // Avoid numerical errors
if ( -(lookRotation.y) < maxAngleDown) { lookRotation.y = -maxAngleDown; }
// Up and down
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
// Rotate view vector around right axis
float pitchAngle = -lookRotation.y - lean.y;
pitchAngle = Clamp(pitchAngle, -PI/2 + 0.0001f, PI/2 - 0.0001f); // Clamp angle so it doesn't go past straight up or straight down
Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, pitchAngle);
// Head animation
// Rotate up direction around forward axis
float headSin = sinf(headTimer*PI);
float headCos = cosf(headTimer*PI);
const float stepRotation = 0.01f;
camera->up = Vector3RotateByAxisAngle(up, pitch, headSin*stepRotation + lean.x);
// Camera BOB
const float bobSide = 0.1f;
const float bobUp = 0.15f;
Vector3 bobbing = Vector3Scale(right, headSin*bobSide);
bobbing.y = fabsf(headCos*bobUp);
camera->position = Vector3Add(camera->position, Vector3Scale(bobbing, walkLerp));
camera->target = Vector3Add(camera->position, pitch);
}
// Draw game level
static void DrawLevel(void)
{
const int floorExtent = 25;
const float tileSize = 5.0f;
const Color tileColor1 = (Color){ 150, 200, 200, 255 };
// Floor tiles
for (int y = -floorExtent; y < floorExtent; y++)
{
for (int x = -floorExtent; x < floorExtent; x++)
{
if ((y & 1) && (x & 1))
{
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, tileColor1);
}
else if (!(y & 1) && !(x & 1))
{
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, LIGHTGRAY);
}
}
}
const Vector3 towerSize = (Vector3){ 16.0f, 32.0f, 16.0f };
const Color towerColor = (Color){ 150, 200, 200, 255 };
Vector3 towerPos = (Vector3){ 16.0f, 16.0f, 16.0f };
DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
towerPos.x *= -1;
DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
towerPos.z *= -1;
DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
towerPos.x *= -1;
DrawCubeV(towerPos, towerSize, towerColor);
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
// Red sun
DrawSphere((Vector3){ 300.0f, 300.0f, 0.0f }, 100.0f, (Color){ 255, 0, 0, 255 });
}

View File

@ -1,88 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d camera free
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.3, last time updated with raylib 1.3
*
* 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) 2015-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 [core] example - 3d camera free");
// Define the camera to look into our 3d world
Camera3D camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FREE);
if (IsKeyPressed(KEY_Z)) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
DrawRectangle( 10, 10, 320, 93, Fade(SKYBLUE, 0.5f));
DrawRectangleLines( 10, 10, 320, 93, BLUE);
DrawText("Free camera default controls:", 20, 20, 10, BLACK);
DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY);
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY);
DrawText("- Z to zoom to (0, 0, 0)", 40, 80, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,80 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d camera mode
*
* 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 [core] example - 3d camera mode");
// Define the camera to look into our 3d world
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
Vector3 cubePosition = { 0.0f, 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
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Welcome to the third dimension!", 10, 40, 20, DARKGRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,176 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d camera split screen
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 3.7, last time updated with raylib 4.0
*
* 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) 2021-2025 Jeffery Myers (@JeffM2501)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera split screen");
// Setup player 1 camera and screen
Camera cameraPlayer1 = { 0 };
cameraPlayer1.fovy = 45.0f;
cameraPlayer1.up.y = 1.0f;
cameraPlayer1.target.y = 1.0f;
cameraPlayer1.position.z = -3.0f;
cameraPlayer1.position.y = 1.0f;
RenderTexture screenPlayer1 = LoadRenderTexture(screenWidth/2, screenHeight);
// Setup player two camera and screen
Camera cameraPlayer2 = { 0 };
cameraPlayer2.fovy = 45.0f;
cameraPlayer2.up.y = 1.0f;
cameraPlayer2.target.y = 3.0f;
cameraPlayer2.position.x = -3.0f;
cameraPlayer2.position.y = 3.0f;
RenderTexture screenPlayer2 = LoadRenderTexture(screenWidth/2, screenHeight);
// Build a flipped rectangle the size of the split view to use for drawing later
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenPlayer1.texture.width, (float)-screenPlayer1.texture.height };
// Grid data
int count = 5;
float spacing = 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
//----------------------------------------------------------------------------------
// If anyone moves this frame, how far will they move based on the time since the last frame
// this moves things at 10 world units per second, regardless of the actual FPS
float offsetThisFrame = 10.0f*GetFrameTime();
// Move Player1 forward and backwards (no turning)
if (IsKeyDown(KEY_W))
{
cameraPlayer1.position.z += offsetThisFrame;
cameraPlayer1.target.z += offsetThisFrame;
}
else if (IsKeyDown(KEY_S))
{
cameraPlayer1.position.z -= offsetThisFrame;
cameraPlayer1.target.z -= offsetThisFrame;
}
// Move Player2 forward and backwards (no turning)
if (IsKeyDown(KEY_UP))
{
cameraPlayer2.position.x += offsetThisFrame;
cameraPlayer2.target.x += offsetThisFrame;
}
else if (IsKeyDown(KEY_DOWN))
{
cameraPlayer2.position.x -= offsetThisFrame;
cameraPlayer2.target.x -= offsetThisFrame;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Draw Player1 view to the render texture
BeginTextureMode(screenPlayer1);
ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer1);
// Draw scene: grid of cube trees on a plane to make a "world"
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
for (float x = -count*spacing; x <= count*spacing; x += spacing)
{
for (float z = -count*spacing; z <= count*spacing; z += spacing)
{
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
}
}
// Draw a cube at each player's position
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
EndMode3D();
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
DrawText("PLAYER1: W/S to move", 10, 10, 20, MAROON);
EndTextureMode();
// Draw Player2 view to the render texture
BeginTextureMode(screenPlayer2);
ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer2);
// Draw scene: grid of cube trees on a plane to make a "world"
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
for (float x = -count*spacing; x <= count*spacing; x += spacing)
{
for (float z = -count*spacing; z <= count*spacing; z += spacing)
{
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
}
}
// Draw a cube at each player's position
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
EndMode3D();
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
DrawText("PLAYER2: UP/DOWN to move", 10, 10, 20, DARKBLUE);
EndTextureMode();
// Draw both views render textures to the screen side by side
BeginDrawing();
ClearBackground(BLACK);
DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
EndDrawing();
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(screenPlayer1); // Unload render texture
UnloadRenderTexture(screenPlayer2); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,120 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - 3d picking
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.3, 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) 2015-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 [core] example - 3d picking");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Vector3 cubePosition = { 0.0f, 1.0f, 0.0f };
Vector3 cubeSize = { 2.0f, 2.0f, 2.0f };
Ray ray = { 0 }; // Picking line ray
RayCollision collision = { 0 }; // Ray collision hit info
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 (IsCursorHidden()) UpdateCamera(&camera, CAMERA_FIRST_PERSON);
// Toggle camera controls
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
if (IsCursorHidden()) EnableCursor();
else DisableCursor();
}
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
if (!collision.hit)
{
ray = GetScreenToWorldRay(GetMousePosition(), camera);
// Check collision between ray and box
collision = GetRayCollisionBox(ray,
(BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 },
(Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }});
}
else collision.hit = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
if (collision.hit)
{
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED);
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON);
DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN);
}
else
{
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY);
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY);
}
DrawRay(ray, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Try clicking on the box with your mouse!", 240, 10, 20, DARKGRAY);
if (collision.hit) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30))/2, (int)(screenHeight*0.1f), 30, GREEN);
DrawText("Right click mouse to toggle camera controls", 10, 430, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,340 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - automation events
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example based on 2d_camera_platformer example by arvyy (@arvyy)
*
* 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"
#define GRAVITY 400
#define PLAYER_JUMP_SPD 350.0f
#define PLAYER_HOR_SPD 200.0f
#define MAX_ENVIRONMENT_ELEMENTS 5
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct Player {
Vector2 position;
float speed;
bool canJump;
} Player;
typedef struct EnvElement {
Rectangle rect;
int blocking;
Color color;
} EnvElement;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - automation events");
// Define player
Player player = { 0 };
player.position = (Vector2){ 400, 280 };
player.speed = 0;
player.canJump = false;
// Define environment elements (platforms)
EnvElement envElements[MAX_ENVIRONMENT_ELEMENTS] = {
{{ 0, 0, 1000, 400 }, 0, LIGHTGRAY },
{{ 0, 400, 1000, 200 }, 1, GRAY },
{{ 300, 200, 400, 10 }, 1, GRAY },
{{ 250, 300, 100, 10 }, 1, GRAY },
{{ 650, 300, 100, 10 }, 1, GRAY }
};
// Define camera
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
// Automation events
AutomationEventList aelist = LoadAutomationEventList(0); // Initialize list of automation events to record new events
SetAutomationEventList(&aelist);
bool eventRecording = false;
bool eventPlaying = false;
unsigned int frameCounter = 0;
unsigned int playFrameCounter = 0;
unsigned int currentPlayFrame = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
float deltaTime = 0.015f;//GetFrameTime();
// Dropped files logic
//----------------------------------------------------------------------------------
if (IsFileDropped())
{
FilePathList droppedFiles = LoadDroppedFiles();
// Supports loading .rgs style files (text or binary) and .png style palette images
if (IsFileExtension(droppedFiles.paths[0], ".txt;.rae"))
{
UnloadAutomationEventList(aelist);
aelist = LoadAutomationEventList(droppedFiles.paths[0]);
eventRecording = false;
// Reset scene state to play
eventPlaying = true;
playFrameCounter = 0;
currentPlayFrame = 0;
player.position = (Vector2){ 400, 280 };
player.speed = 0;
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
}
//----------------------------------------------------------------------------------
// Update player
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_LEFT)) player.position.x -= PLAYER_HOR_SPD*deltaTime;
if (IsKeyDown(KEY_RIGHT)) player.position.x += PLAYER_HOR_SPD*deltaTime;
if (IsKeyDown(KEY_SPACE) && player.canJump)
{
player.speed = -PLAYER_JUMP_SPD;
player.canJump = false;
}
int hitObstacle = 0;
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
{
EnvElement *element = &envElements[i];
Vector2 *p = &(player.position);
if (element->blocking &&
element->rect.x <= p->x &&
element->rect.x + element->rect.width >= p->x &&
element->rect.y >= p->y &&
element->rect.y <= p->y + player.speed*deltaTime)
{
hitObstacle = 1;
player.speed = 0.0f;
p->y = element->rect.y;
}
}
if (!hitObstacle)
{
player.position.y += player.speed*deltaTime;
player.speed += GRAVITY*deltaTime;
player.canJump = false;
}
else player.canJump = true;
if (IsKeyPressed(KEY_R))
{
// Reset game state
player.position = (Vector2){ 400, 280 };
player.speed = 0;
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
//----------------------------------------------------------------------------------
// Events playing
// NOTE: Logic must be before Camera update because it depends on mouse-wheel value,
// that can be set by the played event... but some other inputs could be affected
//----------------------------------------------------------------------------------
if (eventPlaying)
{
// NOTE: Multiple events could be executed in a single frame
while (playFrameCounter == aelist.events[currentPlayFrame].frame)
{
PlayAutomationEvent(aelist.events[currentPlayFrame]);
currentPlayFrame++;
if (currentPlayFrame == aelist.count)
{
eventPlaying = false;
currentPlayFrame = 0;
playFrameCounter = 0;
TraceLog(LOG_INFO, "FINISH PLAYING!");
break;
}
}
playFrameCounter++;
}
//----------------------------------------------------------------------------------
// Update camera
//----------------------------------------------------------------------------------
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
// WARNING: On event replay, mouse-wheel internal value is set
camera.zoom += ((float)GetMouseWheelMove()*0.05f);
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
{
EnvElement *element = &envElements[i];
minX = fminf(element->rect.x, minX);
maxX = fmaxf(element->rect.x + element->rect.width, maxX);
minY = fminf(element->rect.y, minY);
maxY = fmaxf(element->rect.y + element->rect.height, maxY);
}
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera);
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera);
if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - (float)screenWidth/2);
if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - (float)screenHeight/2);
if (min.x > 0) camera.offset.x = (float)screenWidth/2 - min.x;
if (min.y > 0) camera.offset.y = (float)screenHeight/2 - min.y;
//----------------------------------------------------------------------------------
// Events management
if (IsKeyPressed(KEY_S)) // Toggle events recording
{
if (!eventPlaying)
{
if (eventRecording)
{
StopAutomationEventRecording();
eventRecording = false;
ExportAutomationEventList(aelist, "automation.rae");
TraceLog(LOG_INFO, "RECORDED FRAMES: %i", aelist.count);
}
else
{
SetAutomationEventBaseFrame(180);
StartAutomationEventRecording();
eventRecording = true;
}
}
}
else if (IsKeyPressed(KEY_A)) // Toggle events playing (WARNING: Starts next frame)
{
if (!eventRecording && (aelist.count > 0))
{
// Reset scene state to play
eventPlaying = true;
playFrameCounter = 0;
currentPlayFrame = 0;
player.position = (Vector2){ 400, 280 };
player.speed = 0;
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
}
if (eventRecording || eventPlaying) frameCounter++;
else frameCounter = 0;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(LIGHTGRAY);
BeginMode2D(camera);
// Draw environment elements
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
{
DrawRectangleRec(envElements[i].rect, envElements[i].color);
}
// Draw player rectangle
DrawRectangleRec((Rectangle){ player.position.x - 20, player.position.y - 40, 40, 40 }, RED);
EndMode2D();
// Draw game controls
DrawRectangle(10, 10, 290, 145, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 10, 290, 145, Fade(BLUE, 0.8f));
DrawText("Controls:", 20, 20, 10, BLACK);
DrawText("- RIGHT | LEFT: Player movement", 30, 40, 10, DARKGRAY);
DrawText("- SPACE: Player jump", 30, 60, 10, DARKGRAY);
DrawText("- R: Reset game state", 30, 80, 10, DARKGRAY);
DrawText("- S: START/STOP RECORDING INPUT EVENTS", 30, 110, 10, BLACK);
DrawText("- A: REPLAY LAST RECORDED INPUT EVENTS", 30, 130, 10, BLACK);
// Draw automation events recording indicator
if (eventRecording)
{
DrawRectangle(10, 160, 290, 30, Fade(RED, 0.3f));
DrawRectangleLines(10, 160, 290, 30, Fade(MAROON, 0.8f));
DrawCircle(30, 175, 10, MAROON);
if (((frameCounter/15)%2) == 1) DrawText(TextFormat("RECORDING EVENTS... [%i]", aelist.count), 50, 170, 10, MAROON);
}
else if (eventPlaying)
{
DrawRectangle(10, 160, 290, 30, Fade(LIME, 0.3f));
DrawRectangleLines(10, 160, 290, 30, Fade(DARKGREEN, 0.8f));
DrawTriangle((Vector2){ 20, 155 + 10 }, (Vector2){ 20, 155 + 30 }, (Vector2){ 40, 155 + 20 }, DARKGREEN);
if (((frameCounter/15)%2) == 1) DrawText(TextFormat("PLAYING RECORDED EVENTS... [%i]", currentPlayFrame), 50, 170, 10, DARKGREEN);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,154 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - basic screen manager
*
* Example complexity rating: [★☆☆☆] 1/4
*
* NOTE: This example illustrates a very simple screen manager based on a states machines
*
* Example originally created with raylib 4.0, 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) 2021-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------------
// Types and Structures Definition
//------------------------------------------------------------------------------------------
typedef enum GameScreen { LOGO = 0, TITLE, GAMEPLAY, ENDING } GameScreen;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic screen manager");
GameScreen currentScreen = LOGO;
// TODO: Initialize all required variables and load all required data here!
int framesCounter = 0; // Useful to count frames
SetTargetFPS(60); // Set desired framerate (frames-per-second)
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
switch (currentScreen)
{
case LOGO:
{
// TODO: Update LOGO screen variables here!
framesCounter++; // Count frames
// Wait for 2 seconds (120 frames) before jumping to TITLE screen
if (framesCounter > 120)
{
currentScreen = TITLE;
}
} break;
case TITLE:
{
// TODO: Update TITLE screen variables here!
// Press enter to change to GAMEPLAY screen
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
{
currentScreen = GAMEPLAY;
}
} break;
case GAMEPLAY:
{
// TODO: Update GAMEPLAY screen variables here!
// Press enter to change to ENDING screen
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
{
currentScreen = ENDING;
}
} break;
case ENDING:
{
// TODO: Update ENDING screen variables here!
// Press enter to return to TITLE screen
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
{
currentScreen = TITLE;
}
} break;
default: break;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
switch(currentScreen)
{
case LOGO:
{
// TODO: Draw LOGO screen here!
DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY);
DrawText("WAIT for 2 SECONDS...", 290, 220, 20, GRAY);
} break;
case TITLE:
{
// TODO: Draw TITLE screen here!
DrawRectangle(0, 0, screenWidth, screenHeight, GREEN);
DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN);
DrawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, DARKGREEN);
} break;
case GAMEPLAY:
{
// TODO: Draw GAMEPLAY screen here!
DrawRectangle(0, 0, screenWidth, screenHeight, PURPLE);
DrawText("GAMEPLAY SCREEN", 20, 20, 40, MAROON);
DrawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, MAROON);
} break;
case ENDING:
{
// TODO: Draw ENDING screen here!
DrawRectangle(0, 0, screenWidth, screenHeight, BLUE);
DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE);
DrawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, DARKBLUE);
} break;
default: break;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// TODO: Unload all loaded data (textures, fonts, audio) here!
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,72 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - basic window
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Welcome to raylib!
*
* To test examples, just press F6 and execute 'raylib_compile_execute' script
* Note that compiled executable is placed in the same folder as .c file
*
* To test the examples on Web, press F6 and execute 'raylib_compile_execute_web' script
* Web version of the program is generated in the same folder as .c file
*
* You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com
*
* Enjoy using raylib. :)
*
* 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) 2013-2026 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 [core] example - basic window");
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);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,164 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - clipboard text
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Ananth S (@Ananth1839) 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 Ananth S (@Ananth1839)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#define MAX_TEXT_SAMPLES 5
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text");
// Define some sample texts
const char *sampleTexts[MAX_TEXT_SAMPLES] = {
"Hello from raylib!",
"The quick brown fox jumps over the lazy dog",
"Clipboard operations are useful!",
"raylib is a simple and easy-to-use library",
"Copy and paste me!"
};
const char *clipboardText = NULL;
char inputBuffer[256] = "Hello from raylib!"; // Random initial string
// UI required variables
bool textBoxEditMode = false;
bool btnCutPressed = false;
bool btnCopyPressed = false;
bool btnPastePressed = false;
bool btnClearPressed = false;
bool btnRandomPressed = false;
// Set UI style
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
GuiSetIconScale(2);
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
//----------------------------------------------------------------------------------
// Handle button interactions
if (btnCutPressed)
{
SetClipboardText(inputBuffer);
clipboardText = GetClipboardText();
inputBuffer[0] = '\0'; // Quick solution to clear text
//memset(inputBuffer, 0, 256); // Clear full buffer properly
}
if (btnCopyPressed)
{
SetClipboardText(inputBuffer); // Copy text to clipboard
clipboardText = GetClipboardText(); // Get text from clipboard
}
if (btnPastePressed)
{
// Paste text from clipboard
clipboardText = GetClipboardText();
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
}
if (btnClearPressed)
{
inputBuffer[0] = '\0'; // Quick solution to clear text
//memset(inputBuffer, 0, 256); // Clear full buffer properly
}
if (btnRandomPressed)
{
// Get random text from sample list
TextCopy(inputBuffer, sampleTexts[GetRandomValue(0, MAX_TEXT_SAMPLES - 1)]);
}
// Quick cut/copy/paste with keyboard shortcuts
if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))
{
if (IsKeyPressed(KEY_X))
{
SetClipboardText(inputBuffer);
inputBuffer[0] = '\0'; // Quick solution to clear text
}
if (IsKeyPressed(KEY_C)) SetClipboardText(inputBuffer);
if (IsKeyPressed(KEY_V))
{
clipboardText = GetClipboardText();
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw instructions
GuiLabel((Rectangle){ 50, 20, 700, 36 }, "Use the BUTTONS or KEY SHORTCUTS:");
DrawText("[CTRL+X] - CUT | [CTRL+C] COPY | [CTRL+V] | PASTE", 50, 60, 20, MAROON);
// Draw text box
if (GuiTextBox((Rectangle){ 50, 120, 652, 40 }, inputBuffer, 256, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
// Random text button
btnRandomPressed = GuiButton((Rectangle){ 50 + 652 + 8, 120, 40, 40 }, "#77#");
// Draw buttons
btnCutPressed = GuiButton((Rectangle){ 50, 180, 158, 40 }, "#17#CUT");
btnCopyPressed = GuiButton((Rectangle){ 50 + 165, 180, 158, 40 }, "#16#COPY");
btnPastePressed = GuiButton((Rectangle){ 50 + 165*2, 180, 158, 40 }, "#18#PASTE");
btnClearPressed = GuiButton((Rectangle){ 50 + 165*3, 180, 158, 40 }, "#143#CLEAR");
// Draw clipboard status
GuiSetState(STATE_DISABLED);
GuiLabel((Rectangle){ 50, 260, 700, 40 }, "Clipboard current text data:");
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
GuiTextBox((Rectangle){ 50, 300, 700, 40 }, (char *)clipboardText, 256, false);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
GuiLabel((Rectangle){ 50, 360, 700, 40 }, "Try copying text from other applications and pasting here!");
GuiSetState(STATE_NORMAL);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,143 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - compute hash
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.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) 2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static char *GetDataAsHexText(const unsigned int *data, int dataSize);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - compute hash");
// UI controls variables
char textInput[96] = "The quick brown fox jumps over the lazy dog.";
bool textBoxEditMode = false;
bool btnComputeHashes = false;
// Data hash values
unsigned int hashCRC32 = 0;
unsigned int *hashMD5 = NULL;
unsigned int *hashSHA1 = NULL;
unsigned int *hashSHA256 = NULL;
// Base64 encoded data
char *base64Text = NULL;
int base64TextSize = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (btnComputeHashes)
{
int textInputLen = (int)strlen(textInput);
// Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
base64Text = EncodeDataBase64((unsigned char *)textInput, textInputLen, &base64TextSize);
hashCRC32 = ComputeCRC32((unsigned char *)textInput, textInputLen); // Compute CRC32 hash code (4 bytes)
hashMD5 = ComputeMD5((unsigned char *)textInput, textInputLen); // Compute MD5 hash code, returns static int[4] (16 bytes)
hashSHA1 = ComputeSHA1((unsigned char *)textInput, textInputLen); // Compute SHA1 hash code, returns static int[5] (20 bytes)
hashSHA256 = ComputeSHA256((unsigned char *)textInput, textInputLen); // Compute SHA256 hash code, returns static int[8] (32 bytes)
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
GuiLabel((Rectangle){ 40, 26, 720, 32 }, "INPUT DATA (TEXT):");
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
if (GuiTextBox((Rectangle){ 40, 64, 720, 32 }, textInput, 95, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
btnComputeHashes = GuiButton((Rectangle){ 40, 64 + 40, 720, 32 }, "COMPUTE INPUT DATA HASHES");
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
GuiLabel((Rectangle){ 40, 160, 720, 32 }, "INPUT DATA HASH VALUES:");
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
GuiLabel((Rectangle){ 40, 200, 120, 32 }, "CRC32 [32 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200, 720 - 120, 32 }, GetDataAsHexText(&hashCRC32, 1), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36, 120, 32 }, "MD5 [128 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36, 720 - 120, 32 }, GetDataAsHexText(hashMD5, 4), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36*2, 120, 32 }, "SHA1 [160 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*2, 720 - 120, 32 }, GetDataAsHexText(hashSHA1, 5), 120, false);
GuiLabel((Rectangle){ 40, 200 + 36*3, 120, 32 }, "SHA256 [256 bit]:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*3, 720 - 120, 32 }, GetDataAsHexText(hashSHA256, 8), 120, false);
GuiSetState(STATE_FOCUSED);
GuiLabel((Rectangle){ 40, 200 + 36*5 - 30, 320, 32 }, "BONUS - BAS64 ENCODED STRING:");
GuiSetState(STATE_NORMAL);
GuiLabel((Rectangle){ 40, 200 + 36*5, 120, 32 }, "BASE64 ENCODING:");
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*5, 720 - 120, 32 }, base64Text, 120, false);
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
MemFree(base64Text); // Free Base64 text data
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
static char *GetDataAsHexText(const unsigned int *data, int dataSize)
{
static char text[128] = { 0 };
memset(text, 0, 128);
if ((data != NULL) && (dataSize > 0) && (dataSize < ((128/8) - 1)))
{
for (int i = 0; i < dataSize; i++) TextCopy(text + i*8, TextFormat("%08X", data[i]));
}
else TextCopy(text, "00000000");
return text;
}

View File

@ -1,141 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - custom frame control
*
* Example complexity rating: [★★★★] 4/4
*
* NOTE: WARNING: This is an example for advanced users willing to have full control over
* the frame processes. By default, EndDrawing() calls the following processes:
* 1. Draw remaining batch data: rlDrawRenderBatchActive()
* 2. SwapScreenBuffer()
* 3. Frame time control: WaitTime()
* 4. PollInputEvents()
*
* To avoid steps 2, 3 and 4, flag SUPPORT_CUSTOM_FRAME_CONTROL can be enabled in
* config.h (it requires recompiling raylib). This way those steps are up to the user
*
* Note that enabling this flag invalidates some functions:
* - GetFrameTime()
* - SetTargetFPS()
* - GetFPS()
*
* Example originally created with raylib 4.0, 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) 2021-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 [core] example - custom frame control");
// Custom timming variables
double previousTime = GetTime(); // Previous time measure
double currentTime = 0.0; // Current time measure
double updateDrawTime = 0.0; // Update + Draw time
double waitTime = 0.0; // Wait time (if target fps required)
float deltaTime = 0.0f; // Frame time (Update + Draw + Wait time)
float timeCounter = 0.0f; // Accumulative time counter (seconds)
float position = 0.0f; // Circle position
bool pause = false; // Pause control flag
int targetFPS = 60; // Our initial target fps
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
#ifndef PLATFORM_WEB // NOTE: On non web platforms the PollInputEvents just works before the inputs checks
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
#endif
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
if (IsKeyPressed(KEY_UP)) targetFPS += 20;
else if (IsKeyPressed(KEY_DOWN)) targetFPS -= 20;
if (targetFPS < 0) targetFPS = 0;
if (!pause)
{
position += 200*deltaTime; // We move at 200 pixels per second
if (position >= GetScreenWidth()) position = 0;
timeCounter += deltaTime; // We count time (seconds)
}
#ifdef PLATFORM_WEB // NOTE: On web platform for some reason the PollInputEvents only works after the inputs check, so just call it after check all your inputs (on web)
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
#endif
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < GetScreenWidth()/200; i++) DrawRectangle(200*i, 0, 1, GetScreenHeight(), SKYBLUE);
DrawCircle((int)position, GetScreenHeight()/2 - 25, 50, RED);
DrawText(TextFormat("%03.0f ms", timeCounter*1000.0f), (int)position - 40, GetScreenHeight()/2 - 100, 20, MAROON);
DrawText(TextFormat("PosX: %03.0f", position), (int)position - 50, GetScreenHeight()/2 + 40, 20, BLACK);
DrawText("Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate.", 10, 10, 20, DARKGRAY);
DrawText("PRESS SPACE to PAUSE MOVEMENT", 10, GetScreenHeight() - 60, 20, GRAY);
DrawText("PRESS UP | DOWN to CHANGE TARGET FPS", 10, GetScreenHeight() - 30, 20, GRAY);
DrawText(TextFormat("TARGET FPS: %i", targetFPS), GetScreenWidth() - 220, 10, 20, LIME);
if (deltaTime != 0)
{
DrawText(TextFormat("CURRENT FPS: %i", (int)(1.0f/deltaTime)), GetScreenWidth() - 220, 40, 20, GREEN);
}
EndDrawing();
// NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL,
// Events polling, screen buffer swap and frame time control must be managed by the user
SwapScreenBuffer(); // Flip the back buffer to screen (front buffer)
currentTime = GetTime();
updateDrawTime = currentTime - previousTime;
if (targetFPS > 0) // We want a fixed frame rate
{
waitTime = (1.0f/(float)targetFPS) - updateDrawTime;
if (waitTime > 0.0)
{
WaitTime((float)waitTime);
currentTime = GetTime();
deltaTime = (float)(currentTime - previousTime);
}
}
else deltaTime = (float)updateDrawTime; // Framerate could be variable
previousTime = currentTime;
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,90 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - custom logging
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 2.5, last time updated with raylib 2.5
*
* Example contributed by Pablo Marcos Oltra (@pamarcos) 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 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdio.h> // Required for: printf(), vprintf(), fprintf()
#include <time.h> // Required for: time_t, tm, time(), localtime(), strftime()
// Custom logging function
void CustomTraceLog(int msgType, const char *text, va_list args)
{
char timeStr[64] = { 0 };
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info);
printf("[%s] ", timeStr);
switch (msgType)
{
case LOG_INFO: printf("[INFO] : "); break;
case LOG_ERROR: printf("[ERROR]: "); break;
case LOG_WARNING: printf("[WARN] : "); break;
case LOG_DEBUG: printf("[DEBUG]: "); break;
default: break;
}
vprintf(text, args);
printf("\n");
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// Set custom logger
SetTraceLogCallback(CustomTraceLog);
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");
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);
DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,112 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - delta time
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.5, 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"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - delta time");
int currentFps = 60;
// Store the position for the both of the circles
Vector2 deltaCircle = { 0, (float)screenHeight/3.0f };
Vector2 frameCircle = { 0, (float)screenHeight*(2.0f/3.0f) };
// The speed applied to both circles
const float speed = 10.0f;
const float circleRadius = 32.0f;
SetTargetFPS(currentFps);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Adjust the FPS target based on the mouse wheel
float mouseWheel = GetMouseWheelMove();
if (mouseWheel != 0)
{
currentFps += (int)mouseWheel;
if (currentFps < 0) currentFps = 0;
SetTargetFPS(currentFps);
}
// GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
// Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
// Multiply by 6.0 (an arbitrary value) in order to make the speed
// visually closer to the other circle (at 60 fps), for comparison
deltaCircle.x += GetFrameTime()*6.0f*speed;
// This circle can move faster or slower visually depending on the FPS
frameCircle.x += 0.1f*speed;
// If either circle is off the screen, reset it back to the start
if (deltaCircle.x > screenWidth) deltaCircle.x = 0;
if (frameCircle.x > screenWidth) frameCircle.x = 0;
// Reset both circles positions
if (IsKeyPressed(KEY_R))
{
deltaCircle.x = 0;
frameCircle.x = 0;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw both circles to the screen
DrawCircleV(deltaCircle, circleRadius, RED);
DrawCircleV(frameCircle, circleRadius, BLUE);
// Draw the help text
// Determine what help text to show depending on the current FPS target
const char *fpsText = 0;
if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
DrawText(fpsText, 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
// Draw the text above the circles
DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, RED);
DrawText("FUNC: x += speed", 10, 240, 20, BLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,96 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - directory files
*
* Example complexity rating: [★☆☆☆] 1/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)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
#define MAX_FILEPATH_SIZE 1024
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - directory files");
char directory[MAX_FILEPATH_SIZE] = { 0 };
strcpy(directory, GetWorkingDirectory());
// Load file-paths on current working directory
// NOTE: LoadDirectoryFiles() loads files and directories by default,
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
//FilePathList files = LoadDirectoryFiles(directory);
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
int btnBackPressed = false;
int listScrollIndex = 0;
int listItemActive = -1;
int listItemFocused = -1;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (btnBackPressed)
{
TextCopy(directory, GetPrevDirectoryPath(directory));
UnloadDirectoryFiles(files);
files = LoadDirectoryFiles(directory);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
btnBackPressed = GuiButton((Rectangle){ 40.0f, 10.0f, 48, 28 }, "<");
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
GuiLabel((Rectangle){ 40 + 48 + 10, 10, 700, 28 }, directory);
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
GuiSetStyle(LISTVIEW, TEXT_PADDING, 40);
GuiListViewEx((Rectangle){ 0, 50, (float)GetScreenWidth(), (float)GetScreenHeight() - 50 },
files.paths, files.count, &listScrollIndex, &listItemActive, &listItemFocused);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadDirectoryFiles(files);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,108 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - drop files
*
* Example complexity rating: [★★☆☆] 2/4
*
* NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?)
*
* Example originally created with raylib 1.3, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: calloc(), free()
#define MAX_FILEPATH_RECORDED 4096
#define MAX_FILEPATH_SIZE 2048
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files");
int filePathCounter = 0;
char *filePaths[MAX_FILEPATH_RECORDED] = { 0 }; // We will register a maximum of filepaths
// Allocate space for the required file paths
for (int i = 0; i < MAX_FILEPATH_RECORDED; i++)
{
filePaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_SIZE, 1);
}
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 (IsFileDropped())
{
FilePathList droppedFiles = LoadDroppedFiles();
for (int i = 0, offset = filePathCounter; i < (int)droppedFiles.count; i++)
{
if (filePathCounter < (MAX_FILEPATH_RECORDED - 1))
{
TextCopy(filePaths[offset + i], droppedFiles.paths[i]);
filePathCounter++;
}
}
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (filePathCounter == 0) DrawText("Drop your files to this window!", 100, 40, 20, DARKGRAY);
else
{
DrawText("Dropped files:", 100, 40, 20, DARKGRAY);
for (int i = 0; i < filePathCounter; i++)
{
if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f));
else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f));
DrawText(filePaths[i], 120, 100 + 40*i, 10, GRAY);
}
DrawText("Drop new files...", 100, 110 + 40*filePathCounter, 20, DARKGRAY);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < MAX_FILEPATH_RECORDED; i++)
{
RL_FREE(filePaths[i]); // Free allocated memory for all filepaths
}
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,134 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - highdpi demo
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.0, last time updated with raylib 5.5
*
* Example contributed by Jonathan Marler (@marler8997) 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 Jonathan Marler (@marler8997)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void DrawTextCenter(const char *text, int x, int y, int fontSize, Color color);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi demo");
SetWindowMinSize(450, 450);
int logicalGridDescY = 120;
int logicalGridLabelY = logicalGridDescY + 30;
int logicalGridTop = logicalGridLabelY + 30;
int logicalGridBottom = logicalGridTop + 80;
int pixelGridTop = logicalGridBottom - 20;
int pixelGridBottom = pixelGridTop + 80;
int pixelGridLabelY = pixelGridBottom + 30;
int pixelGridDescY = pixelGridLabelY + 30;
int cellSize = 50;
float cellSizePx = (float)cellSize;
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 monitorCount = GetMonitorCount();
if ((monitorCount > 1) && IsKeyPressed(KEY_N))
{
SetWindowMonitor((GetCurrentMonitor() + 1)%monitorCount);
}
int currentMonitor = GetCurrentMonitor();
Vector2 dpiScale = GetWindowScaleDPI();
cellSizePx = ((float)cellSize)/dpiScale.x;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
int windowCenter = GetScreenWidth()/2;
DrawTextCenter(TextFormat("Dpi Scale: %f", dpiScale.x), windowCenter, 30, 40, DARKGRAY);
DrawTextCenter(TextFormat("Monitor: %d/%d ([N] next monitor)", currentMonitor+1, monitorCount), windowCenter, 70, 20, LIGHTGRAY);
DrawTextCenter(TextFormat("Window is %d \"logical points\" wide", GetScreenWidth()), windowCenter, logicalGridDescY, 20, ORANGE);
bool odd = true;
for (int i = cellSize; i < GetScreenWidth(); i += cellSize, odd = !odd)
{
if (odd) DrawRectangle(i, logicalGridTop, cellSize, logicalGridBottom-logicalGridTop, ORANGE);
DrawTextCenter(TextFormat("%d", i), i, logicalGridLabelY, 10, LIGHTGRAY);
DrawLine(i, logicalGridLabelY + 10, i, logicalGridBottom, GRAY);
}
odd = true;
const int minTextSpace = 30;
int lastTextX = -minTextSpace;
for (int i = cellSize; i < GetRenderWidth(); i += cellSize, odd = !odd)
{
int x = (int)(((float)i)/dpiScale.x);
if (odd) DrawRectangle(x, pixelGridTop, (int)cellSizePx, pixelGridBottom - pixelGridTop, CLITERAL(Color){ 0, 121, 241, 100 });
DrawLine(x, pixelGridTop, (int)(((float)i)/dpiScale.x), pixelGridLabelY - 10, GRAY);
if ((x - lastTextX) >= minTextSpace)
{
DrawTextCenter(TextFormat("%d", i), x, pixelGridLabelY, 10, LIGHTGRAY);
lastTextX = x;
}
}
DrawTextCenter(TextFormat("Window is %d \"physical pixels\" wide", GetRenderWidth()), windowCenter, pixelGridDescY, 20, BLUE);
const char *text = "Can you see this?";
Vector2 size = MeasureTextEx(GetFontDefault(), text, 20, 3);
Vector2 pos = (Vector2){ GetScreenWidth() - size.x - 5, GetScreenHeight() - size.y - 5 };
DrawTextEx(GetFontDefault(), text, pos, 20, 3, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
static void DrawTextCenter(const char *text, int x, int y, int fontSize, Color color)
{
Vector2 size = MeasureTextEx(GetFontDefault(), text, (float)fontSize, 3);
Vector2 pos = (Vector2){ x - size.x/2, y - size.y/2 };
DrawTextEx(GetFontDefault(), text, pos, (float)fontSize, 3, color);
}

View File

@ -1,107 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - highdpi testbed
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Ramon Santamaria (@raysan5) 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 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI);
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
Vector2 scaleDpi = GetWindowScaleDPI();
Vector2 mousePos = GetMousePosition();
int currentMonitor = GetCurrentMonitor();
Vector2 windowPos = GetWindowPosition();
int gridSpacing = 40; // Grid spacing in pixels
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
mousePos = GetMousePosition();
currentMonitor = GetCurrentMonitor();
scaleDpi = GetWindowScaleDPI();
windowPos = GetWindowPosition();
if (IsKeyPressed(KEY_SPACE)) ToggleBorderlessWindowed();
if (IsKeyPressed(KEY_F)) ToggleFullscreen();
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw grid
for (int h = 0; h < GetScreenHeight()/gridSpacing + 1; h++)
{
DrawText(TextFormat("%02i", h*gridSpacing), 4, h*gridSpacing - 4, 10, GRAY);
DrawLine(24, h*gridSpacing, GetScreenWidth(), h*gridSpacing, LIGHTGRAY);
}
for (int v = 0; v < GetScreenWidth()/gridSpacing + 1; v++)
{
DrawText(TextFormat("%02i", v*gridSpacing), v*gridSpacing - 10, 4, 10, GRAY);
DrawLine(v*gridSpacing, 20, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
}
// Draw UI info
DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(),
GetMonitorWidth(currentMonitor), GetMonitorHeight(currentMonitor)), 50, 50, 20, DARKGRAY);
DrawText(TextFormat("WINDOW POSITION: %ix%i", (int)windowPos.x, (int)windowPos.y), 50, 90, 20, DARKGRAY);
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 130, 20, DARKGRAY);
DrawText(TextFormat("RENDER SIZE: %ix%i", GetRenderWidth(), GetRenderHeight()), 50, 170, 20, DARKGRAY);
DrawText(TextFormat("SCALE FACTOR: %.2fx%.2f", scaleDpi.x, scaleDpi.y), 50, 210, 20, GRAY);
// Draw reference rectangles, top-left and bottom-right corners
DrawRectangle(0, 0, 30, 60, RED);
DrawRectangle(GetScreenWidth() - 30, GetScreenHeight() - 60, 30, 60, BLUE);
// Draw mouse position
DrawCircleV(GetMousePosition(), 20, MAROON);
DrawRectangleRec((Rectangle) { mousePos.x - 25, mousePos.y, 50, 2 }, BLACK);
DrawRectangleRec((Rectangle) { mousePos.x, mousePos.y - 25, 2, 50 }, BLACK);
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
(mousePos.y > GetScreenHeight() - 60)? (int)mousePos.y - 46 : (int)mousePos.y + 30, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// TODO: Unload all loaded resources at this point
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,203 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input actions
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6
*
* Example contributed by Jett (@JettMonstersGoBoom) 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 Jett (@JettMonstersGoBoom)
*
********************************************************************************************/
// Simple example for decoding input as actions, allowing remapping of input to different keys or gamepad buttons
// For example instead of using `IsKeyDown(KEY_LEFT)`, you can use `IsActionDown(ACTION_LEFT)`
// which can be reassigned to e.g. KEY_A and also assigned to a gamepad button. the action will trigger with either gamepad or keys
#include "raylib.h"
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum ActionType {
NO_ACTION = 0,
ACTION_UP,
ACTION_DOWN,
ACTION_LEFT,
ACTION_RIGHT,
ACTION_FIRE,
MAX_ACTION
} ActionType;
// Key and button inputs
typedef struct ActionInput {
int key;
int button;
} ActionInput;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static int gamepadIndex = 0; // Gamepad default index
static ActionInput actionInputs[MAX_ACTION] = { 0 };
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static bool IsActionPressed(int action); // Check action key/button pressed
static bool IsActionReleased(int action); // Check action key/button released
static bool IsActionDown(int action); // Check action key/button down
static void SetActionsDefault(void); // Set the "default" keyset
static void SetActionsCursor(void); // Set the "alternate" keyset
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input actions");
// Set default actions
char actionSet = 0;
SetActionsDefault();
bool releaseAction = false;
Vector2 position = (Vector2){ 400.0f, 200.0f };
Vector2 size = (Vector2){ 40.0f, 40.0f };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
gamepadIndex = 0; // Set gamepad being checked
if (IsActionDown(ACTION_UP)) position.y -= 2;
if (IsActionDown(ACTION_DOWN)) position.y += 2;
if (IsActionDown(ACTION_LEFT)) position.x -= 2;
if (IsActionDown(ACTION_RIGHT)) position.x += 2;
if (IsActionPressed(ACTION_FIRE))
{
position.x = (screenWidth-size.x)/2;
position.y = (screenHeight-size.y)/2;
}
// Register release action for one frame
releaseAction = false;
if (IsActionReleased(ACTION_FIRE)) releaseAction = true;
// Switch control scheme by pressing TAB
if (IsKeyPressed(KEY_TAB))
{
actionSet = !actionSet;
if (actionSet == 0) SetActionsDefault();
else SetActionsCursor();
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(GRAY);
DrawRectangleV(position, size, releaseAction? BLUE : RED);
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Arrow keys", 10, 10, 20, WHITE);
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Check action key/button pressed
// NOTE: Combines key pressed and gamepad button pressed in one action
static bool IsActionPressed(int action)
{
bool result = false;
if (action < MAX_ACTION) result = (IsKeyPressed(actionInputs[action].key) || IsGamepadButtonPressed(gamepadIndex, actionInputs[action].button));
return result;
}
// Check action key/button released
// NOTE: Combines key released and gamepad button released in one action
static bool IsActionReleased(int action)
{
bool result = false;
if (action < MAX_ACTION) result = (IsKeyReleased(actionInputs[action].key) || IsGamepadButtonReleased(gamepadIndex, actionInputs[action].button));
return result;
}
// Check action key/button down
// NOTE: Combines key down and gamepad button down in one action
static bool IsActionDown(int action)
{
bool result = false;
if (action < MAX_ACTION) result = (IsKeyDown(actionInputs[action].key) || IsGamepadButtonDown(gamepadIndex, actionInputs[action].button));
return result;
}
// Set the "default" keyset
// NOTE: Here WASD and gamepad buttons on the left side for movement
static void SetActionsDefault(void)
{
actionInputs[ACTION_UP].key = KEY_W;
actionInputs[ACTION_DOWN].key = KEY_S;
actionInputs[ACTION_LEFT].key = KEY_A;
actionInputs[ACTION_RIGHT].key = KEY_D;
actionInputs[ACTION_FIRE].key = KEY_SPACE;
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_LEFT_FACE_UP;
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_LEFT_FACE_LEFT;
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT;
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
}
// Set the "alternate" keyset
// NOTE: Here cursor keys and gamepad buttons on the right side for movement
static void SetActionsCursor(void)
{
actionInputs[ACTION_UP].key = KEY_UP;
actionInputs[ACTION_DOWN].key = KEY_DOWN;
actionInputs[ACTION_LEFT].key = KEY_LEFT;
actionInputs[ACTION_RIGHT].key = KEY_RIGHT;
actionInputs[ACTION_FIRE].key = KEY_SPACE;
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_RIGHT_FACE_UP;
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT;
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT;
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
}

View File

@ -1,291 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input gamepad
*
* Example complexity rating: [★☆☆☆] 1/4
*
* NOTE: This example requires a Gamepad connected to the system
* raylib is configured to work with the following gamepads:
* - Xbox 360 Controller (Xbox 360, Xbox One)
* - PLAYSTATION(R)3 Controller
* Check raylib.h for buttons configuration
*
* Example originally created with raylib 1.1, 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) 2013-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
// NOTE: Gamepad name ID depends on drivers and OS
#define XBOX_ALIAS_1 "xbox"
#define XBOX_ALIAS_2 "x-box"
#define PS_ALIAS_1 "playstation"
#define PS_ALIAS_2 "sony"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gamepad");
Texture2D texPs3Pad = LoadTexture("resources/ps3.png");
Texture2D texXboxPad = LoadTexture("resources/xbox.png");
// Set axis deadzones
const float leftStickDeadzoneX = 0.1f;
const float leftStickDeadzoneY = 0.1f;
const float rightStickDeadzoneX = 0.1f;
const float rightStickDeadzoneY = 0.1f;
const float leftTriggerDeadzone = -0.9f;
const float rightTriggerDeadzone = -0.9f;
Rectangle vibrateButton = { 0 };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
int gamepad = 0; // which gamepad to display
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
Vector2 mousePosition = GetMousePosition();
vibrateButton = (Rectangle){ 10, 70.0f + 20*GetGamepadAxisCount(gamepad) + 20, 75, 24 };
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, vibrateButton)) SetGamepadVibration(gamepad, 1.0, 1.0, 1.0);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (IsGamepadAvailable(gamepad))
{
DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK);
// Get axis values
float leftStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_X);
float leftStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y);
float rightStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X);
float rightStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_Y);
float leftTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER);
float rightTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER);
// Calculate deadzones
if (leftStickX > -leftStickDeadzoneX && leftStickX < leftStickDeadzoneX) leftStickX = 0.0f;
if (leftStickY > -leftStickDeadzoneY && leftStickY < leftStickDeadzoneY) leftStickY = 0.0f;
if (rightStickX > -rightStickDeadzoneX && rightStickX < rightStickDeadzoneX) rightStickX = 0.0f;
if (rightStickY > -rightStickDeadzoneY && rightStickY < rightStickDeadzoneY) rightStickY = 0.0f;
if (leftTrigger < leftTriggerDeadzone) leftTrigger = -1.0f;
if (rightTrigger < rightTriggerDeadzone) rightTrigger = -1.0f;
if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1) ||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1))
{
DrawTexture(texXboxPad, 0, 0, DARKGRAY);
// Draw buttons: xbox home
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(394, 89, 19, RED);
// Draw buttons: basic
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawCircle(436, 150, 9, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawCircle(352, 150, 9, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(501, 151, 15, BLUE);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(536, 187, 15, LIME);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(572, 151, 15, MAROON);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(536, 115, 15, GOLD);
// Draw buttons: d-pad
DrawRectangle(317, 202, 19, 71, BLACK);
DrawRectangle(293, 228, 69, 19, BLACK);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(317, 202, 19, 26, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(292, 228, 25, 19, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED);
// Draw buttons: left-right back
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(259, 61, 20, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(536, 61, 20, RED);
// Draw axis: left joystick
Color leftGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(259, 152, 39, BLACK);
DrawCircle(259, 152, 34, LIGHTGRAY);
DrawCircle(259 + (int)(leftStickX*20), 152 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick
Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(461, 237, 38, BLACK);
DrawCircle(461, 237, 33, LIGHTGRAY);
DrawCircle(461 + (int)(rightStickX*20), 237 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers
DrawRectangle(170, 30, 15, 70, GRAY);
DrawRectangle(604, 30, 15, 70, GRAY);
DrawRectangle(170, 30, 15, (int)(((1 + leftTrigger)/2)*70), RED);
DrawRectangle(604, 30, 15, (int)(((1 + rightTrigger)/2)*70), RED);
//DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK);
//DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK);
}
else if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_1) > -1) ||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_2) > -1))
{
DrawTexture(texPs3Pad, 0, 0, DARKGRAY);
// Draw buttons: ps
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(396, 222, 13, RED);
// Draw buttons: basic
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawRectangle(328, 170, 32, 13, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawTriangle((Vector2){ 436, 168 }, (Vector2){ 436, 185 }, (Vector2){ 464, 177 }, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(557, 144, 13, LIME);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(586, 173, 13, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(557, 203, 13, VIOLET);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(527, 173, 13, PINK);
// Draw buttons: d-pad
DrawRectangle(225, 132, 24, 84, BLACK);
DrawRectangle(195, 161, 84, 25, BLACK);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(225, 132, 24, 29, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(195, 161, 30, 25, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED);
// Draw buttons: left-right back buttons
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(239, 82, 20, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(557, 82, 20, RED);
// Draw axis: left joystick
Color leftGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(319, 255, 35, BLACK);
DrawCircle(319, 255, 31, LIGHTGRAY);
DrawCircle(319 + (int)(leftStickX*20), 255 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick
Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(475, 255, 35, BLACK);
DrawCircle(475, 255, 31, LIGHTGRAY);
DrawCircle(475 + (int)(rightStickX*20), 255 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers
DrawRectangle(169, 48, 15, 70, GRAY);
DrawRectangle(611, 48, 15, 70, GRAY);
DrawRectangle(169, 48, 15, (int)(((1 + leftTrigger)/2)*70), RED);
DrawRectangle(611, 48, 15, (int)(((1 + rightTrigger)/2)*70), RED);
}
else
{
// Draw background: generic
DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 16, DARKGRAY);
// Draw buttons: basic
DrawCircle(365, 170, 12, RAYWHITE);
DrawCircle(405, 170, 12, RAYWHITE);
DrawCircle(445, 170, 12, RAYWHITE);
DrawCircle(516, 191, 17, RAYWHITE);
DrawCircle(551, 227, 17, RAYWHITE);
DrawCircle(587, 191, 17, RAYWHITE);
DrawCircle(551, 155, 17, RAYWHITE);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawCircle(365, 170, 10, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(405, 170, 10, GREEN);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawCircle(445, 170, 10, BLUE);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(516, 191, 15, GOLD);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(551, 227, 15, BLUE);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(587, 191, 15, GREEN);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(551, 155, 15, RED);
// Draw buttons: d-pad
DrawRectangle(245, 145, 28, 88, RAYWHITE);
DrawRectangle(215, 174, 88, 29, RAYWHITE);
DrawRectangle(247, 147, 24, 84, BLACK);
DrawRectangle(217, 176, 84, 25, BLACK);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(247, 147, 24, 29, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(247, 147 + 54, 24, 30, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(217, 176, 30, 25, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(217 + 54, 176, 30, 25, RED);
// Draw buttons: left-right back
DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, DARKGRAY);
DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, DARKGRAY);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, RED);
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, RED);
// Draw axis: left joystick
Color leftGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
DrawCircle(345, 260, 40, BLACK);
DrawCircle(345, 260, 35, LIGHTGRAY);
DrawCircle(345 + (int)(leftStickX*20), 260 + (int)(leftStickY*20), 25, leftGamepadColor);
// Draw axis: right joystick
Color rightGamepadColor = BLACK;
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
DrawCircle(465, 260, 40, BLACK);
DrawCircle(465, 260, 35, LIGHTGRAY);
DrawCircle(465 + (int)(rightStickX*20), 260 + (int)(rightStickY*20), 25, rightGamepadColor);
// Draw axis: left-right triggers
DrawRectangle(151, 110, 15, 70, GRAY);
DrawRectangle(644, 110, 15, 70, GRAY);
DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED);
DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED);
}
DrawText(TextFormat("DETECTED AXIS [%i]:", GetGamepadAxisCount(gamepad)), 10, 50, 10, MAROON);
for (int i = 0; i < GetGamepadAxisCount(gamepad); i++)
{
DrawText(TextFormat("AXIS %i: %.02f", i, GetGamepadAxisMovement(gamepad, i)), 20, 70 + 20*i, 10, DARKGRAY);
}
// Draw vibrate button
DrawRectangleRec(vibrateButton, SKYBLUE);
DrawText("VIBRATE", (int)(vibrateButton.x + 14), (int)(vibrateButton.y + 1), 10, DARKGRAY);
if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
}
else
{
DrawText(TextFormat("GP%d: NOT DETECTED", gamepad), 10, 10, 10, GRAY);
DrawTexture(texXboxPad, 0, 0, LIGHTGRAY);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texPs3Pad);
UnloadTexture(texXboxPad);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,123 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input gestures
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.4, 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) 2016-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define MAX_GESTURE_STRINGS 20
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures");
Vector2 touchPosition = { 0, 0 };
Rectangle touchArea = { 220, 10, screenWidth - 230.0f, screenHeight - 20.0f };
int gesturesCount = 0;
char gestureStrings[MAX_GESTURE_STRINGS][32];
int currentGesture = GESTURE_NONE;
int lastGesture = GESTURE_NONE;
//SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected
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
//----------------------------------------------------------------------------------
lastGesture = currentGesture;
currentGesture = GetGestureDetected();
touchPosition = GetTouchPosition(0);
if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != GESTURE_NONE))
{
if (currentGesture != lastGesture)
{
// Store gesture string
switch (currentGesture)
{
case GESTURE_TAP: TextCopy(gestureStrings[gesturesCount], "GESTURE TAP"); break;
case GESTURE_DOUBLETAP: TextCopy(gestureStrings[gesturesCount], "GESTURE DOUBLETAP"); break;
case GESTURE_HOLD: TextCopy(gestureStrings[gesturesCount], "GESTURE HOLD"); break;
case GESTURE_DRAG: TextCopy(gestureStrings[gesturesCount], "GESTURE DRAG"); break;
case GESTURE_SWIPE_RIGHT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE RIGHT"); break;
case GESTURE_SWIPE_LEFT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE LEFT"); break;
case GESTURE_SWIPE_UP: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE UP"); break;
case GESTURE_SWIPE_DOWN: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE DOWN"); break;
case GESTURE_PINCH_IN: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH IN"); break;
case GESTURE_PINCH_OUT: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH OUT"); break;
default: break;
}
gesturesCount++;
// Reset gestures strings
if (gesturesCount >= MAX_GESTURE_STRINGS)
{
for (int i = 0; i < MAX_GESTURE_STRINGS; i++) TextCopy(gestureStrings[i], "\0");
gesturesCount = 0;
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangleRec(touchArea, GRAY);
DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE);
DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f));
for (int i = 0; i < gesturesCount; i++)
{
if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f));
else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f));
if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY);
else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON);
}
DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY);
DrawText("DETECTED GESTURES", 50, 15, 10, GRAY);
if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,315 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input gestures testbed
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.0, last time updated with raylib 6.0
*
* Example contributed by ubkp (@ubkp) 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) 2023-2025 ubkp (@ubkp)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h> // Required for the protractor angle graphic drawing
#define GESTURE_LOG_SIZE 20
#define MAX_TOUCH_COUNT 32
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static char const *GetGestureName(int gesture); // Get text string for gesture value
static Color GetGestureColor(int gesture); // Get color for gesture value
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures testbed");
Vector2 messagePosition = { 160, 7 };
// Last gesture variables definitions
int lastGesture = 0;
Vector2 lastGesturePosition = { 165, 130 };
// Gesture log variables definitions
// NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
char gestureLog[GESTURE_LOG_SIZE][12] = { "" };
// NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
int gestureLogIndex = GESTURE_LOG_SIZE;
int previousGesture = 0;
// Log mode values:
// - 0 shows repeated events
// - 1 hides repeated events
// - 2 shows repeated events but hide hold events
// - 3 hides repeated events and hide hold events
int logMode = 1;
Color gestureColor = { 0, 0, 0, 255 };
Rectangle logButton1 = { 53, 7, 48, 26 };
Rectangle logButton2 = { 108, 7, 36, 26 };
Vector2 gestureLogPosition = { 10, 10 };
// Protractor variables definitions
float angleLength = 90.0f;
float currentAngleDegrees = 0.0f;
Vector2 finalVector = { 0.0f, 0.0f };
Vector2 protractorPosition = { 266.0f, 315.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
//--------------------------------------------------------------------------------------
// Handle common gestures data
int i, ii; // Iterators that will be reused by all for loops
const int currentGesture = GetGestureDetected();
const float currentDragDegrees = GetGestureDragAngle();
const float currentPitchDegrees = GetGesturePinchAngle();
const int touchCount = GetTouchPointCount();
// Handle last gesture
if ((currentGesture != 0) && (currentGesture != 4) && (currentGesture != previousGesture))
lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
// Handle gesture log
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
if (CheckCollisionPointRec(GetMousePosition(), logButton1))
{
switch (logMode)
{
case 3: logMode = 2; break;
case 2: logMode = 3; break;
case 1: logMode = 0; break;
default: logMode = 1; break;
}
}
else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
{
switch (logMode)
{
case 3: logMode = 1; break;
case 2: logMode = 0; break;
case 1: logMode = 3; break;
default: logMode = 2; break;
}
}
}
int fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
if (currentGesture !=0)
{
if (logMode == 3) // 3 hides repeated events and hide hold events
{
if (((currentGesture != 4) && (currentGesture != previousGesture)) || (currentGesture < 3)) fillLog = 1;
}
else if (logMode == 2) // 2 shows repeated events but hide hold events
{
if (currentGesture != 4) fillLog = 1;
}
else if (logMode == 1) // 1 hides repeated events
{
if (currentGesture != previousGesture) fillLog = 1;
}
else // 0 shows repeated events
{
fillLog = 1;
}
}
if (fillLog) // If one of the conditions from logMode was met, fill the gesture log
{
previousGesture = currentGesture;
gestureColor = GetGestureColor(currentGesture);
if (gestureLogIndex <= 0) gestureLogIndex = GESTURE_LOG_SIZE;
gestureLogIndex--;
// Copy the gesture respective name to the gesture log array
TextCopy(gestureLog[gestureLogIndex], GetGestureName(currentGesture));
}
// Handle protractor
if (currentGesture > 255) currentAngleDegrees = currentPitchDegrees; // Pinch In and Pinch Out
else if (currentGesture > 15) currentAngleDegrees = currentDragDegrees; // Swipe Right, Swipe Left, Swipe Up and Swipe Down
else if (currentGesture > 0) currentAngleDegrees = 0.0f; // Tap, Doubletap, Hold and Grab
float currentAngleRadians = ((currentAngleDegrees + 90.0f)*PI/180); // Convert the current angle to Radians
// Calculate the final vector for display
finalVector = (Vector2){ (angleLength*sinf(currentAngleRadians)) + protractorPosition.x,
(angleLength*cosf(currentAngleRadians)) + protractorPosition.y };
// Handle touch and mouse pointer points
Vector2 touchPosition[MAX_TOUCH_COUNT] = { 0 };
Vector2 mousePosition = { 0 };
if (currentGesture != GESTURE_NONE)
{
if (touchCount != 0)
{
for (i = 0; i < touchCount; i++) touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
}
else mousePosition = GetMousePosition();
}
//--------------------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw common elements
DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 5, 10, BLACK);
DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.x + 15, (int)messagePosition.y + 5, 10, BLACK);
DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 35, 10, BLACK);
DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.", (int)messagePosition.x + 15, (int)messagePosition.y + 35, 10, BLACK);
// Draw last gesture
DrawText("Last gesture", (int)lastGesturePosition.x + 33, (int)lastGesturePosition.y - 47, 20, BLACK);
DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.x + 17, (int)lastGesturePosition.y - 18, 10, BLACK);
DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y, 20, 20, lastGesture == GESTURE_SWIPE_UP ? RED : LIGHTGRAY);
DrawRectangle((int)lastGesturePosition.x, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_LEFT ? RED : LIGHTGRAY);
DrawRectangle((int)lastGesturePosition.x + 40, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_RIGHT ? RED : LIGHTGRAY);
DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y + 40, 20, 20, lastGesture == GESTURE_SWIPE_DOWN ? RED : LIGHTGRAY);
DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 16, 10, lastGesture == GESTURE_TAP ? BLUE : LIGHTGRAY);
DrawRing( (Vector2){lastGesturePosition.x + 103, lastGesturePosition.y + 16}, 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == GESTURE_DRAG ? LIME : LIGHTGRAY);
DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
DrawCircle((int)lastGesturePosition.x + 103, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
DrawTriangle((Vector2){ lastGesturePosition.x + 122, lastGesturePosition.y + 16 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 26 }, (Vector2){lastGesturePosition.x + 137, lastGesturePosition.y + 6 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
DrawTriangle((Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 6 }, (Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 162, lastGesturePosition.y + 16 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
DrawTriangle((Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 33 }, (Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 140, lastGesturePosition.y + 43 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
DrawTriangle((Vector2){ lastGesturePosition.x + 144, lastGesturePosition.y + 43 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 33 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
for (i = 0; i < 4; i++) DrawCircle((int)lastGesturePosition.x + 180, (int)lastGesturePosition.y + 7 + i*15, 5, touchCount <= i? LIGHTGRAY : gestureColor);
// Draw gesture log
DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK);
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1)%GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY));
Color logButton1Color, logButton2Color;
switch (logMode)
{
case 3: logButton1Color=MAROON; logButton2Color=MAROON; break;
case 2: logButton1Color=GRAY; logButton2Color=MAROON; break;
case 1: logButton1Color=MAROON; logButton2Color=GRAY; break;
default: logButton1Color=GRAY; logButton2Color=GRAY; break;
}
DrawRectangleRec(logButton1, logButton1Color);
DrawText("Hide", (int)logButton1.x + 7, (int)logButton1.y + 3, 10, WHITE);
DrawText("Repeat", (int)logButton1.x + 7, (int)logButton1.y + 13, 10, WHITE);
DrawRectangleRec(logButton2, logButton2Color);
DrawText("Hide", (int)logButton1.x + 62, (int)logButton1.y + 3, 10, WHITE);
DrawText("Hold", (int)logButton1.x + 62, (int)logButton1.y + 13, 10, WHITE);
// Draw protractor
DrawText("Angle", (int)protractorPosition.x + 55, (int)protractorPosition.y + 76, 10, BLACK);
const char *angleString = TextFormat("%f", currentAngleDegrees);
const int angleStringDot = TextFindIndex(angleString, ".");
const char *angleStringTrim = TextSubtext(angleString, 0, angleStringDot + 3);
DrawText( angleStringTrim, (int)protractorPosition.x + 55, (int)protractorPosition.y + 92, 20, gestureColor);
DrawCircleV(protractorPosition, 80.0f, WHITE);
DrawLineEx((Vector2){ protractorPosition.x - 90, protractorPosition.y }, (Vector2){ protractorPosition.x + 90, protractorPosition.y }, 3.0f, LIGHTGRAY);
DrawLineEx((Vector2){ protractorPosition.x, protractorPosition.y - 90 }, (Vector2){ protractorPosition.x, protractorPosition.y + 90 }, 3.0f, LIGHTGRAY);
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y - 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y + 45 }, 3.0f, GREEN);
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y + 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y - 45 }, 3.0f, GREEN);
DrawText("0", (int)protractorPosition.x + 96, (int)protractorPosition.y - 9, 20, BLACK);
DrawText("30", (int)protractorPosition.x + 74, (int)protractorPosition.y - 68, 20, BLACK);
DrawText("90", (int)protractorPosition.x - 11, (int)protractorPosition.y - 110, 20, BLACK);
DrawText("150", (int)protractorPosition.x - 100, (int)protractorPosition.y - 68, 20, BLACK);
DrawText("180", (int)protractorPosition.x - 124, (int)protractorPosition.y - 9, 20, BLACK);
DrawText("210", (int)protractorPosition.x - 100, (int)protractorPosition.y + 50, 20, BLACK);
DrawText("270", (int)protractorPosition.x - 18, (int)protractorPosition.y + 92, 20, BLACK);
DrawText("330", (int)protractorPosition.x + 72, (int)protractorPosition.y + 50, 20, BLACK);
if (currentAngleDegrees != 0.0f) DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
// Draw touch and mouse pointer points
if (currentGesture != GESTURE_NONE)
{
if ( touchCount != 0 )
{
for (i = 0; i < touchCount; i++)
{
DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
DrawCircleV(touchPosition[i], 5.0f, gestureColor);
}
if (touchCount == 2) DrawLineEx(touchPosition[0], touchPosition[1], ((currentGesture == 512)? 8.0f : 12.0f), gestureColor);
}
else
{
DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
DrawCircleV(mousePosition, 5.0f, gestureColor);
}
}
EndDrawing();
//--------------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Get text string for gesture value
static char const *GetGestureName(int gesture)
{
switch (gesture)
{
case 0: return "None"; break;
case 1: return "Tap"; break;
case 2: return "Double Tap"; break;
case 4: return "Hold"; break;
case 8: return "Drag"; break;
case 16: return "Swipe Right"; break;
case 32: return "Swipe Left"; break;
case 64: return "Swipe Up"; break;
case 128: return "Swipe Down"; break;
case 256: return "Pinch In"; break;
case 512: return "Pinch Out"; break;
default: return "Unknown"; break;
}
}
// Get color for gesture value
static Color GetGestureColor(int gesture)
{
switch (gesture)
{
case 0: return BLACK; break;
case 1: return BLUE; break;
case 2: return SKYBLUE; break;
case 4: return BLACK; break;
case 8: return LIME; break;
case 16: return RED; break;
case 32: return RED; break;
case 64: return RED; break;
case 128: return RED; break;
case 256: return VIOLET; break;
case 512: return ORANGE; break;
default: return BLACK; break;
}
}

View File

@ -1,66 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input keys
*
* 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 [core] example - input keys");
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
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 (IsKeyDown(KEY_RIGHT)) ballPosition.x += 2.0f;
if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 2.0f;
if (IsKeyDown(KEY_UP)) ballPosition.y -= 2.0f;
if (IsKeyDown(KEY_DOWN)) ballPosition.y += 2.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("move the ball with arrow keys", 10, 10, 20, DARKGRAY);
DrawCircleV(ballPosition, 50, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,82 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input mouse
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.0, last time updated with raylib 5.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"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse");
Vector2 ballPosition = { -100.0f, -100.0f };
Color ballColor = DARKBLUE;
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_H))
{
if (IsCursorHidden()) ShowCursor();
else HideCursor();
}
ballPosition = GetMousePosition();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) ballColor = MAROON;
else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) ballColor = LIME;
else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) ballColor = DARKBLUE;
else if (IsMouseButtonPressed(MOUSE_BUTTON_SIDE)) ballColor = PURPLE;
else if (IsMouseButtonPressed(MOUSE_BUTTON_EXTRA)) ballColor = YELLOW;
else if (IsMouseButtonPressed(MOUSE_BUTTON_FORWARD)) ballColor = ORANGE;
else if (IsMouseButtonPressed(MOUSE_BUTTON_BACK)) ballColor = BEIGE;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawCircleV(ballPosition, 40, ballColor);
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY);
DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY);
if (IsCursorHidden()) DrawText("CURSOR HIDDEN", 20, 60, 20, RED);
else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,65 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input mouse wheel
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.1, last time updated with raylib 1.3
*
* 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 [core] example - input mouse wheel");
int boxPositionY = screenHeight/2 - 40;
int scrollSpeed = 4; // Scrolling speed in pixels
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
//----------------------------------------------------------------------------------
boxPositionY -= (int)(GetMouseWheelMove()*scrollSpeed);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangle(screenWidth/2 - 40, boxPositionY, 80, 80, MAROON);
DrawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, GRAY);
DrawText(TextFormat("Box position Y: %03i", boxPositionY), 10, 40, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,81 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input multitouch
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 2.1, last time updated with raylib 2.5
*
* Example contributed by Berni (@Berni8k) 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 Berni (@Berni8k) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define MAX_TOUCH_POINTS 10
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input multitouch");
Vector2 touchPositions[MAX_TOUCH_POINTS] = { 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
//----------------------------------------------------------------------------------
// Get the touch point count ( how many fingers are touching the screen )
int tCount = GetTouchPointCount();
// Clamp touch points available ( set the maximum touch points allowed )
if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS;
// Get touch points positions
for (int i = 0; i < tCount; i++) touchPositions[i] = GetTouchPosition(i);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < tCount; i++)
{
// Make sure point is not (0, 0) as this means there is no touch for it
if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0))
{
// Draw circle and touch index number
DrawCircleV(touchPositions[i], 34, ORANGE);
DrawText(TextFormat("%d", i), (int)touchPositions[i].x - 10, (int)touchPositions[i].y - 70, 40, BLACK);
}
}
DrawText("touch the screen at multiple locations to get multiple balls", 10, 10, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,171 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - input virtual controls
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example contributed by GreenSnakeLinux (@GreenSnakeLinux),
* reviewed by Ramon Santamaria (@raysan5), oblerion (@oblerion) and danilwhale (@danilwhale)
*
* 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 GreenSnakeLinux (@GreenSnakeLinux) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
typedef enum {
BUTTON_NONE = -1,
BUTTON_UP,
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_DOWN,
BUTTON_MAX
} PadButton;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - input virtual controls");
Vector2 padPosition = { 100, 350 };
float buttonRadius = 30;
Vector2 buttonPositions[BUTTON_MAX] = {
{ padPosition.x,padPosition.y - buttonRadius*1.5f }, // Up
{ padPosition.x - buttonRadius*1.5f, padPosition.y }, // Left
{ padPosition.x + buttonRadius*1.5f, padPosition.y }, // Right
{ padPosition.x, padPosition.y + buttonRadius*1.5f } // Down
};
Vector2 arrowTris[4][3] = {
// Up
{
{ buttonPositions[0].x, buttonPositions[0].y - 12 },
{ buttonPositions[0].x - 9, buttonPositions[0].y + 9 },
{ buttonPositions[0].x + 9, buttonPositions[0].y + 9 }
},
// Left
{
{ buttonPositions[1].x + 9, buttonPositions[1].y - 9 },
{ buttonPositions[1].x - 12, buttonPositions[1].y },
{ buttonPositions[1].x + 9, buttonPositions[1].y + 9 }
},
// Right
{
{ buttonPositions[2].x + 12, buttonPositions[2].y },
{ buttonPositions[2].x - 9, buttonPositions[2].y - 9 },
{ buttonPositions[2].x - 9, buttonPositions[2].y + 9 }
},
// Down
{
{ buttonPositions[3].x - 9, buttonPositions[3].y - 9 },
{ buttonPositions[3].x, buttonPositions[3].y + 12 },
{ buttonPositions[3].x + 9, buttonPositions[3].y - 9 }
}
};
Color buttonLabelColors[BUTTON_MAX] = {
YELLOW, // Up
BLUE, // Left
RED, // Right
GREEN // Down
};
int pressedButton = BUTTON_NONE;
Vector2 inputPosition = { 0, 0 };
Vector2 playerPosition = { (float)screenWidth/2, (float)screenHeight/2 };
float playerSpeed = 75;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//--------------------------------------------------------------------------
if ((GetTouchPointCount() > 0)) inputPosition = GetTouchPosition(0); // Use touch position
else inputPosition = GetMousePosition(); // Use mouse position
// Reset pressed button to none
pressedButton = BUTTON_NONE;
// Make sure user is pressing left mouse button if they're from desktop
if ((GetTouchPointCount() > 0) ||
((GetTouchPointCount() == 0) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)))
{
// Find nearest D-Pad button to the input position
for (int i = 0; i < BUTTON_MAX; i++)
{
float distX = fabsf(buttonPositions[i].x - inputPosition.x);
float distY = fabsf(buttonPositions[i].y - inputPosition.y);
if ((distX + distY < buttonRadius))
{
pressedButton = i;
break;
}
}
}
// Move player according to pressed button
switch (pressedButton)
{
case BUTTON_UP: playerPosition.y -= playerSpeed*GetFrameTime(); break;
case BUTTON_LEFT: playerPosition.x -= playerSpeed*GetFrameTime(); break;
case BUTTON_RIGHT: playerPosition.x += playerSpeed*GetFrameTime(); break;
case BUTTON_DOWN: playerPosition.y += playerSpeed*GetFrameTime(); break;
default: break;
};
//--------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw world
DrawCircleV(playerPosition, 50, MAROON);
// Draw GUI
for (int i = 0; i < BUTTON_MAX; i++)
{
DrawCircleV(buttonPositions[i], buttonRadius, (i == pressedButton)? DARKGRAY : BLACK);
DrawTriangle(
arrowTris[i][0],
arrowTris[i][1],
arrowTris[i][2],
buttonLabelColors[i]
);
}
DrawText("move the player with D-Pad buttons", 10, 10, 20, DARKGRAY);
EndDrawing();
//--------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,333 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - keyboard testbed
*
* Example complexity rating: [★★☆☆] 2/4
*
* NOTE: raylib defined keys refer to ENG-US Keyboard layout,
* mapping to other layouts is up to the user
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* 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) 2026 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define KEY_REC_SPACING 4 // Space in pixels between key rectangles
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static const char *GetKeyText(int key);
static void GuiKeyboardKey(Rectangle bounds, int key);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard testbed");
SetExitKey(KEY_NULL); // Avoid exit on KEY_ESCAPE
// Keyboard line 01
int line01KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line01KeyWidths[i] = 45;
line01KeyWidths[13] = 62; // PRINTSCREEN
int line01Keys[15] = {
KEY_ESCAPE, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
KEY_F12, KEY_PRINT_SCREEN, KEY_PAUSE
};
// Keyboard line 02
int line02KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line02KeyWidths[i] = 45;
line02KeyWidths[0] = 25; // GRAVE
line02KeyWidths[13] = 82; // BACKSPACE
int line02Keys[15] = {
KEY_GRAVE, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR,
KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, KEY_NINE,
KEY_ZERO, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_DELETE };
// Keyboard line 03
int line03KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line03KeyWidths[i] = 45;
line03KeyWidths[0] = 50; // TAB
line03KeyWidths[13] = 57; // BACKSLASH
int line03Keys[15] = {
KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y,
KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET, KEY_BACKSLASH, KEY_INSERT
};
// Keyboard line 04
int line04KeyWidths[14] = { 0 };
for (int i = 0; i < 14; i++) line04KeyWidths[i] = 45;
line04KeyWidths[0] = 68; // CAPS
line04KeyWidths[12] = 88; // ENTER
int line04Keys[14] = {
KEY_CAPS_LOCK, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G,
KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
KEY_APOSTROPHE, KEY_ENTER, KEY_PAGE_UP
};
// Keyboard line 05
int line05KeyWidths[14] = { 0 };
for (int i = 0; i < 14; i++) line05KeyWidths[i] = 45;
line05KeyWidths[0] = 80; // LSHIFT
line05KeyWidths[11] = 76; // RSHIFT
int line05Keys[14] = {
KEY_LEFT_SHIFT, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B,
KEY_N, KEY_M, KEY_COMMA, KEY_PERIOD, /*KEY_MINUS*/
KEY_SLASH, KEY_RIGHT_SHIFT, KEY_UP, KEY_PAGE_DOWN
};
// Keyboard line 06
int line06KeyWidths[11] = { 0 };
for (int i = 0; i < 11; i++) line06KeyWidths[i] = 45;
line06KeyWidths[0] = 80; // LCTRL
line06KeyWidths[3] = 208; // SPACE
line06KeyWidths[7] = 60; // RCTRL
int line06Keys[11] = {
KEY_LEFT_CONTROL, KEY_LEFT_SUPER, KEY_LEFT_ALT,
KEY_SPACE, KEY_RIGHT_ALT, 162, KEY_NULL,
KEY_RIGHT_CONTROL, KEY_LEFT, KEY_DOWN, KEY_RIGHT
};
Vector2 keyboardOffset = { 26, 80 };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
int key = GetKeyPressed(); // Get pressed keycode
if (key > 0) TraceLog(LOG_INFO, "KEYBOARD TESTBED: KEY PRESSED: %d", key);
int ch = GetCharPressed(); // Get pressed char for text input, using OS mapping
if (ch > 0) TraceLog(LOG_INFO, "KEYBOARD TESTBED: CHAR PRESSED: %c (%d)", ch, ch);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("KEYBOARD LAYOUT: ENG-US", 26, 38, 20, LIGHTGRAY);
// Keyboard line 01 - 15 keys
// ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, IMP, CLOSE
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y, (float)line01KeyWidths[i], 30.0f }, line01Keys[i]);
recOffsetX += line01KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 02 - 15 keys
// `, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -, =, BACKSPACE, DEL
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + KEY_REC_SPACING, (float)line02KeyWidths[i], 38.0f }, line02Keys[i]);
recOffsetX += line02KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 03 - 15 keys
// TAB, Q, W, E, R, T, Y, U, I, O, P, [, ], \, INS
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38 + KEY_REC_SPACING*2, (float)line03KeyWidths[i], 38.0f }, line03Keys[i]);
recOffsetX += line03KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 04 - 14 keys
// MAYUS, A, S, D, F, G, H, J, K, L, ;, ', ENTER, REPAG
for (int i = 0, recOffsetX = 0; i < 14; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*2 + KEY_REC_SPACING*3, (float)line04KeyWidths[i], 38.0f }, line04Keys[i]);
recOffsetX += line04KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 05 - 14 keys
// LSHIFT, Z, X, C, V, B, N, M, ,, ., /, RSHIFT, UP, AVPAG
for (int i = 0, recOffsetX = 0; i < 14; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*3 + KEY_REC_SPACING*4, (float)line05KeyWidths[i], 38.0f }, line05Keys[i]);
recOffsetX += line05KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 06 - 11 keys
// LCTRL, WIN, LALT, SPACE, ALTGR, \, FN, RCTRL, LEFT, DOWN, RIGHT
for (int i = 0, recOffsetX = 0; i < 11; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*4 + KEY_REC_SPACING*5, (float)line06KeyWidths[i], 38.0f }, line06Keys[i]);
recOffsetX += line06KeyWidths[i] + KEY_REC_SPACING;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Get keyboard keycode as text (US keyboard)
// NOTE: Mapping for other keyboard layouts can be done here
static const char *GetKeyText(int key)
{
switch (key)
{
case KEY_APOSTROPHE : return "'"; // Key: '
case KEY_COMMA : return ","; // Key: ,
case KEY_MINUS : return "-"; // Key: -
case KEY_PERIOD : return "."; // Key: .
case KEY_SLASH : return "/"; // Key: /
case KEY_ZERO : return "0"; // Key: 0
case KEY_ONE : return "1"; // Key: 1
case KEY_TWO : return "2"; // Key: 2
case KEY_THREE : return "3"; // Key: 3
case KEY_FOUR : return "4"; // Key: 4
case KEY_FIVE : return "5"; // Key: 5
case KEY_SIX : return "6"; // Key: 6
case KEY_SEVEN : return "7"; // Key: 7
case KEY_EIGHT : return "8"; // Key: 8
case KEY_NINE : return "9"; // Key: 9
case KEY_SEMICOLON : return ";"; // Key: ;
case KEY_EQUAL : return "="; // Key: =
case KEY_A : return "A"; // Key: A | a
case KEY_B : return "B"; // Key: B | b
case KEY_C : return "C"; // Key: C | c
case KEY_D : return "D"; // Key: D | d
case KEY_E : return "E"; // Key: E | e
case KEY_F : return "F"; // Key: F | f
case KEY_G : return "G"; // Key: G | g
case KEY_H : return "H"; // Key: H | h
case KEY_I : return "I"; // Key: I | i
case KEY_J : return "J"; // Key: J | j
case KEY_K : return "K"; // Key: K | k
case KEY_L : return "L"; // Key: L | l
case KEY_M : return "M"; // Key: M | m
case KEY_N : return "N"; // Key: N | n
case KEY_O : return "O"; // Key: O | o
case KEY_P : return "P"; // Key: P | p
case KEY_Q : return "Q"; // Key: Q | q
case KEY_R : return "R"; // Key: R | r
case KEY_S : return "S"; // Key: S | s
case KEY_T : return "T"; // Key: T | t
case KEY_U : return "U"; // Key: U | u
case KEY_V : return "V"; // Key: V | v
case KEY_W : return "W"; // Key: W | w
case KEY_X : return "X"; // Key: X | x
case KEY_Y : return "Y"; // Key: Y | y
case KEY_Z : return "Z"; // Key: Z | z
case KEY_LEFT_BRACKET : return "["; // Key: [
case KEY_BACKSLASH : return "\\"; // Key: '\'
case KEY_RIGHT_BRACKET : return "]"; // Key: ]
case KEY_GRAVE : return "`"; // Key: `
case KEY_SPACE : return "SPACE"; // Key: Space
case KEY_ESCAPE : return "ESC"; // Key: Esc
case KEY_ENTER : return "ENTER"; // Key: Enter
case KEY_TAB : return "TAB"; // Key: Tab
case KEY_BACKSPACE : return "BACK"; // Key: Backspace
case KEY_INSERT : return "INS"; // Key: Ins
case KEY_DELETE : return "DEL"; // Key: Del
case KEY_RIGHT : return "RIGHT"; // Key: Cursor right
case KEY_LEFT : return "LEFT"; // Key: Cursor left
case KEY_DOWN : return "DOWN"; // Key: Cursor down
case KEY_UP : return "UP"; // Key: Cursor up
case KEY_PAGE_UP : return "PGUP"; // Key: Page up
case KEY_PAGE_DOWN : return "PGDOWN"; // Key: Page down
case KEY_HOME : return "HOME"; // Key: Home
case KEY_END : return "END"; // Key: End
case KEY_CAPS_LOCK : return "CAPS"; // Key: Caps lock
case KEY_SCROLL_LOCK : return "LOCK"; // Key: Scroll down
case KEY_NUM_LOCK : return "NUMLOCK"; // Key: Num lock
case KEY_PRINT_SCREEN : return "PRINTSCR"; // Key: Print screen
case KEY_PAUSE : return "PAUSE"; // Key: Pause
case KEY_F1 : return "F1"; // Key: F1
case KEY_F2 : return "F2"; // Key: F2
case KEY_F3 : return "F3"; // Key: F3
case KEY_F4 : return "F4"; // Key: F4
case KEY_F5 : return "F5"; // Key: F5
case KEY_F6 : return "F6"; // Key: F6
case KEY_F7 : return "F7"; // Key: F7
case KEY_F8 : return "F8"; // Key: F8
case KEY_F9 : return "F9"; // Key: F9
case KEY_F10 : return "F10"; // Key: F10
case KEY_F11 : return "F11"; // Key: F11
case KEY_F12 : return "F12"; // Key: F12
case KEY_LEFT_SHIFT : return "LSHIFT"; // Key: Shift left
case KEY_LEFT_CONTROL : return "LCTRL"; // Key: Control left
case KEY_LEFT_ALT : return "LALT"; // Key: Alt left
case KEY_LEFT_SUPER : return "WIN"; // Key: Super left
case KEY_RIGHT_SHIFT : return "RSHIFT"; // Key: Shift right
case KEY_RIGHT_CONTROL : return "RCTRL"; // Key: Control right
case KEY_RIGHT_ALT : return "ALTGR"; // Key: Alt right
case KEY_RIGHT_SUPER : return "RSUPER"; // Key: Super right
case KEY_KB_MENU : return "KBMENU"; // Key: KB menu
case KEY_KP_0 : return "KP0"; // Key: Keypad 0
case KEY_KP_1 : return "KP1"; // Key: Keypad 1
case KEY_KP_2 : return "KP2"; // Key: Keypad 2
case KEY_KP_3 : return "KP3"; // Key: Keypad 3
case KEY_KP_4 : return "KP4"; // Key: Keypad 4
case KEY_KP_5 : return "KP5"; // Key: Keypad 5
case KEY_KP_6 : return "KP6"; // Key: Keypad 6
case KEY_KP_7 : return "KP7"; // Key: Keypad 7
case KEY_KP_8 : return "KP8"; // Key: Keypad 8
case KEY_KP_9 : return "KP9"; // Key: Keypad 9
case KEY_KP_DECIMAL : return "KPDEC"; // Key: Keypad .
case KEY_KP_DIVIDE : return "KPDIV"; // Key: Keypad /
case KEY_KP_MULTIPLY : return "KPMUL"; // Key: Keypad *
case KEY_KP_SUBTRACT : return "KPSUB"; // Key: Keypad -
case KEY_KP_ADD : return "KPADD"; // Key: Keypad +
case KEY_KP_ENTER : return "KPENTER"; // Key: Keypad Enter
case KEY_KP_EQUAL : return "KPEQU"; // Key: Keypad =
default: return "";
}
}
// Draw keyboard key
static void GuiKeyboardKey(Rectangle bounds, int key)
{
if (key == KEY_NULL) DrawRectangleLinesEx(bounds, 2.0f, LIGHTGRAY);
else
{
if (IsKeyDown(key))
{
DrawRectangleLinesEx(bounds, 2.0f, MAROON);
DrawText(GetKeyText(key), (int)(bounds.x + 4), (int)(bounds.y + 4), 10, MAROON);
}
else
{
DrawRectangleLinesEx(bounds, 2.0f, DARKGRAY);
DrawText(GetKeyText(key), (int)(bounds.x + 4), (int)(bounds.y + 4), 10, DARKGRAY);
}
}
if (CheckCollisionPointRec(GetMousePosition(), bounds))
{
DrawRectangleRec(bounds, Fade(RED, 0.2f));
DrawRectangleLinesEx(bounds, 3.0f, RED);
}
}

View File

@ -1,160 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - monitor detector
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6
*
* Example contributed by Maicon Santana (@maiconpintoabreu) 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 Maicon Santana (@maiconpintoabreu)
*
********************************************************************************************/
#include "raylib.h"
#define MAX_MONITORS 10
// Monitor info
typedef struct MonitorInfo {
Vector2 position;
const char *name;
int width;
int height;
int physicalWidth;
int physicalHeight;
int refreshRate;
} MonitorInfo;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector");
MonitorInfo monitors[MAX_MONITORS] = { 0 };
int currentMonitorIndex = GetCurrentMonitor();
int monitorCount = 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
//----------------------------------------------------------------------------------
// Variables to find the max x and Y to calculate the scale
int maxWidth = 1;
int maxHeight = 1;
// Monitor offset is to fix when monitor position x is negative
int monitorOffsetX = 0;
// Rebuild monitors array every frame
monitorCount = GetMonitorCount();
for (int i = 0; i < monitorCount; i++)
{
monitors[i] = (MonitorInfo){
GetMonitorPosition(i),
GetMonitorName(i),
GetMonitorWidth(i),
GetMonitorHeight(i),
GetMonitorPhysicalWidth(i),
GetMonitorPhysicalHeight(i),
GetMonitorRefreshRate(i)
};
if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = -(int)monitors[i].position.x;
const int width = (int)monitors[i].position.x + monitors[i].width;
const int height = (int)monitors[i].position.y + monitors[i].height;
if (maxWidth < width) maxWidth = width;
if (maxHeight < height) maxHeight = height;
}
if (IsKeyPressed(KEY_ENTER) && (monitorCount > 1))
{
currentMonitorIndex += 1;
// Set index to 0 if the last one
if (currentMonitorIndex == monitorCount) currentMonitorIndex = 0;
SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
}
else currentMonitorIndex = GetCurrentMonitor(); // Get currentMonitorIndex if manually moved
float monitorScale = 0.6f;
if (maxHeight > (maxWidth + monitorOffsetX)) monitorScale *= ((float)screenHeight/(float)maxHeight);
else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX));
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Press [Enter] to move window to next monitor available", 20, 20, 20, DARKGRAY);
DrawRectangleLines(20, 60, screenWidth - 40, screenHeight - 100, DARKGRAY);
// Draw Monitor Rectangles with information inside
for (int i = 0; i < monitorCount; i++)
{
// Calculate retangle position and size using monitorScale
const Rectangle rec = (Rectangle){
(monitors[i].position.x + monitorOffsetX)*monitorScale + 140,
monitors[i].position.y*monitorScale + 80,
monitors[i].width*monitorScale,
monitors[i].height*monitorScale
};
// Draw monitor name and information inside the rectangle
DrawText(TextFormat("[%i] %s", i, monitors[i].name), (int)rec.x + 10, (int)rec.y + (int)(100*monitorScale), (int)(120*monitorScale), BLUE);
DrawText(
TextFormat("Resolution: [%ipx x %ipx]\nRefreshRate: [%ihz]\nPhysical Size: [%imm x %imm]\nPosition: %3.0f x %3.0f",
monitors[i].width,
monitors[i].height,
monitors[i].refreshRate,
monitors[i].physicalWidth,
monitors[i].physicalHeight,
monitors[i].position.x,
monitors[i].position.y
), (int)rec.x + 10, (int)rec.y + (int)(200*monitorScale), (int)(120*monitorScale), DARKGRAY);
// Highlight current monitor
if (i == currentMonitorIndex)
{
DrawRectangleLinesEx(rec, 5, RED);
Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 };
// Draw window position based on monitors
DrawRectangleV(windowPosition, (Vector2){screenWidth*monitorScale, screenHeight*monitorScale}, Fade(GREEN, 0.5));
}
else DrawRectangleLinesEx(rec, 5, GRAY);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,177 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - random sequence
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example contributed by Dalton Overmyer (@REDl3east) 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) 2023-2025 Dalton Overmyer (@REDl3east)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <stdlib.h> // Required for: malloc(), free()
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct ColorRect {
Color color;
Rectangle rect;
} ColorRect;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static Color GenerateRandomColor(void);
static ColorRect *GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight);
static void ShuffleColorRectSequence(ColorRect *rectangles, int rectCount);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - random sequence");
int rectCount = 20;
float rectSize = (float)screenWidth/rectCount;
ColorRect *rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE)) ShuffleColorRectSequence(rectangles, rectCount);
if (IsKeyPressed(KEY_UP))
{
rectCount++;
rectSize = (float)screenWidth/rectCount;
RL_FREE(rectangles);
// Re-generate random sequence with new count
rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight);
}
if (IsKeyPressed(KEY_DOWN))
{
if (rectCount >= 4)
{
rectCount--;
rectSize = (float)screenWidth/rectCount;
RL_FREE(rectangles);
// Re-generate random sequence with new count
rectangles = GenerateRandomColorRectSequence((float)rectCount, rectSize, (float)screenWidth, 0.75f*screenHeight);
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < rectCount; i++)
{
DrawRectangleRec(rectangles[i].rect, rectangles[i].color);
DrawText("Press SPACE to shuffle the current sequence", 10, screenHeight - 96, 20, BLACK);
DrawText("Press UP to add a rectangle and generate a new sequence", 10, screenHeight - 64, 20, BLACK);
DrawText("Press DOWN to remove a rectangle and generate a new sequence", 10, screenHeight - 32, 20, BLACK);
}
DrawText(TextFormat("Count: %d rectangles", rectCount), 10, 10, 20, MAROON);
DrawFPS(screenWidth - 80, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(rectangles);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
static Color GenerateRandomColor(void)
{
Color color = {
GetRandomValue(0, 255),
GetRandomValue(0, 255),
GetRandomValue(0, 255),
255
};
return color;
}
static ColorRect *GenerateRandomColorRectSequence(float rectCount, float rectWidth, float screenWidth, float screenHeight)
{
ColorRect *rectangles = (ColorRect *)RL_CALLOC((int)rectCount, sizeof(ColorRect));
int *seq = LoadRandomSequence((unsigned int)rectCount, 0, (unsigned int)rectCount - 1);
float rectSeqWidth = rectCount*rectWidth;
float startX = (screenWidth - rectSeqWidth)*0.5f;
for (int i = 0; i < rectCount; i++)
{
int rectHeight = (int)Remap((float)seq[i], 0, rectCount - 1, 0, screenHeight);
rectangles[i].color = GenerateRandomColor();
rectangles[i].rect = CLITERAL(Rectangle){ startX + i*rectWidth, screenHeight - rectHeight, rectWidth, (float)rectHeight };
}
UnloadRandomSequence(seq);
return rectangles;
}
static void ShuffleColorRectSequence(ColorRect *rectangles, int rectCount)
{
int *seq = LoadRandomSequence(rectCount, 0, rectCount - 1);
for (int i1 = 0; i1 < rectCount; i1++)
{
ColorRect *r1 = &rectangles[i1];
ColorRect *r2 = &rectangles[seq[i1]];
// Swap only the color and height
ColorRect tmp = *r1;
r1->color = r2->color;
r1->rect.height = r2->rect.height;
r1->rect.y = r2->rect.y;
r2->color = tmp.color;
r2->rect.height = tmp.rect.height;
r2->rect.y = tmp.rect.y;
}
UnloadRandomSequence(seq);
}

View File

@ -1,74 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - random values
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.1, last time updated with raylib 1.1
*
* 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 [core] example - random values");
// SetRandomSeed(0xaabbccff); // Set a custom random seed if desired, by default: "time(NULL)"
int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included)
unsigned int framesCounter = 0; // Variable used to count frames
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
//----------------------------------------------------------------------------------
framesCounter++;
// Every two seconds (120 frames) a new random value is generated
if (((framesCounter/120)%2) == 1)
{
randValue = GetRandomValue(-8, 5);
framesCounter = 0;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Every 2 seconds a new random value is generated:", 130, 100, 20, MAROON);
DrawText(TextFormat("%i", randValue), 360, 180, 80, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,101 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - render texture
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.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) 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 [core] example - render texture");
// Define a render texture to render
int renderTextureWidth = 300;
int renderTextureHeight = 300;
RenderTexture2D target = LoadRenderTexture(renderTextureWidth, renderTextureHeight);
Vector2 ballPosition = { renderTextureWidth/2.0f, renderTextureHeight/2.0f };
Vector2 ballSpeed = { 5.0f, 4.0f };
int ballRadius = 20;
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
//-----------------------------------------------------
// Ball movement logic
ballPosition.x += ballSpeed.x;
ballPosition.y += ballSpeed.y;
// Check walls collision for bouncing
if ((ballPosition.x >= (renderTextureWidth - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f;
if ((ballPosition.y >= (renderTextureHeight - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -1.0f;
// Render texture rotation
rotation += 0.5f;
//-----------------------------------------------------
// Draw
//-----------------------------------------------------
// Draw our scene to the render texture
BeginTextureMode(target);
ClearBackground(SKYBLUE);
DrawRectangle(0, 0, 20, 20, RED);
DrawCircleV(ballPosition, (float)ballRadius, MAROON);
EndTextureMode();
// Draw render texture to main framebuffer
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw our render texture with rotation applied
// NOTE 1: We set the origin of the texture to the center of the render texture
// NOTE 2: We flip vertically the texture setting negative source rectangle height
DrawTexturePro(target.texture,
(Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height },
(Rectangle){ screenWidth/2.0f, screenHeight/2.0f, (float)target.texture.width, (float)target.texture.height },
(Vector2){ target.texture.width/2.0f, target.texture.height/2.0f }, rotation, WHITE);
DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, BLACK);
DrawFPS(10, 10);
EndDrawing();
//-----------------------------------------------------
}
// De-Initialization
//---------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------
return 0;
}

View File

@ -1,78 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - scissor test
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 2.5, last time updated with raylib 3.0
*
* Example contributed by Chris Dill (@MysteriousSpace) 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 Chris Dill (@MysteriousSpace)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - scissor test");
Rectangle scissorArea = { 0, 0, 300, 300 };
bool scissorMode = 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
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_S)) scissorMode = !scissorMode;
// Centre the scissor area around the mouse position
scissorArea.x = GetMouseX() - scissorArea.width/2;
scissorArea.y = GetMouseY() - scissorArea.height/2;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (scissorMode) BeginScissorMode((int)scissorArea.x, (int)scissorArea.y, (int)scissorArea.width, (int)scissorArea.height);
// Draw full screen rectangle and some text
// NOTE: Only part defined by scissor area will be rendered
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RED);
DrawText("Move the mouse around to reveal this text!", 190, 200, 20, LIGHTGRAY);
if (scissorMode) EndScissorMode();
DrawRectangleLinesEx(scissorArea, 1, BLACK);
DrawText("Press S to toggle scissor test", 10, 10, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,166 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - screen recording
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.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) 2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
// Using msf_gif library to record frames into GIF
#define MSF_GIF_IMPL
#include "msf_gif.h" // GIF recording functionality
#include <math.h> // Required for: sinf()
#define GIF_RECORD_FRAMERATE 5 // Record framerate, we get a frame every N frames
#define MAX_SINEWAVE_POINTS 256
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - screen recording");
bool gifRecording = false; // GIF recording state
unsigned int gifFrameCounter = 0; // GIF frames counter
MsfGifState gifState = { 0 }; // MSGIF context state
Vector2 circlePosition = { 0.0f, screenHeight/2.0f };
float timeCounter = 0.0f;
// Get sine wave points for line drawing
Vector2 sinePoints[MAX_SINEWAVE_POINTS] = { 0 };
for (int i = 0; i < MAX_SINEWAVE_POINTS; i++)
{
sinePoints[i].x = i*GetScreenWidth()/180.0f;
sinePoints[i].y = screenHeight/2.0f + 150*sinf((2*PI/1.5f)*(1.0f/60.0f)*(float)i); // Calculate for 60 fps
}
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Update circle sinusoidal movement
timeCounter += GetFrameTime();
circlePosition.x += GetScreenWidth()/180.0f;
circlePosition.y = screenHeight/2.0f + 150*sinf((2*PI/1.5f)*timeCounter);
if (circlePosition.x > screenWidth)
{
circlePosition.x = 0.0f;
circlePosition.y = screenHeight/2.0f;
timeCounter = 0.0f;
}
// Start-Stop GIF recording on CTRL+R
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_R))
{
if (gifRecording)
{
// Stop current recording and save file
gifRecording = false;
MsfGifResult result = msf_gif_end(&gifState);
SaveFileData(TextFormat("%s/screenrecording.gif", GetApplicationDirectory()), result.data, (unsigned int)result.dataSize);
msf_gif_free(result);
TraceLog(LOG_INFO, "Finish animated GIF recording");
}
else
{
// Start a new recording
gifRecording = true;
gifFrameCounter = 0;
msf_gif_begin(&gifState, GetRenderWidth(), GetRenderHeight());
TraceLog(LOG_INFO, "Start animated GIF recording");
}
}
if (gifRecording)
{
gifFrameCounter++;
// NOTE: We record one gif frame depending on the desired gif framerate
if (gifFrameCounter > GIF_RECORD_FRAMERATE)
{
// Get image data for the current frame (from backbuffer)
// WARNING: This process is quite slow, it can generate stuttering
Image imScreen = LoadImageFromScreen();
// Add the frame to the gif recording, providing and "estimated" time for display in centiseconds
msf_gif_frame(&gifState, imScreen.data, (int)((1.0f/60.0f)*GIF_RECORD_FRAMERATE)/10, 16, imScreen.width*4);
gifFrameCounter = 0;
UnloadImage(imScreen); // Free image data
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < (MAX_SINEWAVE_POINTS - 1); i++)
{
DrawLineV(sinePoints[i], sinePoints[i + 1], MAROON);
DrawCircleV(sinePoints[i], 3, MAROON);
}
DrawCircleV(circlePosition, 30, RED);
DrawFPS(10, 10);
/*
// Draw record indicator
// WARNING: If drawn here, it will appear in the recorded image,
// use a render texture instead for the recording and LoadImageFromTexture(rt.texture)
if (gifRecording)
{
// Display the recording indicator every half-second
if ((int)(GetTime()/0.5)%2 == 1)
{
DrawCircle(30, GetScreenHeight() - 20, 10, MAROON);
DrawText("GIF RECORDING", 50, GetScreenHeight() - 25, 10, RED);
}
}
*/
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// If still recording a GIF on close window, just finish
if (gifRecording)
{
MsfGifResult result = msf_gif_end(&gifState);
msf_gif_free(result);
gifRecording = false;
}
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,125 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - smooth pixelperfect
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 3.7, last time updated with raylib 4.0
*
* Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) 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) 2021-2025 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h> // Required for: sinf(), cosf()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
const int virtualScreenWidth = 160;
const int virtualScreenHeight = 90;
const float virtualRatio = (float)screenWidth/(float)virtualScreenWidth;
InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixelperfect");
Camera2D worldSpaceCamera = { 0 }; // Game world camera
worldSpaceCamera.zoom = 1.0f;
Camera2D screenSpaceCamera = { 0 }; // Smoothing camera
screenSpaceCamera.zoom = 1.0f;
// Load render texture to draw all our objects
RenderTexture2D target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
Rectangle rec01 = { 70.0f, 35.0f, 20.0f, 20.0f };
Rectangle rec02 = { 90.0f, 55.0f, 30.0f, 10.0f };
Rectangle rec03 = { 80.0f, 65.0f, 15.0f, 25.0f };
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
Vector2 origin = { 0.0f, 0.0f };
float rotation = 0.0f;
float cameraX = 0.0f;
float cameraY = 0.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
rotation += 60.0f*GetFrameTime(); // Rotate the rectangles, 60 degrees per second
// Make the camera move to demonstrate the effect
cameraX = (sinf((float)GetTime())*50.0f) - 10.0f;
cameraY = cosf((float)GetTime())*30.0f;
// Set the camera's target to the values computed above
screenSpaceCamera.target = (Vector2){ cameraX, cameraY };
// Round worldSpace coordinates, keep decimals into screenSpace coordinates
worldSpaceCamera.target.x = truncf(screenSpaceCamera.target.x);
screenSpaceCamera.target.x -= worldSpaceCamera.target.x;
screenSpaceCamera.target.x *= virtualRatio;
worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y);
screenSpaceCamera.target.y -= worldSpaceCamera.target.y;
screenSpaceCamera.target.y *= virtualRatio;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(target);
ClearBackground(RAYWHITE);
BeginMode2D(worldSpaceCamera);
DrawRectanglePro(rec01, origin, rotation, BLACK);
DrawRectanglePro(rec02, origin, -rotation, RED);
DrawRectanglePro(rec03, origin, rotation + 45.0f, BLUE);
EndMode2D();
EndTextureMode();
BeginDrawing();
ClearBackground(RED);
BeginMode2D(screenSpaceCamera);
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
EndMode2D();
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
DrawFPS(GetScreenWidth() - 95, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,200 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - storage values
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.4, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: calloc(), free()
#define STORAGE_DATA_FILE "storage.data" // Storage file
// NOTE: Storage positions must start with 0, directly related to file memory layout
typedef enum {
STORAGE_POSITION_SCORE = 0,
STORAGE_POSITION_HISCORE = 1
} StorageData;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static bool SaveStorageValue(unsigned int position, int value);
static int LoadStorageValue(unsigned int position);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - storage values");
int score = 0;
int hiscore = 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_R))
{
score = GetRandomValue(1000, 2000);
hiscore = GetRandomValue(2000, 4000);
}
if (IsKeyPressed(KEY_ENTER))
{
SaveStorageValue(STORAGE_POSITION_SCORE, score);
SaveStorageValue(STORAGE_POSITION_HISCORE, hiscore);
}
else if (IsKeyPressed(KEY_SPACE))
{
// NOTE: If requested position could not be found, value 0 is returned
score = LoadStorageValue(STORAGE_POSITION_SCORE);
hiscore = LoadStorageValue(STORAGE_POSITION_HISCORE);
}
framesCounter++;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText(TextFormat("SCORE: %i", score), 280, 130, 40, MAROON);
DrawText(TextFormat("HI-SCORE: %i", hiscore), 210, 200, 50, BLACK);
DrawText(TextFormat("frames: %i", framesCounter), 10, 10, 20, LIME);
DrawText("Press R to generate random numbers", 220, 40, 20, LIGHTGRAY);
DrawText("Press ENTER to SAVE values", 250, 310, 20, LIGHTGRAY);
DrawText("Press SPACE to LOAD values", 252, 350, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
// Save integer value to storage file (to defined position)
// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer)
bool SaveStorageValue(unsigned int position, int value)
{
bool success = false;
int dataSize = 0;
unsigned int newDataSize = 0;
unsigned char *fileData = LoadFileData(STORAGE_DATA_FILE, &dataSize);
unsigned char *newFileData = NULL;
if (fileData != NULL)
{
if (dataSize <= (position*sizeof(int)))
{
// Increase data size up to position and store value
newDataSize = (position + 1)*sizeof(int);
newFileData = (unsigned char *)RL_REALLOC(fileData, newDataSize);
if (newFileData != NULL)
{
// RL_REALLOC succeded
int *dataPtr = (int *)newFileData;
dataPtr[position] = value;
}
else
{
// RL_REALLOC failed
TraceLog(LOG_WARNING, "FILEIO: [%s] Failed to realloc data (%u), position in bytes (%u) bigger than actual file size", STORAGE_DATA_FILE, dataSize, position*sizeof(int));
// We store the old size of the file
newFileData = fileData;
newDataSize = dataSize;
}
}
else
{
// Store the old size of the file
newFileData = fileData;
newDataSize = dataSize;
// Replace value on selected position
int *dataPtr = (int *)newFileData;
dataPtr[position] = value;
}
success = SaveFileData(STORAGE_DATA_FILE, newFileData, newDataSize);
RL_FREE(newFileData);
TraceLog(LOG_INFO, "FILEIO: [%s] Saved storage value: %i", STORAGE_DATA_FILE, value);
}
else
{
TraceLog(LOG_INFO, "FILEIO: [%s] File created successfully", STORAGE_DATA_FILE);
dataSize = (position + 1)*sizeof(int);
fileData = (unsigned char *)RL_MALLOC(dataSize);
int *dataPtr = (int *)fileData;
dataPtr[position] = value;
success = SaveFileData(STORAGE_DATA_FILE, fileData, dataSize);
UnloadFileData(fileData);
TraceLog(LOG_INFO, "FILEIO: [%s] Saved storage value: %i", STORAGE_DATA_FILE, value);
}
return success;
}
// Load integer value from storage file (from defined position)
// NOTE: If requested position could not be found, value 0 is returned
int LoadStorageValue(unsigned int position)
{
int value = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(STORAGE_DATA_FILE, &dataSize);
if (fileData != NULL)
{
if (dataSize < ((int)(position*4))) TraceLog(LOG_WARNING, "FILEIO: [%s] Failed to find storage position: %i", STORAGE_DATA_FILE, position);
else
{
int *dataPtr = (int *)fileData;
value = dataPtr[position];
}
UnloadFileData(fileData);
TraceLog(LOG_INFO, "FILEIO: [%s] Loaded storage value: %i", STORAGE_DATA_FILE, value);
}
return value;
}

View File

@ -1,173 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - text file loading
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6
*
* Example contributed by Aanjishnu Bhattacharyya (@NimComPoo-04) 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) 0 Aanjishnu Bhattacharyya (@NimComPoo-04)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h" // Required for: Lerp()
#include <string.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - text file loading");
// Setting up the camera
Camera2D cam = {
.offset = {0, 0},
.target = {0, 0},
.rotation = 0,
.zoom = 1
};
// Loading text file from resources/text_file.txt
const char *fileName = "resources/text_file.txt";
char *text = LoadFileText(fileName);
// Loading all the text lines
int lineCount = 0;
char **lines = LoadTextLines(text, &lineCount);
// Stylistic choises
int fontSize = 20;
int textTop = 25 + fontSize; // Top of the screen from where the text is rendered
int wrapWidth = screenWidth - 20;
// Wrap the lines as needed
for (int i = 0; i < lineCount; i++)
{
int j = 0;
int lastSpace = 0; // Keeping track of last valid space to insert '\n'
int lastWrapStart = 0; // Keeping track of the start of this wrapped line.
while (j <= strlen(lines[i]))
{
if (lines[i][j] == ' ' || lines[i][j] == '\0')
{
char before = lines[i][j];
// Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function
lines[i][j] = '\0';
// Checking if the text has crossed the wrapWidth, then going back and inserting a newline
if (MeasureText(lines[i] + lastWrapStart, fontSize) > wrapWidth)
{
lines[i][lastSpace] = '\n';
// Since we added a newline the place of wrap changed so we update our lastWrapStart
lastWrapStart = lastSpace + 1;
}
if(before != '\0') lines[i][j] = ' '; // Resetting the space back
lastSpace = j; // Since we encountered a new space we update our last encountered space location
}
j++;
}
}
// Calculating the total height so that we can show a scrollbar
int textHeight = 0;
for (int i = 0; i < lineCount; i++)
{
Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2);
textHeight += (int)size.y + 10;
}
// A simple scrollbar on the side to show how far we have read into the file
Rectangle scrollBar = {
.x = (float)screenWidth - 5,
.y = 0,
.width = 5,
.height = screenHeight*100.0f/(textHeight - screenHeight) // Scrollbar height is just a percentage
};
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
float scroll = GetMouseWheelMove();
cam.target.y -= scroll*fontSize*1.5f; // Choosing an arbitrary speed for scroll
if (cam.target.y < 0) cam.target.y = 0; // Snapping to 0 if we go too far back
// Ensuring that the camera does not scroll past all text
if (cam.target.y > textHeight - screenHeight + textTop)
cam.target.y = (float)textHeight - screenHeight + textTop;
// Computing the position of the scrollBar depending on the percentage of text covered
scrollBar.y = Lerp((float)textTop, (float)screenHeight - scrollBar.height, (float)(cam.target.y - textTop)/(textHeight - screenHeight));
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode2D(cam);
// Going through all the read lines
for (int i = 0, t = textTop; i < lineCount; i++)
{
// Each time we go through and calculate the height of the text to move the cursor appropriately
Vector2 size;
if(strcmp(lines[i], "")){
// Fix for empty line in the text file
size = MeasureTextEx( GetFontDefault(), lines[i], (float)fontSize, 2);
}else{
size = MeasureTextEx( GetFontDefault(), " ", (float)fontSize, 2);
}
DrawText(lines[i], 10, t, fontSize, RED);
// Inserting extra space for real newlines,
// wrapped lines are rendered closer together
t += (int)size.y + 10;
}
EndMode2D();
// Header displaying which file is being read currently
DrawRectangle(0, 0, screenWidth, textTop - 10, BEIGE);
DrawText(TextFormat("File: %s", fileName), 10, 10, fontSize, MAROON);
DrawRectangleRec(scrollBar, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTextLines(lines, lineCount);
UnloadFileText(text);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,312 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - undo redo
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6
*
* Example contributed 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 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: calloc(), free()
#include <string.h> // Required for: memcpy(), strcmp()
#define MAX_UNDO_STATES 26 // Maximum undo states supported for the ring buffer
#define GRID_CELL_SIZE 24
#define MAX_GRID_CELLS_X 30
#define MAX_GRID_CELLS_Y 13
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Point struct, like Vector2 but using int
typedef struct {
int x;
int y;
} Point;
// Player state struct
// NOTE: Contains all player data that needs to be affected by undo/redo
typedef struct {
Point cell;
Color color;
} PlayerState;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
// Draw undo system visualization logic
static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoIndex, int currentUndoIndex, int slotSize);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// We have multiple options to implement an Undo/Redo system
// Probably the most professional one is using the Command pattern to
// define Actions and store those actions into an array as the events happen,
// raylib internal Automation System actually uses a similar approach,
// but in this example we are using another more simple solution,
// just record PlayerState changes when detected, checking for changes every certain frames
// This approach requires more memory and is more performance costly but it is quite simple to implement
InitWindow(screenWidth, screenHeight, "raylib [core] example - undo redo");
// Undo/redo system variables
int currentUndoIndex = 0;
int firstUndoIndex = 0;
int lastUndoIndex = 0;
int undoFrameCounter = 0;
Vector2 undoInfoPos = { 110, 400 };
// Init current player state and undo/redo recorded states array
PlayerState player = { 0 };
player.cell = (Point){ 10, 10 };
player.color = RED;
// Init undo buffer to store MAX_UNDO_STATES states
PlayerState *states = (PlayerState *)RL_CALLOC(MAX_UNDO_STATES, sizeof(PlayerState));
// Init all undo states to current state
for (int i = 0; i < MAX_UNDO_STATES; i++) memcpy(&states[i], &player, sizeof(PlayerState));
// Grid variables
Vector2 gridPosition = { 40, 60 };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Player movement logic
if (IsKeyPressed(KEY_RIGHT)) player.cell.x++;
else if (IsKeyPressed(KEY_LEFT)) player.cell.x--;
else if (IsKeyPressed(KEY_UP)) player.cell.y--;
else if (IsKeyPressed(KEY_DOWN)) player.cell.y++;
// Make sure player does not go out of bounds
if (player.cell.x < 0) player.cell.x = 0;
else if (player.cell.x >= MAX_GRID_CELLS_X) player.cell.x = MAX_GRID_CELLS_X - 1;
if (player.cell.y < 0) player.cell.y = 0;
else if (player.cell.y >= MAX_GRID_CELLS_Y) player.cell.y = MAX_GRID_CELLS_Y - 1;
// Player color change logic
if (IsKeyPressed(KEY_SPACE))
{
player.color.r = (unsigned char)GetRandomValue(20, 255);
player.color.g = (unsigned char)GetRandomValue(20, 220);
player.color.b = (unsigned char)GetRandomValue(20, 240);
}
// Undo state change logic
undoFrameCounter++;
// Waiting a number of frames before checking if we should store a new state snapshot
if (undoFrameCounter >= 2) // Checking every 2 frames
{
if (memcmp(&states[currentUndoIndex], &player, sizeof(PlayerState)) != 0)
{
// Move cursor to next available position of the undo ring buffer to record state
currentUndoIndex++;
if (currentUndoIndex >= MAX_UNDO_STATES) currentUndoIndex = 0;
if (currentUndoIndex == firstUndoIndex) firstUndoIndex++;
if (firstUndoIndex >= MAX_UNDO_STATES) firstUndoIndex = 0;
memcpy(&states[currentUndoIndex], &player, sizeof(PlayerState));
lastUndoIndex = currentUndoIndex;
}
undoFrameCounter = 0;
}
// Recover previous state from buffer: CTRL+Z
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_Z))
{
if (currentUndoIndex != firstUndoIndex)
{
currentUndoIndex--;
if (currentUndoIndex < 0) currentUndoIndex = MAX_UNDO_STATES - 1;
if (memcmp(&states[currentUndoIndex], &player, sizeof(PlayerState)) != 0)
{
memcpy(&player, &states[currentUndoIndex], sizeof(PlayerState));
}
}
}
// Recover next state from buffer: CTRL+Y
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_Y))
{
if (currentUndoIndex != lastUndoIndex)
{
int nextUndoIndex = currentUndoIndex + 1;
if (nextUndoIndex >= MAX_UNDO_STATES) nextUndoIndex = 0;
if (nextUndoIndex != firstUndoIndex)
{
currentUndoIndex = nextUndoIndex;
if (memcmp(&states[currentUndoIndex], &player, sizeof(PlayerState)) != 0)
{
memcpy(&player, &states[currentUndoIndex], sizeof(PlayerState));
}
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw controls info
DrawText("[ARROWS] MOVE PLAYER - [SPACE] CHANGE PLAYER COLOR", 40, 20, 20, DARKGRAY);
// Draw player visited cells recorded by undo
// NOTE: Remember we are using a ring buffer approach so,
// some cells info could start at the end of the array and end at the beginning
if (lastUndoIndex > firstUndoIndex)
{
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
}
else if (firstUndoIndex > lastUndoIndex)
{
if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex))
{
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
}
else
{
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
DrawRectangle((int)gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, (int)gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY);
for (int i = 0; i < currentUndoIndex; i++)
DrawRectangle((int)gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, (int)gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY);
}
}
// Draw game grid
for (int y = 0; y <= MAX_GRID_CELLS_Y; y++)
DrawLine((int)gridPosition.x, (int)gridPosition.y + y*GRID_CELL_SIZE,
(int)gridPosition.x + MAX_GRID_CELLS_X*GRID_CELL_SIZE, (int)gridPosition.y + y*GRID_CELL_SIZE, GRAY);
for (int x = 0; x <= MAX_GRID_CELLS_X; x++)
DrawLine((int)gridPosition.x + x*GRID_CELL_SIZE, (int)gridPosition.y,
(int)gridPosition.x + x*GRID_CELL_SIZE, (int)gridPosition.y + MAX_GRID_CELLS_Y*GRID_CELL_SIZE, GRAY);
// Draw player
DrawRectangle((int)gridPosition.x + player.cell.x*GRID_CELL_SIZE, (int)gridPosition.y + player.cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE + 1, GRID_CELL_SIZE + 1, player.color);
// Draw undo system buffer info
DrawText("UNDO STATES:", (int)undoInfoPos.x - 85, (int)undoInfoPos.y + 9, 10, DARKGRAY);
DrawUndoBuffer(undoInfoPos, firstUndoIndex, lastUndoIndex, currentUndoIndex, 24);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(states); // Free undo states array
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Draw undo system visualization logic
// NOTE: Visualizing the ring buffer array, every square can store a player state
static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoIndex, int currentUndoIndex, int slotSize)
{
// Draw index marks
DrawRectangle((int)position.x + 8 + slotSize*currentUndoIndex, (int)position.y - 10, 8, 8, RED);
DrawRectangleLines((int)position.x + 2 + slotSize*firstUndoIndex, (int)position.y + 27, 8, 8, BLACK);
DrawRectangle((int)position.x + 14 + slotSize*lastUndoIndex, (int)position.y + 27, 8, 8, BLACK);
// Draw background gray slots
for (int i = 0; i < MAX_UNDO_STATES; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIGHTGRAY);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GRAY);
}
// Draw occupied slots: firstUndoIndex --> lastUndoIndex
if (firstUndoIndex <= lastUndoIndex)
{
for (int i = firstUndoIndex; i < lastUndoIndex + 1; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE);
}
}
else if (lastUndoIndex < firstUndoIndex)
{
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE);
}
for (int i = 0; i < lastUndoIndex + 1; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE);
}
}
// Draw occupied slots: firstUndoIndex --> currentUndoIndex
if (firstUndoIndex < currentUndoIndex)
{
for (int i = firstUndoIndex; i < currentUndoIndex; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME);
}
}
else if (currentUndoIndex < firstUndoIndex)
{
for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME);
}
for (int i = 0; i < currentUndoIndex; i++)
{
DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN);
DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME);
}
}
// Draw current selected UNDO slot
DrawRectangle((int)position.x + slotSize*currentUndoIndex, (int)position.y, slotSize, slotSize, GOLD);
DrawRectangleLines((int)position.x + slotSize*currentUndoIndex, (int)position.y, slotSize, slotSize, ORANGE);
}

View File

@ -1,321 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - viewport scaling
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Agnis Aldiņš (@nezvers) 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 Agnis Aldiņš (@nezvers)
*
********************************************************************************************/
#include "raylib.h"
#define RESOLUTION_COUNT 4 // For iteration purposes and teaching example
typedef enum {
// Only upscale, useful for pixel art
KEEP_ASPECT_INTEGER,
KEEP_HEIGHT_INTEGER,
KEEP_WIDTH_INTEGER,
// Can also downscale
KEEP_ASPECT,
KEEP_HEIGHT,
KEEP_WIDTH,
// For itteration purposes and as a teaching example
VIEWPORT_TYPE_COUNT,
} ViewportType;
// For displaying on GUI
const char *ViewportTypeNames[VIEWPORT_TYPE_COUNT] = {
"KEEP_ASPECT_INTEGER",
"KEEP_HEIGHT_INTEGER",
"KEEP_WIDTH_INTEGER",
"KEEP_ASPECT",
"KEEP_HEIGHT",
"KEEP_WIDTH",
};
//--------------------------------------------------------------------------------------
// Module Functions Declaration
//--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target);
// Example how to calculate position on RenderTexture
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//---------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - viewport scaling");
// Preset resolutions that could be created by subdividing screen resolution
Vector2 resolutionList[RESOLUTION_COUNT] = {
(Vector2){ 64, 64 },
(Vector2){ 256, 240 },
(Vector2){ 320, 180 },
// 4K doesn't work with integer scaling but included for example purposes with non-integer scaling
(Vector2){ 3840, 2160 },
};
int resolutionIndex = 0;
int gameWidth = 64;
int gameHeight = 64;
RenderTexture2D target = (RenderTexture2D){ 0 };
Rectangle sourceRect = (Rectangle){ 0 };
Rectangle destRect = (Rectangle){ 0 };
ViewportType viewportType = KEEP_ASPECT_INTEGER;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
// Button rectangles
Rectangle decreaseResolutionButton = (Rectangle){ 200, 30, 10, 10 };
Rectangle increaseResolutionButton = (Rectangle){ 215, 30, 10, 10 };
Rectangle decreaseTypeButton = (Rectangle){ 200, 45, 10, 10 };
Rectangle increaseTypeButton = (Rectangle){ 215, 45, 10, 10 };
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 (IsWindowResized()) ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
Vector2 mousePosition = GetMousePosition();
bool mousePressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
// Check buttons and rescale
if (CheckCollisionPointRec(mousePosition, decreaseResolutionButton) && mousePressed)
{
resolutionIndex = (resolutionIndex + RESOLUTION_COUNT - 1)%RESOLUTION_COUNT;
gameWidth = (int)resolutionList[resolutionIndex].x;
gameHeight = (int)resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, increaseResolutionButton) && mousePressed)
{
resolutionIndex = (resolutionIndex + 1)%RESOLUTION_COUNT;
gameWidth = (int)resolutionList[resolutionIndex].x;
gameHeight = (int)resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, decreaseTypeButton) && mousePressed)
{
viewportType = (viewportType + VIEWPORT_TYPE_COUNT - 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
if (CheckCollisionPointRec(mousePosition, increaseTypeButton) && mousePressed)
{
viewportType = (viewportType + 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
Vector2 textureMousePosition = Screen2RenderTexturePosition(mousePosition, &sourceRect, &destRect);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Draw our scene to the render texture
BeginTextureMode(target);
ClearBackground(WHITE);
DrawCircleV(textureMousePosition, 20.0f, LIME);
EndTextureMode();
// Draw render texture to main framebuffer
BeginDrawing();
ClearBackground(BLACK);
// Draw our render texture with rotation applied
DrawTexturePro(target.texture, sourceRect, destRect, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
// Draw Native resolution (GUI or anything)
// Draw info box
Rectangle infoRect = (Rectangle){5, 5, 330, 105};
DrawRectangleRec(infoRect, Fade(LIGHTGRAY, 0.7f));
DrawRectangleLinesEx(infoRect, 1, BLUE);
DrawText(TextFormat("Window Resolution: %d x %d", screenWidth, screenHeight), 15, 15, 10, BLACK);
DrawText(TextFormat("Game Resolution: %d x %d", gameWidth, gameHeight), 15, 30, 10, BLACK);
DrawText(TextFormat("Type: %s", ViewportTypeNames[viewportType]), 15, 45, 10, BLACK);
Vector2 scaleRatio = (Vector2){destRect.width/sourceRect.width, -destRect.height/sourceRect.height};
if (scaleRatio.x < 0.001f || scaleRatio.y < 0.001f) DrawText(TextFormat("Scale ratio: INVALID"), 15, 60, 10, BLACK);
else DrawText(TextFormat("Scale ratio: %.2f x %.2f", scaleRatio.x, scaleRatio.y), 15, 60, 10, BLACK);
DrawText(TextFormat("Source size: %.2f x %.2f", sourceRect.width, -sourceRect.height), 15, 75, 10, BLACK);
DrawText(TextFormat("Destination size: %.2f x %.2f", destRect.width, destRect.height), 15, 90, 10, BLACK);
// Draw buttons
DrawRectangleRec(decreaseTypeButton, SKYBLUE);
DrawRectangleRec(increaseTypeButton, SKYBLUE);
DrawRectangleRec(decreaseResolutionButton, SKYBLUE);
DrawRectangleRec(increaseResolutionButton, SKYBLUE);
DrawText("<", (int)decreaseTypeButton.x + 3, (int)decreaseTypeButton.y + 1, 10, BLACK);
DrawText(">", (int)increaseTypeButton.x + 3, (int)increaseTypeButton.y + 1, 10, BLACK);
DrawText("<", (int)decreaseResolutionButton.x + 3, (int)decreaseResolutionButton.y + 1, 10, BLACK);
DrawText(">", (int)increaseResolutionButton.x + 3, (int)increaseResolutionButton.y + 1, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//----------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------------------------------
return 0;
}
//--------------------------------------------------------------------------------------
// Module Functions Definition
//--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight;
const int ratio_x = (screenWidth/gameWidth);
const int ratio_y = (screenHeight/gameHeight);
const float resizeRatio = (float)((ratio_x < ratio_y)? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = (float)screenHeight/gameHeight;
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)(int)(screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = (float)screenWidth/gameWidth;
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)(screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.0f;
}
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight;
const float ratio_x = ((float)screenWidth/(float)gameWidth);
const float ratio_y = ((float)screenHeight/(float)gameHeight);
const float resizeRatio = (ratio_x < ratio_y ? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = ((float)screenHeight/(float)gameHeight);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)(int)((float)screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight*resizeRatio);
}
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{
const float resizeRatio = ((float)screenWidth/(float)gameWidth);
sourceRect->x = 0.0f;
sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)((float)screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.f;
}
static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target)
{
*screenWidth = GetScreenWidth();
*screenHeight = GetScreenHeight();
switch(viewportType)
{
case KEEP_ASPECT_INTEGER: KeepAspectCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_HEIGHT_INTEGER: KeepHeightCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_WIDTH_INTEGER: KeepWidthCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_ASPECT: KeepAspectCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_HEIGHT: KeepHeightCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_WIDTH: KeepWidthCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
default: break;
}
UnloadRenderTexture(*target);
*target = LoadRenderTexture((int)sourceRect->width, -(int)sourceRect->height);
}
// Example how to calculate position on RenderTexture
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect)
{
Vector2 relativePosition = {point.x - scaledRect->x, point.y - scaledRect->y};
Vector2 ratio = {textureRect->width/scaledRect->width, -textureRect->height/scaledRect->height};
return (Vector2){relativePosition.x*ratio.x, relativePosition.y*ratio.x};
}

View File

@ -1,152 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - vr simulator
*
* Example complexity rating: [★★★☆] 3/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) 2017-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// NOTE: screenWidth/screenHeight should match VR device aspect ratio
InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator");
// VR device parameters definition
VrDeviceInfo device = {
// Oculus Rift CV1 parameters for simulator
.hResolution = 2160, // Horizontal resolution in pixels
.vResolution = 1200, // Vertical resolution in pixels
.hScreenSize = 0.133793f, // Horizontal size in meters
.vScreenSize = 0.0669f, // Vertical size in meters
.eyeToScreenDistance = 0.041f, // Distance between eye and display in meters
.lensSeparationDistance = 0.07f, // Lens separation distance in meters
.interpupillaryDistance = 0.07f, // IPD (distance between pupils) in meters
// NOTE: CV1 uses fresnel-hybrid-asymmetric lenses with specific compute shaders
// Following parameters are just an approximation to CV1 distortion stereo rendering
.lensDistortionValues[0] = 1.0f, // Lens distortion constant parameter 0
.lensDistortionValues[1] = 0.22f, // Lens distortion constant parameter 1
.lensDistortionValues[2] = 0.24f, // Lens distortion constant parameter 2
.lensDistortionValues[3] = 0.0f, // Lens distortion constant parameter 3
.chromaAbCorrection[0] = 0.996f, // Chromatic aberration correction parameter 0
.chromaAbCorrection[1] = -0.004f, // Chromatic aberration correction parameter 1
.chromaAbCorrection[2] = 1.014f, // Chromatic aberration correction parameter 2
.chromaAbCorrection[3] = 0.0f, // Chromatic aberration correction parameter 3
};
// Load VR stereo config for VR device parameteres (Oculus Rift CV1 parameters)
VrStereoConfig config = LoadVrStereoConfig(device);
// Distortion shader (uses device lens distortion and chroma)
Shader distortion = LoadShader(0, TextFormat("resources/shaders/glsl%i/distortion.fs", GLSL_VERSION));
// Update distortion shader with lens and distortion-scale parameters
SetShaderValue(distortion, GetShaderLocation(distortion, "leftLensCenter"),
config.leftLensCenter, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "rightLensCenter"),
config.rightLensCenter, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "leftScreenCenter"),
config.leftScreenCenter, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "rightScreenCenter"),
config.rightScreenCenter, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "scale"),
config.scale, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "scaleIn"),
config.scaleIn, SHADER_UNIFORM_VEC2);
SetShaderValue(distortion, GetShaderLocation(distortion, "deviceWarpParam"),
device.lensDistortionValues, SHADER_UNIFORM_VEC4);
SetShaderValue(distortion, GetShaderLocation(distortion, "chromaAbParam"),
device.chromaAbCorrection, SHADER_UNIFORM_VEC4);
// Initialize framebuffer for stereo rendering
// NOTE: Screen size should match HMD aspect ratio
RenderTexture2D target = LoadRenderTexture(device.hResolution, device.vResolution);
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
Rectangle destRec = { 0.0f, 0.0f, (float)GetScreenWidth(), (float)GetScreenHeight() };
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 2.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector
camera.fovy = 60.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(target);
ClearBackground(RAYWHITE);
BeginVrStereoMode(config);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(40, 1.0f);
EndMode3D();
EndVrStereoMode();
EndTextureMode();
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(distortion);
DrawTexturePro(target.texture, sourceRec, destRec, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
EndShaderMode();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadVrStereoConfig(config); // Unload stereo config
UnloadRenderTexture(target); // Unload stereo render fbo
UnloadShader(distortion); // Unload distortion shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,207 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - window flags
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 3.5, last time updated with raylib 3.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) 2020-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//---------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
// Possible window flags
/*
FLAG_VSYNC_HINT
FLAG_FULLSCREEN_MODE -> not working properly -> wrong scaling!
FLAG_WINDOW_RESIZABLE
FLAG_WINDOW_UNDECORATED
FLAG_WINDOW_TRANSPARENT
FLAG_WINDOW_HIDDEN
FLAG_WINDOW_MINIMIZED -> Not supported on window creation
FLAG_WINDOW_MAXIMIZED -> Not supported on window creation
FLAG_WINDOW_UNFOCUSED
FLAG_WINDOW_TOPMOST
FLAG_WINDOW_HIGHDPI -> errors after minimize-resize, fb size is recalculated
FLAG_WINDOW_ALWAYS_RUN
FLAG_MSAA_4X_HINT
*/
// Set configuration flags for window creation
//SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI);// | FLAG_WINDOW_TRANSPARENT);
InitWindow(screenWidth, screenHeight, "raylib [core] example - window flags");
Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
Vector2 ballSpeed = { 5.0f, 4.0f };
float ballRadius = 20;
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_F)) ToggleFullscreen(); // modifies window size when scaling!
if (IsKeyPressed(KEY_R))
{
if (IsWindowState(FLAG_WINDOW_RESIZABLE)) ClearWindowState(FLAG_WINDOW_RESIZABLE);
else SetWindowState(FLAG_WINDOW_RESIZABLE);
}
if (IsKeyPressed(KEY_D))
{
if (IsWindowState(FLAG_WINDOW_UNDECORATED)) ClearWindowState(FLAG_WINDOW_UNDECORATED);
else SetWindowState(FLAG_WINDOW_UNDECORATED);
}
if (IsKeyPressed(KEY_H))
{
if (!IsWindowState(FLAG_WINDOW_HIDDEN)) SetWindowState(FLAG_WINDOW_HIDDEN);
framesCounter = 0;
}
if (IsWindowState(FLAG_WINDOW_HIDDEN))
{
framesCounter++;
if (framesCounter >= 240) ClearWindowState(FLAG_WINDOW_HIDDEN); // Show window after 3 seconds
}
if (IsKeyPressed(KEY_N))
{
if (!IsWindowState(FLAG_WINDOW_MINIMIZED)) MinimizeWindow();
framesCounter = 0;
}
if (IsWindowState(FLAG_WINDOW_MINIMIZED))
{
framesCounter++;
if (framesCounter >= 240)
{
RestoreWindow(); // Restore window after 3 seconds
framesCounter = 0;
}
}
if (IsKeyPressed(KEY_M))
{
// NOTE: Requires FLAG_WINDOW_RESIZABLE enabled!
if (IsWindowState(FLAG_WINDOW_MAXIMIZED)) RestoreWindow();
else MaximizeWindow();
}
if (IsKeyPressed(KEY_U))
{
if (IsWindowState(FLAG_WINDOW_UNFOCUSED)) ClearWindowState(FLAG_WINDOW_UNFOCUSED);
else SetWindowState(FLAG_WINDOW_UNFOCUSED);
}
if (IsKeyPressed(KEY_T))
{
if (IsWindowState(FLAG_WINDOW_TOPMOST)) ClearWindowState(FLAG_WINDOW_TOPMOST);
else SetWindowState(FLAG_WINDOW_TOPMOST);
}
if (IsKeyPressed(KEY_A))
{
if (IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) ClearWindowState(FLAG_WINDOW_ALWAYS_RUN);
else SetWindowState(FLAG_WINDOW_ALWAYS_RUN);
}
if (IsKeyPressed(KEY_V))
{
if (IsWindowState(FLAG_VSYNC_HINT)) ClearWindowState(FLAG_VSYNC_HINT);
else SetWindowState(FLAG_VSYNC_HINT);
}
if (IsKeyPressed(KEY_B)) ToggleBorderlessWindowed();
// Bouncing ball logic
ballPosition.x += ballSpeed.x;
ballPosition.y += ballSpeed.y;
if ((ballPosition.x >= (GetScreenWidth() - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f;
if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -1.0f;
//-----------------------------------------------------
// Draw
//-----------------------------------------------------
BeginDrawing();
if (IsWindowState(FLAG_WINDOW_TRANSPARENT)) ClearBackground(BLANK);
else ClearBackground(RAYWHITE);
DrawCircleV(ballPosition, ballRadius, MAROON);
DrawRectangleLinesEx((Rectangle) { 0, 0, (float)GetScreenWidth(), (float)GetScreenHeight() }, 4, RAYWHITE);
DrawCircleV(GetMousePosition(), 10, DARKBLUE);
DrawFPS(10, 10);
DrawText(TextFormat("Screen Size: [%i, %i]", GetScreenWidth(), GetScreenHeight()), 10, 40, 10, GREEN);
// Draw window state info
DrawText("Following flags can be set after window creation:", 10, 60, 10, GRAY);
if (IsWindowState(FLAG_FULLSCREEN_MODE)) DrawText("[F] FLAG_FULLSCREEN_MODE: on", 10, 80, 10, LIME);
else DrawText("[F] FLAG_FULLSCREEN_MODE: off", 10, 80, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_RESIZABLE)) DrawText("[R] FLAG_WINDOW_RESIZABLE: on", 10, 100, 10, LIME);
else DrawText("[R] FLAG_WINDOW_RESIZABLE: off", 10, 100, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_UNDECORATED)) DrawText("[D] FLAG_WINDOW_UNDECORATED: on", 10, 120, 10, LIME);
else DrawText("[D] FLAG_WINDOW_UNDECORATED: off", 10, 120, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_HIDDEN)) DrawText("[H] FLAG_WINDOW_HIDDEN: on", 10, 140, 10, LIME);
else DrawText("[H] FLAG_WINDOW_HIDDEN: off (hides for 3 seconds)", 10, 140, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_MINIMIZED)) DrawText("[N] FLAG_WINDOW_MINIMIZED: on", 10, 160, 10, LIME);
else DrawText("[N] FLAG_WINDOW_MINIMIZED: off (restores after 3 seconds)", 10, 160, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_MAXIMIZED)) DrawText("[M] FLAG_WINDOW_MAXIMIZED: on", 10, 180, 10, LIME);
else DrawText("[M] FLAG_WINDOW_MAXIMIZED: off", 10, 180, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_UNFOCUSED)) DrawText("[G] FLAG_WINDOW_UNFOCUSED: on", 10, 200, 10, LIME);
else DrawText("[U] FLAG_WINDOW_UNFOCUSED: off", 10, 200, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_TOPMOST)) DrawText("[T] FLAG_WINDOW_TOPMOST: on", 10, 220, 10, LIME);
else DrawText("[T] FLAG_WINDOW_TOPMOST: off", 10, 220, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: on", 10, 240, 10, LIME);
else DrawText("[A] FLAG_WINDOW_ALWAYS_RUN: off", 10, 240, 10, MAROON);
if (IsWindowState(FLAG_VSYNC_HINT)) DrawText("[V] FLAG_VSYNC_HINT: on", 10, 260, 10, LIME);
else DrawText("[V] FLAG_VSYNC_HINT: off", 10, 260, 10, MAROON);
if (IsWindowState(FLAG_BORDERLESS_WINDOWED_MODE)) DrawText("[B] FLAG_BORDERLESS_WINDOWED_MODE: on", 10, 280, 10, LIME);
else DrawText("[B] FLAG_BORDERLESS_WINDOWED_MODE: off", 10, 280, 10, MAROON);
DrawText("Following flags can only be set before window creation:", 10, 320, 10, GRAY);
if (IsWindowState(FLAG_WINDOW_HIGHDPI)) DrawText("FLAG_WINDOW_HIGHDPI: on", 10, 340, 10, LIME);
else DrawText("FLAG_WINDOW_HIGHDPI: off", 10, 340, 10, MAROON);
if (IsWindowState(FLAG_WINDOW_TRANSPARENT)) DrawText("FLAG_WINDOW_TRANSPARENT: on", 10, 360, 10, LIME);
else DrawText("FLAG_WINDOW_TRANSPARENT: off", 10, 360, 10, MAROON);
if (IsWindowState(FLAG_MSAA_4X_HINT)) DrawText("FLAG_MSAA_4X_HINT: on", 10, 380, 10, LIME);
else DrawText("FLAG_MSAA_4X_HINT: off", 10, 380, 10, MAROON);
EndDrawing();
//-----------------------------------------------------
}
// De-Initialization
//---------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------
return 0;
}

View File

@ -1,109 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - window letterbox
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 2.5, last time updated with raylib 4.0
*
* Example contributed by Anata (@anatagawa) 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 Anata (@anatagawa) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h" // Required for: Vector2Clamp()
#define MAX(a, b) ((a)>(b)? (a) : (b))
#define MIN(a, b) ((a)<(b)? (a) : (b))
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
const int screenWidth = 800;
const int screenHeight = 450;
// Enable config flags for resizable window and vertical synchro
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT);
InitWindow(screenWidth, screenHeight, "raylib [core] example - window letterbox");
SetWindowMinSize(320, 240);
int gameScreenWidth = 640;
int gameScreenHeight = 480;
// Render texture initialization, used to hold the rendering result so we can easily resize it
RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight);
SetTextureFilter(target.texture, TEXTURE_FILTER_BILINEAR); // Texture scale filter to use
Color colors[10] = { 0 };
for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 };
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
//----------------------------------------------------------------------------------
// Compute required framebuffer scaling
float scale = MIN((float)GetScreenWidth()/gameScreenWidth, (float)GetScreenHeight()/gameScreenHeight);
if (IsKeyPressed(KEY_SPACE))
{
// Recalculate random colors for the bars
for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 };
}
// Update virtual mouse (clamped mouse value behind game screen)
Vector2 mouse = GetMousePosition();
Vector2 virtualMouse = { 0 };
virtualMouse.x = (mouse.x - (GetScreenWidth() - (gameScreenWidth*scale))*0.5f)/scale;
virtualMouse.y = (mouse.y - (GetScreenHeight() - (gameScreenHeight*scale))*0.5f)/scale;
virtualMouse = Vector2Clamp(virtualMouse, (Vector2){ 0, 0 }, (Vector2){ (float)gameScreenWidth, (float)gameScreenHeight });
// Apply the same transformation as the virtual mouse to the real mouse (i.e. to work with raygui)
//SetMouseOffset(-(GetScreenWidth() - (gameScreenWidth*scale))*0.5f, -(GetScreenHeight() - (gameScreenHeight*scale))*0.5f);
//SetMouseScale(1/scale, 1/scale);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Draw everything in the render texture, note this will not be rendered on screen, yet
BeginTextureMode(target);
ClearBackground(RAYWHITE); // Clear render texture background color
for (int i = 0; i < 10; i++) DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i]);
DrawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE);
DrawText(TextFormat("Default Mouse: [%i , %i]", (int)mouse.x, (int)mouse.y), 350, 25, 20, GREEN);
DrawText(TextFormat("Virtual Mouse: [%i , %i]", (int)virtualMouse.x, (int)virtualMouse.y), 350, 55, 20, YELLOW);
EndTextureMode();
BeginDrawing();
ClearBackground(BLACK); // Clear screen background
// Draw render texture to screen, properly scaled
DrawTexturePro(target.texture, (Rectangle){ 0.0f, 0.0f, (float)target.texture.width, (float)-target.texture.height },
(Rectangle){ (GetScreenWidth() - ((float)gameScreenWidth*scale))*0.5f, (GetScreenHeight() - ((float)gameScreenHeight*scale))*0.5f,
(float)gameScreenWidth*scale, (float)gameScreenHeight*scale }, (Vector2){ 0, 0 }, 0.0f, WHITE);
EndDrawing();
//--------------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,79 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - window should close
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 4.2, 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) 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 [core] example - window should close");
SetExitKey(KEY_NULL); // Disable KEY_ESCAPE to close window, X-button still works
bool exitWindowRequested = false; // Flag to request window to exit
bool exitWindow = false; // Flag to set window to exit
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!exitWindow)
{
// Update
//----------------------------------------------------------------------------------
// Detect if X-button or KEY_ESCAPE have been pressed to close window
if (WindowShouldClose() || IsKeyPressed(KEY_ESCAPE)) exitWindowRequested = true;
if (exitWindowRequested)
{
// A request for close window has been issued, we can save data before closing
// or just show a message asking for confirmation
if (IsKeyPressed(KEY_Y)) exitWindow = true;
else if (IsKeyPressed(KEY_N)) exitWindowRequested = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (exitWindowRequested)
{
DrawRectangle(0, 100, screenWidth, 200, BLACK);
DrawText("Are you sure you want to exit program? [Y/N]", 40, 180, 30, WHITE);
}
else DrawText("Try to close the window to get confirmation message!", 120, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,86 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - window web
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.3, last time updated with raylib 5.5
*
* This example has been adapted to compile for PLATFORM_WEB and PLATFORM_DESKTOP
* As you will notice, code structure is slightly different to the other examples
*
* 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void); // Update and Draw one frame
//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [core] example - window web");
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Welcome to raylib web structure!", 220, 200, 20, SKYBLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -1,87 +0,0 @@
/*******************************************************************************************
*
* raylib [core] example - world screen
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.3, last time updated with raylib 1.4
*
* 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) 2015-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 [core] example - world screen");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
Vector2 cubeScreenPosition = { 0.0f, 0.0f };
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Calculate cube screen space position (with a little offset to be in top)
cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Enemy: 100/100", (int)cubeScreenPosition.x - MeasureText("Enemy: 100/100", 20)/2, (int)cubeScreenPosition.y, 20, BLACK);
DrawText(TextFormat("Cube position in screen space coordinates: [%i, %i]", (int)cubeScreenPosition.x, (int)cubeScreenPosition.y), 10, 10, 20, LIME);
DrawText("Text 2d should be always on top of the cube", 10, 40, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,717 +0,0 @@
/*
HOW TO USE:
In exactly one translation unit (.c or .cpp file), #define MSF_GIF_IMPL before including the header, like so:
#define MSF_GIF_IMPL
#include "msf_gif.h"
Everywhere else, just include the header like normal.
USAGE EXAMPLE:
int width = 480, height = 320, centisecondsPerFrame = 5, bitDepth = 16;
MsfGifState gifState = {};
// msf_gif_bgra_flag = true; //optionally, set this flag if your pixels are in BGRA format instead of RGBA
// msf_gif_alpha_threshold = 128; //optionally, enable transparency (see function documentation below for details)
msf_gif_begin(&gifState, width, height);
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 1
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 2
msf_gif_frame(&gifState, ..., centisecondsPerFrame, bitDepth, width * 4); //frame 3, etc...
MsfGifResult result = msf_gif_end(&gifState);
if (result.data) {
FILE * fp = fopen("MyGif.gif", "wb");
fwrite(result.data, result.dataSize, 1, fp);
fclose(fp);
}
msf_gif_free(result);
Detailed function documentation can be found in the header section below.
ERROR HANDLING:
If memory allocation fails, the functions will signal the error via their return values.
If one function call fails, the library will free all of its allocations,
and all subsequent calls will safely no-op and return 0 until the next call to `msf_gif_begin()`.
Therefore, it's safe to check only the return value of `msf_gif_end()`.
REPLACING MALLOC:
This library uses malloc+realloc+free internally for memory allocation.
To facilitate integration with custom memory allocators, these calls go through macros, which can be redefined.
The expected function signature equivalents of the macros are as follows:
void * MSF_GIF_MALLOC(void * context, size_t newSize)
void * MSF_GIF_REALLOC(void * context, void * oldMemory, size_t oldSize, size_t newSize)
void MSF_GIF_FREE(void * context, void * oldMemory, size_t oldSize)
If your allocator needs a context pointer, you can set the `customAllocatorContext` field of the MsfGifState struct
before calling msf_gif_begin(), and it will be passed to all subsequent allocator macro calls.
The maximum number of bytes the library will allocate to encode a single gif is bounded by the following formula:
`(2 * 1024 * 1024) + (width * height * 8) + ((1024 + width * height * 1.5) * 3 * frameCount)`
The peak heap memory usage in bytes, if using a general-purpose heap allocator, is bounded by the following formula:
`(2 * 1024 * 1024) + (width * height * 9.5) + 1024 + (16 * frameCount) + (2 * sizeOfResultingGif)
See end of file for license information.
*/
//version 2.2
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// HEADER ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef MSF_GIF_H
#define MSF_GIF_H
#include <stdint.h>
#include <stddef.h>
typedef struct {
void * data;
size_t dataSize;
size_t allocSize; //internal use
void * contextPointer; //internal use
} MsfGifResult;
typedef struct { //internal use
uint32_t * pixels;
int depth, count, rbits, gbits, bbits;
} MsfCookedFrame;
typedef struct MsfGifBuffer {
struct MsfGifBuffer * next;
size_t size;
uint8_t data[1];
} MsfGifBuffer;
typedef size_t (* MsfGifFileWriteFunc) (const void * buffer, size_t size, size_t count, void * stream);
typedef struct {
MsfGifFileWriteFunc fileWriteFunc;
void * fileWriteData;
MsfCookedFrame previousFrame;
MsfCookedFrame currentFrame;
int16_t * lzwMem;
MsfGifBuffer * listHead;
MsfGifBuffer * listTail;
int width, height;
void * customAllocatorContext;
int framesSubmitted; //needed for transparency to work correctly (because we reach into the previous frame)
} MsfGifState;
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
/**
* @param width Image width in pixels.
* @param height Image height in pixels.
* @return Non-zero on success, 0 on error.
*/
int msf_gif_begin(MsfGifState * handle, int width, int height);
/**
* @param pixelData Pointer to raw framebuffer data. Rows must be contiguous in memory, in RGBA8 format
* (or BGRA8 if you have set `msf_gif_bgra_flag = true`).
* Note: This function does NOT free `pixelData`. You must free it yourself afterwards.
* @param centiSecondsPerFrame How many hundredths of a second this frame should be displayed for.
* Note: This being specified in centiseconds is a limitation of the GIF format.
* @param maxBitDepth Limits how many bits per pixel can be used when quantizing the gif.
* The actual bit depth chosen for a given frame will be less than or equal to
* the supplied maximum, depending on the variety of colors used in the frame.
* `maxBitDepth` will be clamped between 1 and 16. The recommended default is 16.
* Lowering this value can result in faster exports and smaller gifs,
* but the quality may suffer.
* Please experiment with this value to find what works best for your application.
* @param pitchInBytes The number of bytes from the beginning of one row of pixels to the beginning of the next.
* If you want to flip the image, just pass in a negative pitch.
* @return Non-zero on success, 0 on error.
*/
int msf_gif_frame(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes);
/**
* @return A block of memory containing the gif file data, or NULL on error.
* You are responsible for freeing this via `msf_gif_free()`.
*/
MsfGifResult msf_gif_end(MsfGifState * handle);
/**
* @param result The MsfGifResult struct, verbatim as it was returned from `msf_gif_end()`.
*/
void msf_gif_free(MsfGifResult result);
//The gif format only supports 1-bit transparency, meaning a pixel will either be fully transparent or fully opaque.
//Pixels with an alpha value less than the alpha threshold will be treated as transparent.
//To enable exporting transparent gifs, set it to a value between 1 and 255 (inclusive) before calling msf_gif_frame().
//Setting it to 0 causes the alpha channel to be ignored. Its initial value is 0.
extern int msf_gif_alpha_threshold;
//Set `msf_gif_bgra_flag = true` before calling `msf_gif_frame()` if your pixels are in BGRA byte order instead of RBGA.
extern int msf_gif_bgra_flag;
//TO-FILE FUNCTIONS
//These functions are equivalent to the ones above, but they write results to a file incrementally,
//instead of building a buffer in memory. This can result in lower memory usage when saving large gifs,
//because memory usage is bounded by only the size of a single frame, and is not dependent on the number of frames.
//There is currently no reason to use these unless you are on a memory-constrained platform.
//If in doubt about which API to use, for now you should use the normal (non-file) functions above.
//The signature of MsfGifFileWriteFunc matches fwrite for convenience, so that you can use the C file API like so:
// FILE * fp = fopen("MyGif.gif", "wb");
// msf_gif_begin_to_file(&handle, width, height, (MsfGifFileWriteFunc) fwrite, (void *) fp);
// msf_gif_frame_to_file(...)
// msf_gif_end_to_file(&handle);
// fclose(fp);
//If you use a custom file write function, you must take care to return the same values that fwrite() would return.
//Note that all three functions will potentially write to the file.
int msf_gif_begin_to_file(MsfGifState * handle, int width, int height, MsfGifFileWriteFunc func, void * filePointer);
int msf_gif_frame_to_file(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes);
int msf_gif_end_to_file(MsfGifState * handle); //returns 0 on error and non-zero on success
#ifdef __cplusplus
}
#endif //__cplusplus
#endif //MSF_GIF_H
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// IMPLEMENTATION ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef MSF_GIF_IMPL
#ifndef MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
#define MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
//ensure the library user has either defined all of malloc/realloc/free, or none
#if defined(MSF_GIF_MALLOC) && defined(MSF_GIF_REALLOC) && defined(MSF_GIF_FREE) //ok
#elif !defined(MSF_GIF_MALLOC) && !defined(MSF_GIF_REALLOC) && !defined(MSF_GIF_FREE) //ok
#else
#error "You must either define all of MSF_GIF_MALLOC, MSF_GIF_REALLOC, and MSF_GIF_FREE, or define none of them"
#endif
//provide default allocator definitions that redirect to the standard global allocator
#if !defined(MSF_GIF_MALLOC)
#include <stdlib.h> //malloc, etc.
#define MSF_GIF_MALLOC(contextPointer, newSize) malloc(newSize)
#define MSF_GIF_REALLOC(contextPointer, oldMemory, oldSize, newSize) realloc(oldMemory, newSize)
#define MSF_GIF_FREE(contextPointer, oldMemory, oldSize) free(oldMemory)
#endif
//instrumentation for capturing profiling traces (useless for the library user, but useful for the library author)
#ifdef MSF_GIF_ENABLE_TRACING
#define MsfTimeFunc TimeFunc
#define MsfTimeLoop TimeLoop
#define msf_init_profiling_thread init_profiling_thread
#else
#define MsfTimeFunc
#define MsfTimeLoop(name)
#define msf_init_profiling_thread()
#endif //MSF_GIF_ENABLE_TRACING
#include <string.h> //memcpy
//TODO: use compiler-specific notation to force-inline functions currently marked inline
#if defined(__GNUC__) //gcc, clang
static inline int msf_bit_log(int i) { return 32 - __builtin_clz(i); }
#elif defined(_MSC_VER) //msvc
#include <intrin.h>
static inline int msf_bit_log(int i) { unsigned long idx; _BitScanReverse(&idx, i); return idx + 1; }
#else //fallback implementation for other compilers
//from https://stackoverflow.com/a/31718095/3064745 - thanks!
static inline int msf_bit_log(int i) {
static const int MultiplyDeBruijnBitPosition[32] = {
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31,
};
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
return MultiplyDeBruijnBitPosition[(uint32_t)(i * 0x07C4ACDDU) >> 27] + 1;
}
#endif
static inline int msf_imin(int a, int b) { return a < b? a : b; }
static inline int msf_imax(int a, int b) { return b < a? a : b; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Frame Cooking ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if (defined (__SSE2__) || defined (_M_X64) || _M_IX86_FP == 2) && !defined(MSF_GIF_NO_SSE2)
#include <emmintrin.h>
#endif
int msf_gif_alpha_threshold = 0;
int msf_gif_bgra_flag = 0;
static void msf_cook_frame(MsfCookedFrame * frame, uint8_t * raw, uint8_t * used,
int width, int height, int pitch, int depth)
{ MsfTimeFunc
//bit depth for each channel
static const int rdepthsArray[17] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
static const int gdepthsArray[17] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 };
static const int bdepthsArray[17] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
//this extra level of indirection looks unnecessary but we need to explicitly decay the arrays to pointers
//in order to be able to swap them because of C's annoying not-quite-pointers, not-quite-value-types stack arrays.
const int * rdepths = msf_gif_bgra_flag? bdepthsArray : rdepthsArray;
const int * gdepths = gdepthsArray;
const int * bdepths = msf_gif_bgra_flag? rdepthsArray : bdepthsArray;
static const int ditherKernel[16] = {
0 << 12, 8 << 12, 2 << 12, 10 << 12,
12 << 12, 4 << 12, 14 << 12, 6 << 12,
3 << 12, 11 << 12, 1 << 12, 9 << 12,
15 << 12, 7 << 12, 13 << 12, 5 << 12,
};
uint32_t * cooked = frame->pixels;
int count = 0;
MsfTimeLoop("do") do {
int rbits = rdepths[depth], gbits = gdepths[depth], bbits = bdepths[depth];
int paletteSize = (1 << (rbits + gbits + bbits)) + 1;
memset(used, 0, paletteSize * sizeof(uint8_t));
//TODO: document what this math does and why it's correct
int rdiff = (1 << (8 - rbits)) - 1;
int gdiff = (1 << (8 - gbits)) - 1;
int bdiff = (1 << (8 - bbits)) - 1;
short rmul = (short) ((255.0f - rdiff) / 255.0f * 257);
short gmul = (short) ((255.0f - gdiff) / 255.0f * 257);
short bmul = (short) ((255.0f - bdiff) / 255.0f * 257);
int gmask = ((1 << gbits) - 1) << rbits;
int bmask = ((1 << bbits) - 1) << rbits << gbits;
MsfTimeLoop("cook") for (int y = 0; y < height; ++y) {
int x = 0;
#if (defined (__SSE2__) || defined (_M_X64) || _M_IX86_FP == 2) && !defined(MSF_GIF_NO_SSE2)
__m128i k = _mm_loadu_si128((__m128i *) &ditherKernel[(y & 3) * 4]);
__m128i k2 = _mm_or_si128(_mm_srli_epi32(k, rbits), _mm_slli_epi32(_mm_srli_epi32(k, bbits), 16));
for (; x < width - 3; x += 4) {
uint8_t * pixels = &raw[y * pitch + x * 4];
__m128i p = _mm_loadu_si128((__m128i *) pixels);
__m128i rb = _mm_and_si128(p, _mm_set1_epi32(0x00FF00FF));
__m128i rb1 = _mm_mullo_epi16(rb, _mm_set_epi16(bmul, rmul, bmul, rmul, bmul, rmul, bmul, rmul));
__m128i rb2 = _mm_adds_epu16(rb1, k2);
__m128i r3 = _mm_srli_epi32(_mm_and_si128(rb2, _mm_set1_epi32(0x0000FFFF)), 16 - rbits);
__m128i b3 = _mm_and_si128(_mm_srli_epi32(rb2, 32 - rbits - gbits - bbits), _mm_set1_epi32(bmask));
__m128i g = _mm_and_si128(_mm_srli_epi32(p, 8), _mm_set1_epi32(0x000000FF));
__m128i g1 = _mm_mullo_epi16(g, _mm_set1_epi32(gmul));
__m128i g2 = _mm_adds_epu16(g1, _mm_srli_epi32(k, gbits));
__m128i g3 = _mm_and_si128(_mm_srli_epi32(g2, 16 - rbits - gbits), _mm_set1_epi32(gmask));
__m128i out = _mm_or_si128(_mm_or_si128(r3, g3), b3);
//mask in transparency based on threshold
//NOTE: we can theoretically do a sub instead of srli by doing an unsigned compare via bias
// to maybe save a TINY amount of throughput? but lol who cares maybe I'll do it later -m
__m128i invAlphaMask = _mm_cmplt_epi32(_mm_srli_epi32(p, 24), _mm_set1_epi32(msf_gif_alpha_threshold));
out = _mm_or_si128(_mm_and_si128(invAlphaMask, _mm_set1_epi32(paletteSize - 1)), _mm_andnot_si128(invAlphaMask, out));
//TODO: does storing this as a __m128i then reading it back as a uint32_t violate strict aliasing?
uint32_t * c = &cooked[y * width + x];
_mm_storeu_si128((__m128i *) c, out);
}
#endif
//scalar cleanup loop
for (; x < width; ++x) {
uint8_t * p = &raw[y * pitch + x * 4];
//transparent pixel if alpha is low
if (p[3] < msf_gif_alpha_threshold) {
cooked[y * width + x] = paletteSize - 1;
continue;
}
int dx = x & 3, dy = y & 3;
int k = ditherKernel[dy * 4 + dx];
cooked[y * width + x] =
(msf_imin(65535, p[2] * bmul + (k >> bbits)) >> (16 - rbits - gbits - bbits) & bmask) |
(msf_imin(65535, p[1] * gmul + (k >> gbits)) >> (16 - rbits - gbits ) & gmask) |
msf_imin(65535, p[0] * rmul + (k >> rbits)) >> (16 - rbits );
}
}
count = 0;
MsfTimeLoop("mark") for (int i = 0; i < width * height; ++i) {
used[cooked[i]] = 1;
}
//count used colors, transparent is ignored
MsfTimeLoop("count") for (int j = 0; j < paletteSize - 1; ++j) {
count += used[j];
}
} while (count >= 256 && --depth);
MsfCookedFrame ret = { cooked, depth, count, rdepths[depth], gdepths[depth], bdepths[depth] };
*frame = ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Frame Compression ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static inline void msf_put_code(uint8_t * * writeHead, uint32_t * blockBits, int len, uint32_t code) {
//insert new code into block buffer
int idx = *blockBits / 8;
int bit = *blockBits % 8;
(*writeHead)[idx + 0] |= code << bit ;
(*writeHead)[idx + 1] |= code >> ( 8 - bit);
(*writeHead)[idx + 2] |= code >> (16 - bit);
*blockBits += len;
//prep the next block buffer if the current one is full
if (*blockBits >= 256 * 8) {
*blockBits -= 255 * 8;
(*writeHead) += 256;
(*writeHead)[2] = (*writeHead)[1];
(*writeHead)[1] = (*writeHead)[0];
(*writeHead)[0] = 255;
memset((*writeHead) + 4, 0, 256);
}
}
typedef struct {
int16_t * data;
int len;
int stride;
} MsfStridedList;
static inline void msf_lzw_reset(MsfStridedList * lzw, int tableSize, int stride) { MsfTimeFunc
memset(lzw->data, 0xFF, 4096 * stride * sizeof(int16_t));
lzw->len = tableSize + 2;
lzw->stride = stride;
}
static MsfGifBuffer * msf_compress_frame(void * allocContext, int width, int height, int centiSeconds,
MsfCookedFrame frame, MsfGifState * handle, uint8_t * used, int16_t * lzwMem)
{ MsfTimeFunc
//NOTE: we reserve enough memory for theoretical the worst case upfront because it's a reasonable amount,
// and prevents us from ever having to check size or realloc during compression
int maxBufSize = offsetof(MsfGifBuffer, data) + 32 + 256 * 3 + width * height * 3 / 2; //headers + color table + data
MsfGifBuffer * buffer = (MsfGifBuffer *) MSF_GIF_MALLOC(allocContext, maxBufSize);
if (!buffer) { return NULL; }
uint8_t * writeHead = buffer->data;
MsfStridedList lzw = { lzwMem, 0, 0 };
//allocate tlb
int totalBits = frame.rbits + frame.gbits + frame.bbits;
int tlbSize = (1 << totalBits) + 1;
uint8_t tlb[(1 << 16) + 1]; //only 64k, so stack allocating is fine
//generate palette
typedef struct { uint8_t r, g, b; } Color3;
Color3 table[256] = { { 0 } };
int tableIdx = 1; //we start counting at 1 because 0 is the transparent color
//transparent is always last in the table
tlb[tlbSize-1] = 0;
MsfTimeLoop("table") for (int i = 0; i < tlbSize-1; ++i) {
if (used[i]) {
tlb[i] = tableIdx;
int rmask = (1 << frame.rbits) - 1;
int gmask = (1 << frame.gbits) - 1;
//isolate components
int r = i & rmask;
int g = i >> frame.rbits & gmask;
int b = i >> (frame.rbits + frame.gbits);
//shift into highest bits
r <<= 8 - frame.rbits;
g <<= 8 - frame.gbits;
b <<= 8 - frame.bbits;
table[tableIdx].r = r | r >> frame.rbits | r >> (frame.rbits * 2) | r >> (frame.rbits * 3);
table[tableIdx].g = g | g >> frame.gbits | g >> (frame.gbits * 2) | g >> (frame.gbits * 3);
table[tableIdx].b = b | b >> frame.bbits | b >> (frame.bbits * 2) | b >> (frame.bbits * 3);
if (msf_gif_bgra_flag) {
uint8_t temp = table[tableIdx].r;
table[tableIdx].r = table[tableIdx].b;
table[tableIdx].b = temp;
}
++tableIdx;
}
}
int hasTransparentPixels = used[tlbSize-1];
//SPEC: "Because of some algorithmic constraints however, black & white images which have one color bit
// must be indicated as having a code size of 2."
int tableBits = msf_imax(2, msf_bit_log(tableIdx - 1));
int tableSize = 1 << tableBits;
//NOTE: we don't just compare `depth` field here because it will be wrong for the first frame and we will segfault
MsfCookedFrame previous = handle->previousFrame;
int hasSamePal = frame.rbits == previous.rbits && frame.gbits == previous.gbits && frame.bbits == previous.bbits;
int framesCompatible = hasSamePal && !hasTransparentPixels;
//NOTE: because __attribute__((__packed__)) is annoyingly compiler-specific, we do this unreadable weirdness
char headerBytes[19] = "\x21\xF9\x04\x05\0\0\0\0" "\x2C\0\0\0\0\0\0\0\0\x80";
//NOTE: we need to check the frame number because if we reach into the buffer prior to the first frame,
// we'll just clobber the file header instead, which is a bug
if (hasTransparentPixels && handle->framesSubmitted > 0) {
handle->listTail->data[3] = 0x09; //set the previous frame's disposal to background, so transparency is possible
}
memcpy(&headerBytes[4], &centiSeconds, 2);
memcpy(&headerBytes[13], &width, 2);
memcpy(&headerBytes[15], &height, 2);
headerBytes[17] |= tableBits - 1;
memcpy(writeHead, headerBytes, 18);
writeHead += 18;
//local color table
memcpy(writeHead, table, tableSize * sizeof(Color3));
writeHead += tableSize * sizeof(Color3);
*writeHead++ = tableBits;
//prep block
memset(writeHead, 0, 260);
writeHead[0] = 255;
uint32_t blockBits = 8; //relative to block.head
//SPEC: "Encoders should output a Clear code as the first code of each image data stream."
msf_lzw_reset(&lzw, tableSize, tableIdx);
msf_put_code(&writeHead, &blockBits, msf_bit_log(lzw.len - 1), tableSize);
int lastCode = framesCompatible && frame.pixels[0] == previous.pixels[0]? 0 : tlb[frame.pixels[0]];
MsfTimeLoop("compress") for (int i = 1; i < width * height; ++i) {
//PERF: branching vs. branchless version of this line is observed to have no discernable impact on speed
int color = framesCompatible && frame.pixels[i] == previous.pixels[i]? 0 : tlb[frame.pixels[i]];
int code = (&lzw.data[lastCode * lzw.stride])[color];
if (code < 0) {
//write to code stream
int codeBits = msf_bit_log(lzw.len - 1);
msf_put_code(&writeHead, &blockBits, codeBits, lastCode);
if (lzw.len > 4095) {
//reset buffer code table
msf_put_code(&writeHead, &blockBits, codeBits, tableSize);
msf_lzw_reset(&lzw, tableSize, tableIdx);
} else {
(&lzw.data[lastCode * lzw.stride])[color] = lzw.len;
++lzw.len;
}
lastCode = color;
} else {
lastCode = code;
}
}
//write code for leftover index buffer contents, then the end code
msf_put_code(&writeHead, &blockBits, msf_imin(12, msf_bit_log(lzw.len - 1)), lastCode);
msf_put_code(&writeHead, &blockBits, msf_imin(12, msf_bit_log(lzw.len)), tableSize + 1);
//flush remaining data
if (blockBits > 8) {
int bytes = (blockBits + 7) / 8; //round up
writeHead[0] = bytes - 1;
writeHead += bytes;
}
*writeHead++ = 0; //terminating block
//fill in buffer header and shrink buffer to fit data
buffer->next = NULL;
buffer->size = writeHead - buffer->data;
MsfGifBuffer * moved =
(MsfGifBuffer *) MSF_GIF_REALLOC(allocContext, buffer, maxBufSize, offsetof(MsfGifBuffer, data) + buffer->size);
if (!moved) { MSF_GIF_FREE(allocContext, buffer, maxBufSize); return NULL; }
return moved;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// To-memory API ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const int lzwAllocSize = 4096 * 256 * sizeof(int16_t);
//NOTE: by C standard library conventions, freeing NULL should be a no-op,
// but just in case the user's custom free doesn't follow that rule, we do null checks on our end as well.
static void msf_free_gif_state(MsfGifState * handle) {
if (handle->previousFrame.pixels) MSF_GIF_FREE(handle->customAllocatorContext, handle->previousFrame.pixels,
handle->width * handle->height * sizeof(uint32_t));
if (handle->currentFrame.pixels) MSF_GIF_FREE(handle->customAllocatorContext, handle->currentFrame.pixels,
handle->width * handle->height * sizeof(uint32_t));
if (handle->lzwMem) MSF_GIF_FREE(handle->customAllocatorContext, handle->lzwMem, lzwAllocSize);
for (MsfGifBuffer * node = handle->listHead; node;) {
MsfGifBuffer * next = node->next; //NOTE: we have to copy the `next` pointer BEFORE freeing the node holding it
MSF_GIF_FREE(handle->customAllocatorContext, node, offsetof(MsfGifBuffer, data) + node->size);
node = next;
}
handle->listHead = NULL; //this implicitly marks the handle as invalid until the next msf_gif_begin() call
}
int msf_gif_begin(MsfGifState * handle, int width, int height) { MsfTimeFunc
//NOTE: we cannot stomp the entire struct to zero because we must preserve `customAllocatorContext`.
MsfCookedFrame empty = { 0 }; //god I hate MSVC...
handle->previousFrame = empty;
handle->currentFrame = empty;
handle->width = width;
handle->height = height;
handle->framesSubmitted = 0;
//allocate memory for LZW buffer
//NOTE: Unfortunately we can't just use stack memory for the LZW table because it's 2MB,
// which is more stack space than most operating systems give by default,
// and we can't realistically expect users to be willing to override that just to use our library,
// so we have to allocate this on the heap.
handle->lzwMem = (int16_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, lzwAllocSize);
handle->previousFrame.pixels =
(uint32_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, handle->width * handle->height * sizeof(uint32_t));
handle->currentFrame.pixels =
(uint32_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, handle->width * handle->height * sizeof(uint32_t));
//setup header buffer header (lol)
handle->listHead = (MsfGifBuffer *) MSF_GIF_MALLOC(handle->customAllocatorContext, offsetof(MsfGifBuffer, data) + 32);
if (!handle->listHead || !handle->lzwMem || !handle->previousFrame.pixels || !handle->currentFrame.pixels) {
msf_free_gif_state(handle);
return 0;
}
handle->listTail = handle->listHead;
handle->listHead->next = NULL;
handle->listHead->size = 32;
//NOTE: because __attribute__((__packed__)) is annoyingly compiler-specific, we do this unreadable weirdness
char headerBytes[33] = "GIF89a\0\0\0\0\x70\0\0" "\x21\xFF\x0BNETSCAPE2.0\x03\x01\0\0\0";
memcpy(&headerBytes[6], &width, 2);
memcpy(&headerBytes[8], &height, 2);
memcpy(handle->listHead->data, headerBytes, 32);
return 1;
}
int msf_gif_frame(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes)
{ MsfTimeFunc
if (!handle->listHead) { return 0; }
maxBitDepth = msf_imax(1, msf_imin(16, maxBitDepth));
if (pitchInBytes == 0) pitchInBytes = handle->width * 4;
if (pitchInBytes < 0) pixelData -= pitchInBytes * (handle->height - 1);
uint8_t used[(1 << 16) + 1]; //only 64k, so stack allocating is fine
msf_cook_frame(&handle->currentFrame, pixelData, used, handle->width, handle->height, pitchInBytes,
msf_imin(maxBitDepth, handle->previousFrame.depth + 160 / msf_imax(1, handle->previousFrame.count)));
MsfGifBuffer * buffer = msf_compress_frame(handle->customAllocatorContext, handle->width, handle->height,
centiSecondsPerFame, handle->currentFrame, handle, used, handle->lzwMem);
if (!buffer) { msf_free_gif_state(handle); return 0; }
handle->listTail->next = buffer;
handle->listTail = buffer;
//swap current and previous frames
MsfCookedFrame tmp = handle->previousFrame;
handle->previousFrame = handle->currentFrame;
handle->currentFrame = tmp;
handle->framesSubmitted += 1;
return 1;
}
MsfGifResult msf_gif_end(MsfGifState * handle) { MsfTimeFunc
if (!handle->listHead) { MsfGifResult empty = { 0 }; return empty; }
//first pass: determine total size
size_t total = 1; //1 byte for trailing marker
for (MsfGifBuffer * node = handle->listHead; node; node = node->next) { total += node->size; }
//second pass: write data
uint8_t * buffer = (uint8_t *) MSF_GIF_MALLOC(handle->customAllocatorContext, total);
if (buffer) {
uint8_t * writeHead = buffer;
for (MsfGifBuffer * node = handle->listHead; node; node = node->next) {
memcpy(writeHead, node->data, node->size);
writeHead += node->size;
}
*writeHead++ = 0x3B;
}
//third pass: free buffers
msf_free_gif_state(handle);
MsfGifResult ret = { buffer, total, total, handle->customAllocatorContext };
return ret;
}
void msf_gif_free(MsfGifResult result) { MsfTimeFunc
if (result.data) { MSF_GIF_FREE(result.contextPointer, result.data, result.allocSize); }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// To-file API ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int msf_gif_begin_to_file(MsfGifState * handle, int width, int height, MsfGifFileWriteFunc func, void * filePointer) {
handle->fileWriteFunc = func;
handle->fileWriteData = filePointer;
return msf_gif_begin(handle, width, height);
}
int msf_gif_frame_to_file(MsfGifState * handle, uint8_t * pixelData, int centiSecondsPerFame, int maxBitDepth, int pitchInBytes) {
if (!msf_gif_frame(handle, pixelData, centiSecondsPerFame, maxBitDepth, pitchInBytes)) { return 0; }
//NOTE: this is a somewhat hacky implementation which is not perfectly efficient, but it's good enough for now
MsfGifBuffer * head = handle->listHead;
if (!handle->fileWriteFunc(head->data, head->size, 1, handle->fileWriteData)) { msf_free_gif_state(handle); return 0; }
handle->listHead = head->next;
MSF_GIF_FREE(handle->customAllocatorContext, head, offsetof(MsfGifBuffer, data) + head->size);
return 1;
}
int msf_gif_end_to_file(MsfGifState * handle) {
//NOTE: this is a somewhat hacky implementation which is not perfectly efficient, but it's good enough for now
MsfGifResult result = msf_gif_end(handle);
int ret = (int) handle->fileWriteFunc(result.data, result.dataSize, 1, handle->fileWriteData);
msf_gif_free(result);
return ret;
}
#endif //MSF_GIF_ALREADY_IMPLEMENTED_IN_THIS_TRANSLATION_UNIT
#endif //MSF_GIF_IMPL
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2021 Miles Fogle
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

Some files were not shown because too many files have changed in this diff Show More