← ziglang.inraylib-zigGitHub

drag puzzle

★☆☆☆by Gabriel Piangers (@gabriel-piangers)

There is no browser build of this example yet.

Is it the same as C?

//! raylib [shapes] example - drag puzzle
//!
//! Zig-API translation of examples/shapes/shapes_drag_puzzle.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2026 Gabriel Piangers (@gabriel-piangers)

const rl = @import("raylib");
const rm = rl.math;

const Circle = struct {
    center: rl.Vector2,
    radius: f32,
};

const Triangle = struct {
    v1: rl.Vector2,
    v2: rl.Vector2,
    v3: rl.Vector2,

    fn contains(tri: Triangle, point: rl.Vector2) bool {
        return rl.checkCollisionPointTriangle(point, tri.v1, tri.v2, tri.v3);
    }
};

pub fn main() void {
    // Initialization
    const screen_width = 800;
    const screen_height = 450;

    rl.initWindow(screen_width, screen_height, "raylib [shapes] example - drag puzzle");
    defer rl.closeWindow(); // Close window and OpenGL context

    // Rectangle
    var rec: rl.Rectangle = .{ .x = screen_width / 2 - 250, .y = screen_height / 2 + 50, .width = 100.0, .height = 100.0 };
    const rec_area: rl.Rectangle = .{ .x = screen_width / 2 - 60, .y = screen_height / 2 - 110, .width = 110.0, .height = 110.0 };
    var rec_picked_up = false;

    // Circle
    var circ: Circle = .{ .center = .{ .x = screen_width / 2, .y = screen_height / 2 + 100 }, .radius = 50.0 };
    const circ_area: Circle = .{ .center = .{ .x = screen_width / 2 - 195, .y = screen_height / 2 - 55 }, .radius = 55.0 };
    var circ_picked_up = false;

    // Triangle
    var tri: Triangle = .{ .v1 = .{ .x = 600, .y = 282 }, .v2 = .{ .x = 550, .y = 369 }, .v3 = .{ .x = 650, .y = 369 } };
    const tri_area: Triangle = .{ .v1 = .{ .x = 600, .y = 115 }, .v2 = .{ .x = 540, .y = 222 }, .v3 = .{ .x = 660, .y = 222 } };
    var tri_picked_up = false;

    var mouse_offset: rl.Vector2 = .{ .x = 0.0, .y = 0.0 }; // Offset of the mouse relative to the object's pivot point

    rl.setTargetFPS(60);

    // Main game loop
    while (!rl.windowShouldClose()) { // Detect window close button or ESC key
        // Update
        const mouse_position = rl.getMousePosition();

        // Detect object pickup input
        if (rl.isMouseButtonPressed(.left)) {
            if (rl.checkCollisionPointRec(mouse_position, rec)) {
                rec_picked_up = true;
                mouse_offset = .{ .x = rec.x - mouse_position.x, .y = rec.y - mouse_position.y };
            } else if (rl.checkCollisionPointCircle(mouse_position, circ.center, circ.radius)) {
                circ_picked_up = true;
                mouse_offset = .{ .x = circ.center.x - mouse_position.x, .y = circ.center.y - mouse_position.y };
            } else if (tri.contains(mouse_position)) {
                tri_picked_up = true;
                mouse_offset = .{ .x = tri.v1.x - mouse_position.x, .y = tri.v1.y - mouse_position.y }; // Uses v1 as the pivot point
            }
        }

        // Detect object drop input
        if (rl.isMouseButtonReleased(.left)) {
            if (rec_picked_up) {
                rec_picked_up = false;
            } else if (circ_picked_up) {
                circ_picked_up = false;
            } else if (tri_picked_up) {
                tri_picked_up = false;
            }
        }

        // Rectangle update
        if (rec_picked_up) {
            rec.x = mouse_position.x + mouse_offset.x;
            rec.y = mouse_position.y + mouse_offset.y;
        }
        const rec_col = rl.getCollisionRec(rec_area, rec);
        const rec_placed = rec_col.width == rec.width and rec_col.height == rec.height;

        // Circle update
        if (circ_picked_up) {
            circ.center.x = mouse_position.x + mouse_offset.x;
            circ.center.y = mouse_position.y + mouse_offset.y;
        }
        const circ_placed = rm.vector2Distance(circ.center, circ_area.center) < circ_area.radius - circ.radius;

        // Triangle update
        if (tri_picked_up) {
            const v2_offset: rl.Vector2 = .{ .x = tri.v2.x - tri.v1.x, .y = tri.v2.y - tri.v1.y };
            const v3_offset: rl.Vector2 = .{ .x = tri.v3.x - tri.v1.x, .y = tri.v3.y - tri.v1.y };

            tri.v1 = .{ .x = mouse_position.x + mouse_offset.x, .y = mouse_position.y + mouse_offset.y };
            tri.v2 = .{ .x = tri.v1.x + v2_offset.x, .y = tri.v1.y + v2_offset.y };
            tri.v3 = .{ .x = tri.v1.x + v3_offset.x, .y = tri.v1.y + v3_offset.y };
        }
        // NOTE: upstream checks v2 twice (and never v3); kept for identical behavior
        const tri_placed = tri_area.contains(tri.v1) and tri_area.contains(tri.v2) and tri_area.contains(tri.v2);

        // Draw
        rl.beginDrawing();
        defer rl.endDrawing();

        rl.clearBackground(.ray_white);

        rl.drawRectangleLinesEx(rec_area, 2.0, if (rec_placed) .green else .red);
        rl.drawCircleLinesEx(circ_area.center, circ_area.radius, 2.0, if (circ_placed) .green else .red);
        rl.drawTriangleLinesEx(tri_area.v1, tri_area.v2, tri_area.v3, 2.0, if (tri_placed) .green else .red);

        // Draws objects that are not picked up first
        if (!tri_picked_up) rl.drawTriangle(tri.v1, tri.v2, tri.v3, .violet);
        if (!circ_picked_up) rl.drawCircleV(circ.center, circ.radius, .blue);
        if (!rec_picked_up) rl.drawRectangleRec(rec, .orange);

        // Draws the object that is being dragged on top of others
        if (tri_picked_up) rl.drawTriangle(tri.v1, tri.v2, tri.v3, .violet);
        if (circ_picked_up) rl.drawCircleV(circ.center, circ.radius, .blue);
        if (rec_picked_up) rl.drawRectangleRec(rec, .orange);

        rl.drawText("Use mouse to drag and drop the objects into the right spot!", 10, 10, 20, .gray);
    }
}
/*******************************************************************************************
*
*   raylib [shapes] example - drag puzzle
*
*   Example complexity rating: [★☆☆☆] 1/4
*
*   Example originally created with raylib 6.0, last time updated with raylib 6.0
*
*   Example contributed by Gabriel Piangers (@gabriel-piangers) 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) 2026 Gabriel Piangers (@gabriel-piangers)
*
********************************************************************************************/

#include "raylib.h"
#include "raymath.h"

//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct {
    Vector2 center;
    float radius;
} Circle;

typedef struct {
    Vector2 v1;
    Vector2 v2;
    Vector2 v3;
} Triangle;

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
    // Initialization
    //--------------------------------------------------------------------------------------
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [shapes] example - drag puzzle");

    // Rectangle
    Rectangle rec = { screenWidth/2 - 250, screenHeight/2 + 50, 100.0f, 100.0f };
    Rectangle recArea = { screenWidth/2 - 60, screenHeight/2 - 110, 110.0f, 110.0f };
    bool recPickedUp = false;

    // Circle
    Circle circ = { screenWidth/2, screenHeight/2 + 100, 50.0f };
    Circle circArea = { screenWidth/2 - 195, screenHeight/2 - 55, 55.0f };
    bool circPickedUp = false;

    // Triangle
    Triangle tri = { { 600, 282 }, { 550, 369 }, { 650, 369 } };
    Triangle triArea = { { 600, 115 }, { 540, 222 }, { 660, 222 } };
    bool triPickedUp = false;

    Vector2 mouseOffset = { 0.0f, 0.0f };    // Stores the offset of the mouse relative to the object's pivot point

    SetTargetFPS(60);
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        // Update
        //----------------------------------------------------------------------------------
        Vector2 mousePosition = GetMousePosition();
        bool recPlaced = false;
        bool circPlaced = false;
        bool triPlaced = false;

        // Detect object pickup input
        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, rec))
        {
            recPickedUp = true;
            mouseOffset = (Vector2) { rec.x - mousePosition.x, rec.y - mousePosition.y };
        }
        else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointCircle(mousePosition, circ.center, circ.radius))
        {
            circPickedUp = true;
            mouseOffset = (Vector2) { circ.center.x - mousePosition.x, circ.center.y - mousePosition.y };
        }
        else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointTriangle(mousePosition, tri.v1, tri.v2, tri.v3))
        {
            triPickedUp = true;
            mouseOffset = (Vector2) { tri.v1.x - mousePosition.x, tri.v1.y - mousePosition.y }; // Uses v1 as the pivot point
        }

        // Detect object drop input
        if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && recPickedUp) recPickedUp = false;
        else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && circPickedUp) circPickedUp = false;
        else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && triPickedUp) triPickedUp = false;

        // Rectangle update
        if (recPickedUp)
        {
            rec.x = mousePosition.x + mouseOffset.x;
            rec.y = mousePosition.y + mouseOffset.y;
        }
        Rectangle RecCol = GetCollisionRec(recArea, rec);
        if (RecCol.width == rec.width && RecCol.height == rec.height) recPlaced = true;

        // Circle update
        if (circPickedUp)
        {
            circ.center.x = mousePosition.x + mouseOffset.x;
            circ.center.y = mousePosition.y + mouseOffset.y;
        }
        if (Vector2Distance(circ.center, circArea.center) < circArea.radius - circ.radius) circPlaced = true;

        // Triangle update
        if (triPickedUp)
        {
            Vector2 v2Offset = { tri.v2.x - tri.v1.x, tri.v2.y - tri.v1.y };
            Vector2 v3Offset = { tri.v3.x - tri.v1.x, tri.v3.y - tri.v1.y };

            tri.v1 = (Vector2) { mousePosition.x + mouseOffset.x, mousePosition.y + mouseOffset.y };
            tri.v2 = (Vector2) { tri.v1.x + v2Offset.x, tri.v1.y + v2Offset.y };
            tri.v3 = (Vector2) { tri.v1.x + v3Offset.x, tri.v1.y + v3Offset.y };
        }
        if (
            CheckCollisionPointTriangle(tri.v1, triArea.v1, triArea.v2, triArea.v3) &&
            CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3) &&
            CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3)
        ) triPlaced = true;
        //----------------------------------------------------------------------------------

        // Draw
        //----------------------------------------------------------------------------------
        BeginDrawing();

            ClearBackground(RAYWHITE);

            DrawRectangleLinesEx(recArea, 2.0f, recPlaced ? GREEN : RED);
            DrawCircleLinesEx(circArea.center, circArea.radius, 2.0f, circPlaced ? GREEN : RED);
            DrawTriangleLinesEx(triArea.v1, triArea.v2, triArea.v3, 2.0f, triPlaced ? GREEN : RED);

            // Draws objects that are not picked up first
            if (!triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
            if (!circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
            if (!recPickedUp) DrawRectangleRec(rec, ORANGE);

            // Draws the object that is being dragged on top of others
            if (triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
            if (circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
            if (recPickedUp) DrawRectangleRec(rec, ORANGE);

            DrawText("Use mouse to drag and drop the objects into the right spot!", 10, 10, 20, GRAY);
        EndDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    //--------------------------------------------------------------------------------------
    CloseWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

From raylib 6.2. The original on GitHub.