Skip to content

Instantly share code, notes, and snippets.

@ertugrulcetin
Created February 16, 2026 13:04
Show Gist options
  • Select an option

  • Save ertugrulcetin/33a45bffad25f3757e06deb7e1586be4 to your computer and use it in GitHub Desktop.

Select an option

Save ertugrulcetin/33a45bffad25f3757e06deb7e1586be4 to your computer and use it in GitHub Desktop.
raylib [textures] example in Clojure - bunnymark
(ns examples.bunnymark
(:require
[raylib.core :as r]
[coffi.ffi :as ffi]
[coffi.mem :as mem])
(:import
(java.lang.foreign Arena MemorySegment))
(:gen-class))
(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)
(def ^:const MAX_BUNNIES 90500)
(def ^:const MAX_BATCH_ELEMENTS (int 8192))
(def ^:const SCREEN_WIDTH (int 800))
(def ^:const SCREEN_HEIGHT (int 450))
(def ^:const MOUSE_BUTTON_LEFT (int 0))
(defn -main [& _]
(r/set-config-flags :flag/window-highdpi :flag/window-transparent)
(r/init-window SCREEN_WIDTH SCREEN_HEIGHT "raylib [textures] example in Clojure - bunnymark")
(r/set-target-fps 60)
(let [draw-tex! (ffi/make-downcall (ffi/find-symbol "DrawTexture") [:rl/Texture2D ::mem/int ::mem/int :rl/Color] ::mem/void)
tex-bunny (r/load-texture "resources/img/wabbit_alpha.png")
half-w (int (quot (:width tex-bunny) 2))
half-h (int (quot (:height tex-bunny) 2))
^Arena arena (Arena/ofAuto)
^MemorySegment tex-seg (let [seg (.allocate arena (long 20) (long 4))]
(mem/write-int seg (long 0) (int (:id tex-bunny)))
(mem/write-int seg (long 4) (int (:width tex-bunny)))
(mem/write-int seg (long 8) (int (:height tex-bunny)))
(mem/write-int seg (long 12) (int (:mipmaps tex-bunny)))
(mem/write-int seg (long 16) (int (:format tex-bunny)))
seg)
^MemorySegment color-seg (.allocate arena (long 4) (long 4))
^floats pos-x (float-array MAX_BUNNIES)
^floats pos-y (float-array MAX_BUNNIES)
^floats speed-x (float-array MAX_BUNNIES)
^floats speed-y (float-array MAX_BUNNIES)
^ints colors (int-array MAX_BUNNIES)
^ints cnt (int-array 1)]
(loop []
(when-not (r/window-should-close?)
(let [n (int (aget cnt (int 0)))]
(when (r/is-mouse-button-down? MOUSE_BUTTON_LEFT)
(let [mp (r/get-mouse-position)
mx (float (:x mp))
my (float (:y mp))]
(loop [i 0
c n]
(when (and (< i 100) (< c MAX_BUNNIES))
(aset pos-x c mx)
(aset pos-y c my)
(aset speed-x c (/ (r/get-random-value -250 250) 60.0))
(aset speed-y c (/ (r/get-random-value -250 250) 60.0))
(let [rv (r/get-random-value 50 240)
gv (r/get-random-value 80 240)
bv (r/get-random-value 100 240)]
(aset colors c
(unchecked-int
(bit-or rv
(bit-shift-left gv 8)
(bit-shift-left bv 16)
(bit-shift-left 255 24)))))
(recur (unchecked-inc-int i) (unchecked-inc-int c))))
(aset cnt 0 (min MAX_BUNNIES (+ n 100)))))
(let [n (aget cnt 0)
sw (r/get-screen-width)
sh (r/get-screen-height)
hw half-w
hh half-h]
(loop [i 0]
(when (< i n)
(let [px (+ (aget pos-x i) (aget speed-x i))
py (+ (aget pos-y i) (aget speed-y i))]
(aset pos-x i px)
(aset pos-y i py)
(when (or (> (+ px hw) sw) (< (+ px hw) 0.0))
(aset speed-x i (- (aget speed-x i))))
(when (or (> (+ py hh) sh) (< (+ py (- hh 40.0)) 0.0))
(aset speed-y i (- (aget speed-y i)))))
(recur (unchecked-inc-int i))))
(r/begin-drawing)
(r/clear-background r/color-raywhite)
(loop [i (int 0)]
(when (< i n)
(mem/write-int color-seg (aget colors i))
(draw-tex! tex-seg
(int (aget pos-x i))
(int (aget pos-y i))
color-seg)
(recur (unchecked-inc-int i))))
(r/draw-rectangle 0 0 SCREEN_WIDTH 40 r/color-black)
(r/draw-text (str "bunnies: " n) 120 10 20 r/color-green)
(r/draw-text (str "batched draw calls: " (unchecked-inc (quot n MAX_BATCH_ELEMENTS))) 320 10 20 r/color-maroon)
(r/draw-fps 10 10)
(r/draw-rectangle 0 0 SCREEN_WIDTH 40 r/color-black)
(r/draw-text (str "bunnies: " n) 120 10 20 r/color-green)
(r/draw-text (str "batched draw calls: "
(unchecked-inc (quot (int n) (int MAX_BATCH_ELEMENTS))))
320 10 20 r/color-maroon)
(r/draw-fps 10 10)
(r/end-drawing)))
(recur)))
(r/unload-texture tex-bunny)
(r/close-window)))
@bennyandresen
Copy link

Thanks a lot for sharing!

For others that may be interested about raylib.core, it's presumably from https://github.com/ertugrulcetin/raylib-clojure-playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment