← ziglang.inraylib-zigGitHub

input virtual controls

★★☆☆by GreenSnakeLinux (@GreenSnakeLinux)

There is no browser build of this example yet.

Is it the same as C?

//! raylib [core] example - input virtual controls
//!
//! Zig-API translation of examples/core/core_input_virtual_controls.c (raylib 6.2).
//! Example contributed by GreenSnakeLinux (@GreenSnakeLinux),
//! reviewed by Ramon Santamaria (@raysan5)
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2024-2025 GreenSnakeLinux (@GreenSnakeLinux) and Ramon Santamaria (@raysan5)

const rl = @import("raylib");

const PadButton = enum { up, left, right, down };

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

    rl.initWindow(screen_width, screen_height, "raylib [core] example - input virtual controls");
    defer rl.closeWindow(); // Close window and OpenGL context

    const pad_position: rl.Vector2 = .{ .x = 100, .y = 350 };
    const button_radius: f32 = 30;

    const button_positions = [_]rl.Vector2{
        .{ .x = pad_position.x, .y = pad_position.y - button_radius * 1.5 }, // Up
        .{ .x = pad_position.x - button_radius * 1.5, .y = pad_position.y }, // Left
        .{ .x = pad_position.x + button_radius * 1.5, .y = pad_position.y }, // Right
        .{ .x = pad_position.x, .y = pad_position.y + button_radius * 1.5 }, // Down
    };

    const up = button_positions[0];
    const left = button_positions[1];
    const right = button_positions[2];
    const down = button_positions[3];
    const arrow_tris = [_][3]rl.Vector2{
        // Up
        .{
            .{ .x = up.x, .y = up.y - 12 },
            .{ .x = up.x - 9, .y = up.y + 9 },
            .{ .x = up.x + 9, .y = up.y + 9 },
        },
        // Left
        .{
            .{ .x = left.x + 9, .y = left.y - 9 },
            .{ .x = left.x - 12, .y = left.y },
            .{ .x = left.x + 9, .y = left.y + 9 },
        },
        // Right
        .{
            .{ .x = right.x + 12, .y = right.y },
            .{ .x = right.x - 9, .y = right.y - 9 },
            .{ .x = right.x - 9, .y = right.y + 9 },
        },
        // Down
        .{
            .{ .x = down.x - 9, .y = down.y - 9 },
            .{ .x = down.x, .y = down.y + 12 },
            .{ .x = down.x + 9, .y = down.y - 9 },
        },
    };

    const button_label_colors = [_]rl.Color{
        .yellow, // Up
        .blue, // Left
        .red, // Right
        .green, // Down
    };

    var player_position: rl.Vector2 = .{ .x = screen_width / 2.0, .y = screen_height / 2.0 };
    const player_speed: f32 = 75;

    rl.setTargetFPS(60);

    // Main game loop
    while (!rl.windowShouldClose()) { // Detect window close button or ESC key
        // Update
        const touching = rl.getTouchPointCount() > 0;
        // Use touch position, or mouse position
        const input_position = if (touching) rl.getTouchPosition(0) else rl.getMousePosition();

        // Make sure user is pressing left mouse button if they're from desktop
        var pressed_button: ?PadButton = null;
        if (touching or rl.isMouseButtonDown(.left)) {
            // Find nearest D-Pad button to the input position
            for (button_positions, 0..) |position, i| {
                const dist_x = @abs(position.x - input_position.x);
                const dist_y = @abs(position.y - input_position.y);

                if (dist_x + dist_y < button_radius) {
                    pressed_button = @fromBackingInt(@intCast(i));
                    break;
                }
            }
        }

        // Move player according to pressed button
        if (pressed_button) |button| switch (button) {
            .up => player_position.y -= player_speed * rl.getFrameTime(),
            .left => player_position.x -= player_speed * rl.getFrameTime(),
            .right => player_position.x += player_speed * rl.getFrameTime(),
            .down => player_position.y += player_speed * rl.getFrameTime(),
        };

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

        rl.clearBackground(.ray_white);

        // Draw world
        rl.drawCircleV(player_position, 50, .maroon);

        // Draw GUI
        for (button_positions, arrow_tris, button_label_colors, 0..) |position, tri, label_color, i| {
            const pressed = if (pressed_button) |button| @backingInt(button) == i else false;
            rl.drawCircleV(position, button_radius, if (pressed) .dark_gray else .black);

            rl.drawTriangle(tri[0], tri[1], tri[2], label_color);
        }

        rl.drawText("move the player with D-Pad buttons", 10, 10, 20, .dark_gray);
    }
}
/*******************************************************************************************
*
*   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;
}

From raylib 6.2. The original on GitHub.