← ziglang.inraylib-zigGitHub

ellipse collision

★★☆☆by Ziya (@Monjaris)

There is no browser build of this example yet.

Is it the same as C?

//! raylib [shapes] example - ellipse collision
//!
//! Zig-API translation of examples/shapes/shapes_ellipse_collision.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2025 Ziya (@Monjaris)

const std = @import("std");
const rl = @import("raylib");

const Ellipse = struct {
    center: rl.Vector2,
    rx: f32,
    ry: f32,

    /// Check if point is inside ellipse
    fn containsPoint(e: Ellipse, point: rl.Vector2) bool {
        const dx = (point.x - e.center.x) / e.rx;
        const dy = (point.y - e.center.y) / e.ry;
        return dx * dx + dy * dy <= 1.0;
    }

    /// Radial distance from center to ellipse boundary in direction theta:
    /// r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2)
    fn radius(e: Ellipse, cos_t: f32, sin_t: f32) f32 {
        return (e.rx * e.ry) / @sqrt((e.ry * cos_t) * (e.ry * cos_t) + (e.rx * sin_t) * (e.rx * sin_t));
    }

    /// Check if two ellipses collide
    /// Uses radial boundary distance in the direction between centers — scales correctly with radii
    fn collides(e1: Ellipse, e2: Ellipse) bool {
        const dx = e2.center.x - e1.center.x;
        const dy = e2.center.y - e1.center.y;
        const dist = @sqrt(dx * dx + dy * dy);

        // Ellipses are on top of each other
        if (dist == 0.0) return true;

        const theta = std.math.atan2(dy, dx);
        const cos_t = @cos(theta);
        const sin_t = @sin(theta);

        return dist <= e1.radius(cos_t, sin_t) + e2.radius(cos_t, sin_t);
    }

    fn draw(e: Ellipse, color: rl.Color) void {
        rl.drawEllipse(@intFromFloat(e.center.x), @intFromFloat(e.center.y), e.rx, e.ry, color);
    }

    fn drawLines(e: Ellipse, color: rl.Color) void {
        rl.drawEllipseLines(@intFromFloat(e.center.x), @intFromFloat(e.center.y), e.rx, e.ry, color);
    }
};

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

    rl.initWindow(screen_width, screen_height, "raylib [shapes] example - ellipse collision");
    defer rl.closeWindow();
    rl.setTargetFPS(60);

    var ellipse_a: Ellipse = .{ .center = .{ .x = screen_width / 4.0, .y = screen_height / 2.0 }, .rx = 120.0, .ry = 70.0 };
    var ellipse_b: Ellipse = .{ .center = .{ .x = screen_width * 3 / 4.0, .y = screen_height / 2.0 }, .rx = 90.0, .ry = 140.0 };

    var controlled: enum { a, b } = .a;

    // Main game loop
    while (!rl.windowShouldClose()) { // Detect window close button or ESC key
        // Update
        if (rl.isKeyPressed(.a)) controlled = .a;
        if (rl.isKeyPressed(.b)) controlled = .b;

        switch (controlled) {
            .a => ellipse_a.center = rl.getMousePosition(),
            .b => ellipse_b.center = rl.getMousePosition(),
        }

        const ellipses_collide = ellipse_a.collides(ellipse_b);

        const mouse_in_a = ellipse_a.containsPoint(rl.getMousePosition());
        const mouse_in_b = ellipse_b.containsPoint(rl.getMousePosition());

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

        rl.clearBackground(.ray_white);

        ellipse_a.draw(if (ellipses_collide) .red else .blue);
        ellipse_b.draw(if (ellipses_collide) .red else .green);

        ellipse_a.drawLines(.white);
        ellipse_b.drawLines(.white);

        rl.drawCircleV(ellipse_a.center, 4, .white);
        rl.drawCircleV(ellipse_b.center, 4, .white);

        if (ellipses_collide) {
            rl.drawText("ELLIPSES COLLIDE", screen_width / 2 - 120, 40, 28, .red);
        } else {
            rl.drawText("NO COLLISION", screen_width / 2 - 80, 40, 28, .dark_gray);
        }

        rl.drawText(if (controlled == .a) "Controlling: A" else "Controlling: B", 20, screen_height - 40, 20, .yellow);

        if (mouse_in_a and controlled != .a) rl.drawText("Mouse inside ellipse A", 20, screen_height - 70, 20, .blue);
        if (mouse_in_b and controlled != .b) rl.drawText("Mouse inside ellipse B", 20, screen_height - 70, 20, .green);

        rl.drawText("Press [A] or [B] to switch control", 20, 20, 20, .gray);
    }
}
/*******************************************************************************************
*
*   raylib [shapes] example - ellipse collision
*
*   Example complexity rating: [★★☆☆] 2/4
*
*   Example originally created with raylib 5.5, last time updated with raylib 5.5
*
*   Example contributed by Ziya (@Monjaris)
*
*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
*   BSD-like license that allows static linking with closed source software
*
*   Copyright (c) 2025 Ziya (@Monjaris)
*
********************************************************************************************/

#include "raylib.h"
#include <math.h>

// Check if point is inside ellipse
static bool CheckCollisionPointEllipse(Vector2 point, Vector2 center, float rx, float ry)
{
    float dx = (point.x - center.x)/rx;
    float dy = (point.y - center.y)/ry;
    return (dx*dx + dy*dy) <= 1.0f;
}

// Check if two ellipses collide
// Uses radial boundary distance in the direction between centers — scales correctly with radii
static bool CheckCollisionEllipses(Vector2 c1, float rx1, float ry1, Vector2 c2, float rx2, float ry2)
{
    float dx = c2.x - c1.x;
    float dy = c2.y - c1.y;
    float dist = sqrtf(dx*dx + dy*dy);

    // Ellipses are on top of each other
    if (dist == 0.0f) return true;

    float theta = atan2f(dy, dx);
    float cosT = cosf(theta);
    float sinT = sinf(theta);

    // Radial distance from center to ellipse boundary in direction theta
    // r(theta) = (rx * ry) / sqrt((ry*cos)^2 + (rx*sin)^2)
    float r1 = (rx1*ry1)/sqrtf((ry1*cosT)*(ry1*cosT) + (rx1*sinT)*(rx1*sinT));
    float r2 = (rx2*ry2)/sqrtf((ry2*cosT)*(ry2*cosT) + (rx2*sinT)*(rx2*sinT));

    return dist <= (r1 + r2);
}

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

    InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ellipse collision");
    SetTargetFPS(60);

    Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };
    float ellipseARx = 120.0f;
    float ellipseARy = 70.0f;

    Vector2 ellipseBCenter = { (float)screenWidth*3/4, (float)screenHeight/2 };
    float ellipseBRx = 90.0f;
    float ellipseBRy = 140.0f;

    // 0 = controlling A, 1 = controlling B
    int controlled = 0;

    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        // Update
        //----------------------------------------------------------------------------------
        if (IsKeyPressed(KEY_A)) controlled = 0;
        if (IsKeyPressed(KEY_B)) controlled = 1;

        if (controlled == 0) ellipseACenter = GetMousePosition();
        else ellipseBCenter = GetMousePosition();

        bool ellipsesCollide = CheckCollisionEllipses(
            ellipseACenter, ellipseARx, ellipseARy,
            ellipseBCenter, ellipseBRx, ellipseBRy
        );

        bool mouseInA = CheckCollisionPointEllipse(GetMousePosition(), ellipseACenter, ellipseARx, ellipseARy);
        bool mouseInB = CheckCollisionPointEllipse(GetMousePosition(), ellipseBCenter, ellipseBRx, ellipseBRy);
        //----------------------------------------------------------------------------------

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

            ClearBackground(RAYWHITE);

            DrawEllipse((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, ellipsesCollide ? RED : BLUE);

            DrawEllipse((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, ellipsesCollide ? RED : GREEN);

            DrawEllipseLines((int)ellipseACenter.x, (int)ellipseACenter.y, ellipseARx, ellipseARy, WHITE);

            DrawEllipseLines((int)ellipseBCenter.x, (int)ellipseBCenter.y, ellipseBRx, ellipseBRy, WHITE);

            DrawCircleV(ellipseACenter, 4, WHITE);
            DrawCircleV(ellipseBCenter, 4, WHITE);

            if (ellipsesCollide) DrawText("ELLIPSES COLLIDE", screenWidth/2 - 120, 40, 28, RED);
            else DrawText("NO COLLISION", screenWidth/2 - 80, 40, 28, DARKGRAY);

            DrawText(controlled == 0 ? "Controlling: A" : "Controlling: B", 20, screenHeight - 40, 20, YELLOW);

            if (mouseInA && controlled != 0) DrawText("Mouse inside ellipse A", 20, screenHeight - 70, 20, BLUE);
            if (mouseInB && controlled != 1) DrawText("Mouse inside ellipse B", 20, screenHeight - 70, 20, GREEN);

            DrawText("Press [A] or [B] to switch control", 20, 20, 20, GRAY);

        EndDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    CloseWindow();

    return 0;
}

From raylib 6.2. The original on GitHub.