More raylib examples.

This commit is contained in:
Christoffer Lerno
2025-12-01 22:33:01 +01:00
parent a2aa9fae6b
commit 0bc5cbca74
4 changed files with 535 additions and 2 deletions

View File

@@ -0,0 +1,292 @@
/*******************************************************************************************
*
* 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)
* converted to C3 by Christoffer Lerno
*
********************************************************************************************/
module raylib_camera_platformer;
import raylib55;
const G = 400;
const float PLAYER_JUMP_SPD = 350;
const float PLAYER_HOR_SPD = 200;
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
struct Player
{
RLVector2 position;
float speed;
bool can_jump;
}
struct EnvItem
{
RLRectangle rect;
int blocking;
RLColor color;
}
alias CameraUpdateFn = fn void(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height);
enum CameraUpdateType : (ZString text, CameraUpdateFn func)
{
CENTER = { "Follow player center", &update_camera_center },
CENTER_INSIDE_MAP = { "Follow player center, but clamp to map edges", &update_camera_center_inside_map },
CENTER_SMOOTH_FOLLOW = { "Follow player center; smoothed", &update_camera_center_smooth_follow },
EVEN_OUT_ON_LANDING = { "Follow player center horizontally; update player center vertically after landing", &update_camera_even_out_on_landing },
PLAYER_BOUNDS_PUSH = { "Player push camera on getting too close to screen edge", &update_camera_player_bounds_push }
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 450;
rl::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [core] example - 2d camera platformer");
Player player = {
.position = { 400, 280 },
.speed = 0,
.can_jump = false
};
EnvItem[*] env_items = {
{{ 0, 0, 1000, 400 }, 0, rl::LIGHTGRAY },
{{ 0, 400, 1000, 200 }, 1, rl::GRAY },
{{ 300, 200, 400, 10 }, 1, rl::GRAY },
{{ 250, 300, 100, 10 }, 1, rl::GRAY },
{{ 650, 300, 100, 10 }, 1, rl::GRAY }
};
RLCamera2D camera = {
.target = player.position,
.offset = { SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f },
.rotation = 0.0f,
.zoom = 1.0f
};
CameraUpdateType camera_option = CENTER;
rl::set_target_fps(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!rl::window_should_close())
{
// Update
//----------------------------------------------------------------------------------
float delta_time = rl::get_frame_time();
update_player(&player, &env_items, delta_time);
camera.zoom += ((float)rl::get_mouse_wheel_move() * 0.05f);
switch
{
case camera.zoom > 3.0f: camera.zoom = 3.0f;
case camera.zoom < 0.25f: camera.zoom = 0.25f;
}
if (rl::is_key_pressed(R))
{
camera.zoom = 1.0f;
player.position = { 400, 280 };
}
if (rl::is_key_pressed(C)) camera_option = CameraUpdateType.from_ordinal(((int)camera_option + 1) % (int)CameraUpdateType.len);
// Call update camera function by its pointer
camera_option.func(&camera, &player, &env_items, delta_time, SCREEN_WIDTH, SCREEN_HEIGHT);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl::@drawing()
{
rl::clear_background(rl::LIGHTGRAY);
rl::@mode2d(camera)
{
foreach (item : env_items) rl::draw_rectangle_rec(item.rect, item.color);
RLRectangle player_rect = { player.position.x - 20, player.position.y - 40, 40.0f, 40.0f };
rl::draw_rectangle_rec(player_rect, rl::RED);
rl::draw_circle_v(player.position, 5.0f, rl::GOLD);
};
rl::draw_text("Controls:", 20, 20, 10, rl::BLACK);
rl::draw_text("- Right/Left to move", 40, 40, 10, rl::DARKGRAY);
rl::draw_text("- Space to jump", 40, 60, 10, rl::DARKGRAY);
rl::draw_text("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, rl::DARKGRAY);
rl::draw_text("- C to change camera mode", 40, 100, 10, rl::DARKGRAY);
rl::draw_text("Current camera mode:", 20, 120, 10, rl::BLACK);
rl::draw_text(camera_option.text, 40, 140, 10, rl::DARKGRAY);
};
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl::close_window(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
fn void update_player(Player* player, EnvItem[] env_items, float delta)
{
if (rl::is_key_down(LEFT)) player.position.x -= PLAYER_HOR_SPD * delta;
if (rl::is_key_down(RIGHT)) player.position.x += PLAYER_HOR_SPD * delta;
if (rl::is_key_down(SPACE) && player.can_jump)
{
player.speed = -PLAYER_JUMP_SPD;
player.can_jump = false;
}
bool hit_obstacle = false;
foreach (item : env_items)
{
RLVector2* p = &player.position;
if (item.blocking
&& item.rect.x <= p.x
&& item.rect.x + item.rect.width >= p.x
&& item.rect.y >= p.y
&& item.rect.y <= p.y + player.speed * delta)
{
hit_obstacle = true;
player.speed = 0.0f;
p.y = item.rect.y;
break;
}
}
if (hit_obstacle)
{
player.can_jump = true;
}
else
{
player.position.y += player.speed * delta;
player.speed += G * delta;
player.can_jump = false;
}
}
fn void update_camera_center(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
{
camera.offset = { width / 2.0f, height / 2.0f };
camera.target = player.position;
}
fn void update_camera_center_inside_map(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
{
camera.target = player.position;
camera.offset = { width / 2.0f, height / 2.0f };
float min_x = 1000;
float min_y = 1000;
float max_x = -1000;
float max_y = -1000;
foreach (item : env_items)
{
min_x = min(item.rect.x, min_x);
max_x = max(item.rect.x + item.rect.width, max_x);
min_y = min(item.rect.y, min_y);
max_y = max(item.rect.y + item.rect.height, max_y);
}
RLVector2 max = rl::get_world_to_screen2d({ max_x, max_y }, *camera);
RLVector2 min = rl::get_world_to_screen2d({ min_x, min_y }, *camera);
if (max.x < width) camera.offset.x = width - (max.x - width / 2.0f);
if (max.y < height) camera.offset.y = height - (max.y - height / 2.0f);
if (min.x > 0) camera.offset.x = width / 2.0f - min.x;
if (min.y > 0) camera.offset.y = height / 2.0f - min.y;
}
fn void update_camera_center_smooth_follow(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
{
const float MIN_SPEED = 30;
const float MIN_EFFECT_LENGTH = 10;
const float FRACTION_SPEED = 0.8f;
camera.offset = { width / 2.0f, height / 2.0f };
float length = player.position.distance(camera.target);
if (length > MIN_EFFECT_LENGTH)
{
float speed = max(FRACTION_SPEED * length, MIN_SPEED);
camera.target += (player.position - camera.target) * speed * delta / length;
}
}
fn void update_camera_even_out_on_landing(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
{
const float EVEN_OUT_SPEED = 700;
static bool evening_out = false;
static float even_out_target;
camera.offset = { width / 2.0f, height / 2.0f };
camera.target.x = player.position.x;
if (evening_out)
{
if (even_out_target > camera.target.y)
{
camera.target.y += EVEN_OUT_SPEED * delta;
if (camera.target.y > even_out_target)
{
camera.target.y = even_out_target;
evening_out = false;
}
}
else
{
camera.target.y -= EVEN_OUT_SPEED * delta;
if (camera.target.y < even_out_target)
{
camera.target.y = even_out_target;
evening_out = false;
}
}
}
else
{
if (player.can_jump && player.speed == 0 && player.position.y != camera.target.y)
{
evening_out = true;
even_out_target = player.position.y;
}
}
}
fn void update_camera_player_bounds_push(RLCamera2D* camera, Player* player, EnvItem[] env_items, float delta, int width, int height)
{
const RLVector2 BBOX = { 0.2f, 0.2f };
RLVector2 bboxWorldMin = rl::get_screen_to_world2d({ (1 - BBOX.x) * 0.5f * width, (1 - BBOX.y) * 0.5f*height }, *camera);
RLVector2 bboxWorldMax = rl::get_screen_to_world2d({ (1 + BBOX.x) * 0.5f * width, (1 + BBOX.y) * 0.5f*height }, *camera);
camera.offset = { (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

@@ -0,0 +1,121 @@
/*******************************************************************************************
*
* raylib [core] example - delta time
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
*
* 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)
* converted to C3 by Christoffer Lerno
*
********************************************************************************************/
module raylib_delta_time;
import raylib55;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 450;
rl::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [core] example - delta time");
int current_fps = 60;
// Store the position for the both of the circles
RLVector2 delta_circle = { 0, SCREEN_HEIGHT / 3.0f };
RLVector2 frame_circle = { 0, SCREEN_HEIGHT * (2.0f / 3.0f) };
// The speed applied to both circles
const float SPEED = 10.0f;
const float CIRCLE_RADIUS = 32.0f;
rl::set_target_fps(current_fps);
//--------------------------------------------------------------------------------------
// Main game loop
while (!rl::window_should_close()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Adjust the FPS target based on the mouse wheel
float mouse_wheel = rl::get_mouse_wheel_move();
if (mouse_wheel)
{
current_fps += (int)mouse_wheel;
if (current_fps < 0) current_fps = 0;
rl::set_target_fps(current_fps);
}
// 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
delta_circle.x += rl::get_frame_time() * 6 * SPEED;
// This circle can move faster or slower visually depending on the FPS
frame_circle.x += 0.1f * SPEED;
// If either circle is off the screen, reset it back to the start
if (delta_circle.x > SCREEN_WIDTH) delta_circle.x = 0;
if (frame_circle.x > SCREEN_WIDTH) frame_circle.x = 0;
// Reset both circles positions
if (rl::is_key_pressed(R))
{
delta_circle.x = 0;
frame_circle.x = 0;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl::@drawing()
{
rl::clear_background(rl::RAYWHITE);
// Draw both circles to the screen
rl::draw_circle_v(delta_circle, CIRCLE_RADIUS, rl::RED);
rl::draw_circle_v(frame_circle, CIRCLE_RADIUS, rl::BLUE);
// Draw the help text
// Determine what help text to show depending on the current FPS target
ZString fps_text = null;
if (current_fps <= 0)
{
fps_text = rl::text_format("FPS: unlimited (%i)", rl::get_fps());
}
else
{
fps_text = rl::text_format("FPS: %i (target: %i)", rl::get_fps(), current_fps);
}
rl::draw_text(fps_text, 10, 10, 20, rl::DARKGRAY);
rl::draw_text(rl::text_format("Frame time: %02.02f ms", rl::get_frame_time()), 10, 30, 20, rl::DARKGRAY);
rl::draw_text("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, rl::DARKGRAY);
// Draw the text above the circles
rl::draw_text("FUNC: x += GetFrameTime()*speed", 10, 90, 20, rl::RED);
rl::draw_text("FUNC: x += speed", 10, 240, 20, rl::BLUE);
};
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl::close_window(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@@ -0,0 +1,120 @@
/*******************************************************************************************
*
* 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)
* converted to C3 by Christoffer Lerno
*
********************************************************************************************/
module raylib_input_gestures;
import raylib55;
const MAX_GESTURE_STRINGS = 20;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn int main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 450;
rl::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [core] example - input gestures");
RLRectangle touch_area = { 220, 10, SCREEN_WIDTH - 230.0f, SCREEN_HEIGHT - 20.0f };
int gestures_count = 0;
ZString[MAX_GESTURE_STRINGS] gesture_strings;
RLGesture current_gesture = NONE;
RLGesture last_gesture = NONE;
//SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected
rl::set_target_fps(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!rl::window_should_close()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
last_gesture = current_gesture;
current_gesture = rl::get_gesture_detected();
RLVector2 touch_position = rl::get_touch_position(0);
if (rl::check_collision_point_rec(touch_position, touch_area) && (current_gesture != NONE))
{
if (current_gesture != last_gesture)
{
// Reset gestures strings
if (gestures_count >= MAX_GESTURE_STRINGS)
{
foreach (&s : gesture_strings) *s = "";
gestures_count = 0;
}
// Store gesture string
switch (current_gesture)
{
case TAP: gesture_strings[gestures_count++] = "GESTURE TAP";
case DOUBLETAP: gesture_strings[gestures_count++] = "GESTURE DOUBLETAP";
case HOLD: gesture_strings[gestures_count++] = "GESTURE HOLD";
case DRAG: gesture_strings[gestures_count++] = "GESTURE DRAG";
case SWIPE_RIGHT: gesture_strings[gestures_count++] = "GESTURE SWIPE RIGHT";
case SWIPE_LEFT: gesture_strings[gestures_count++] = "GESTURE SWIPE LEFT";
case SWIPE_UP: gesture_strings[gestures_count++] = "GESTURE SWIPE UP";
case SWIPE_DOWN: gesture_strings[gestures_count++] = "GESTURE SWIPE DOWN";
case PINCH_IN: gesture_strings[gestures_count++] = "GESTURE PINCH IN";
case PINCH_OUT: gesture_strings[gestures_count++] = "GESTURE PINCH OUT";
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
rl::@drawing()
{
rl::clear_background(rl::RAYWHITE);
rl::draw_rectangle_rec(touch_area, rl::GRAY);
rl::draw_rectangle(225, 15, SCREEN_WIDTH - 240, SCREEN_HEIGHT - 30, rl::RAYWHITE);
rl::draw_text("GESTURES TEST AREA", SCREEN_WIDTH - 270, SCREEN_HEIGHT - 40, 20, rl::GRAY.fade(0.5f));
for (int i = 0; i < gestures_count; i++)
{
rl::draw_rectangle(10, 30 + 20 * i, 200, 20, rl::LIGHTGRAY.fade(i % 2 ? 0.3f : 0.5f));
rl::draw_text(gesture_strings[i], 35, 36 + 20 * i, 10, i < gestures_count - 1 ? rl::DARKGRAY : rl::MAROON);
}
rl::draw_rectangle_lines(10, 29, 200, SCREEN_HEIGHT - 50, rl::GRAY);
rl::draw_text("DETECTED GESTURES", 50, 15, 10, rl::GRAY);
if (current_gesture != NONE) rl::draw_circle_v(touch_position, 30, rl::MAROON);
};
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
rl::close_window(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@@ -1,5 +1,3 @@
module raylib_models;
import raylib55;
/*******************************************************************************************
*
* raylib [models] example - animation playing
@@ -24,6 +22,8 @@ import raylib55;
*
********************************************************************************************/
module raylib_models;
import raylib55;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------