bunnymark
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:not checked yet The browser comparison does not cover this example yet.
//! raylib [textures] example - bunnymark
//!
//! Zig-API translation of examples/textures/textures_bunnymark.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
const std = @import("std");
const rl = @import("raylib");
const max_bunnies = 80000; // 80K bunnies limit
// This is the maximum amount of elements (quads) per batch
// NOTE: This value is defined in [rlgl] module and can be changed there
const max_batch_elements = 8192;
const Bunny = struct {
position: rl.Vector2,
speed: rl.Vector2,
color: rl.Color,
};
pub fn main() !void {
// Initialization
const screen_width = 800;
const screen_height = 450;
rl.initWindow(screen_width, screen_height, "raylib [textures] example - bunnymark");
defer rl.closeWindow(); // Close window and OpenGL context
// Load bunny texture
const tex_bunny = try rl.loadTexture("resources/raybunny.png");
defer rl.unloadTexture(tex_bunny);
// Bunnies storage, filled up to `bunnies_count`
const bunnies = try std.heap.page_allocator.alloc(Bunny, max_bunnies);
defer std.heap.page_allocator.free(bunnies);
var bunnies_count: usize = 0;
var paused = false;
const half_width = @as(f32, @floatFromInt(tex_bunny.width)) / 2;
const half_height = @as(f32, @floatFromInt(tex_bunny.height)) / 2;
rl.setTargetFPS(0); // Set our game to run with an uncapped framerate
// Main game loop
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
// Update
if (rl.isMouseButtonDown(.left)) {
// Create more bunnies
for (0..100) |_| {
if (bunnies_count < max_bunnies) {
const position = rl.getMousePosition();
const speed_x: f32 = @floatFromInt(rl.getRandomValue(-250, 250));
const speed_y: f32 = @floatFromInt(rl.getRandomValue(-250, 250));
const r: u8 = @intCast(rl.getRandomValue(50, 240));
const g: u8 = @intCast(rl.getRandomValue(80, 240));
const b: u8 = @intCast(rl.getRandomValue(100, 240));
bunnies[bunnies_count] = .{
.position = position,
.speed = .{ .x = speed_x, .y = speed_y },
.color = .{ .r = r, .g = g, .b = b, .a = 255 },
};
bunnies_count += 1;
}
}
}
if (rl.isKeyPressed(.p)) paused = !paused;
if (!paused) {
// Update bunnies
const screen_w: f32 = @floatFromInt(rl.getScreenWidth());
const screen_h: f32 = @floatFromInt(rl.getScreenHeight());
for (bunnies[0..bunnies_count]) |*bunny| {
bunny.position.x += bunny.speed.x * rl.getFrameTime();
bunny.position.y += bunny.speed.y * rl.getFrameTime();
if (((bunny.position.x + half_width) > screen_w) or
((bunny.position.x + half_width) < 0)) bunny.speed.x *= -1;
if (((bunny.position.y + half_height) > screen_h) or
((bunny.position.y + half_height - 40) < 0)) bunny.speed.y *= -1;
}
}
// Draw
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(.ray_white);
for (bunnies[0..bunnies_count]) |bunny| {
// NOTE: When internal batch buffer limit is reached (MAX_BATCH_ELEMENTS),
// a draw call is launched and buffer starts being filled again;
// before issuing a draw call, updated vertex data from internal CPU buffer is send to GPU...
// Process of sending data is costly and it could happen that GPU data has not been completely
// processed for drawing while new data is tried to be sent (updating current in-use buffers)
// it could generates a stall and consequently a frame drop, limiting the number of drawn bunnies
rl.drawTexture(tex_bunny, @intFromFloat(bunny.position.x), @intFromFloat(bunny.position.y), bunny.color);
}
rl.drawRectangle(0, 0, screen_width, 40, .black);
rl.drawText(rl.textFormat("bunnies: {d}", .{bunnies_count}), 120, 10, 20, .green);
rl.drawText(rl.textFormat("batched draw calls: {d}", .{1 + bunnies_count / max_batch_elements}), 320, 10, 20, .maroon);
rl.drawFPS(10, 10);
}
}/*******************************************************************************************
*
* raylib [textures] example - bunnymark
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 1.6, last time updated with raylib 2.5
*
* 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) 2014-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: malloc(), free()
#define MAX_BUNNIES 80000 // 80K bunnies limit
// This is the maximum amount of elements (quads) per batch
// NOTE: This value is defined in [rlgl] module and can be changed there
#define MAX_BATCH_ELEMENTS 8192
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct Bunny {
Vector2 position;
Vector2 speed;
Color color;
} Bunny;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - bunnymark");
// Load bunny texture
Texture2D texBunny = LoadTexture("resources/raybunny.png");
Bunny *bunnies = (Bunny *)RL_MALLOC(MAX_BUNNIES*sizeof(Bunny)); // Bunnies array
int bunniesCount = 0; // Bunnies counter
bool paused = false;
SetTargetFPS(0); // Set our game to run with an uncapped framerate
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
// Create more bunnies
for (int i = 0; i < 100; i++)
{
if (bunniesCount < MAX_BUNNIES)
{
bunnies[bunniesCount].position = GetMousePosition();
bunnies[bunniesCount].speed.x = (float)GetRandomValue(-250, 250);
bunnies[bunniesCount].speed.y = (float)GetRandomValue(-250, 250);
bunnies[bunniesCount].color = (Color){ GetRandomValue(50, 240),
GetRandomValue(80, 240),
GetRandomValue(100, 240), 255 };
bunniesCount++;
}
}
}
if (IsKeyPressed(KEY_P)) paused = !paused;
if (!paused)
{
// Update bunnies
for (int i = 0; i < bunniesCount; i++)
{
bunnies[i].position.x += bunnies[i].speed.x*GetFrameTime();
bunnies[i].position.y += bunnies[i].speed.y*GetFrameTime();
if (((bunnies[i].position.x + (float)texBunny.width/2) > GetScreenWidth()) ||
((bunnies[i].position.x + (float)texBunny.width/2) < 0)) bunnies[i].speed.x *= -1;
if (((bunnies[i].position.y + (float)texBunny.height/2) > GetScreenHeight()) ||
((bunnies[i].position.y + (float)texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < bunniesCount; i++)
{
// NOTE: When internal batch buffer limit is reached (MAX_BATCH_ELEMENTS),
// a draw call is launched and buffer starts being filled again;
// before issuing a draw call, updated vertex data from internal CPU buffer is send to GPU...
// Process of sending data is costly and it could happen that GPU data has not been completely
// processed for drawing while new data is tried to be sent (updating current in-use buffers)
// it could generates a stall and consequently a frame drop, limiting the number of drawn bunnies
DrawTexture(texBunny, (int)bunnies[i].position.x, (int)bunnies[i].position.y, bunnies[i].color);
}
DrawRectangle(0, 0, screenWidth, 40, BLACK);
DrawText(TextFormat("bunnies: %i", bunniesCount), 120, 10, 20, GREEN);
DrawText(TextFormat("batched draw calls: %i", 1 + bunniesCount/MAX_BATCH_ELEMENTS), 320, 10, 20, MAROON);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(bunnies); // Unload bunnies data array
UnloadTexture(texBunny); // Unload bunny texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}From raylib 6.2. The original on GitHub.