ellipse collision
There is no browser build of this example yet.
Is it the same as C?
- Desktop:verified The Zig version renders a final frame that is byte-identical to the C example.
- Browser:verified In headless Chrome, the Zig version gives a final frame byte-identical to the C example built for the web.
//! 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.