Raylib is a simple, open-source C game library. Chasm ships with a complete Raylib binding, compile with --engine raylib and the full Raylib API is available in your script.
Setup
1
Install Raylib
On macOS:
brew install raylib
On Linux:
sudo apt install libraylib-dev
2
Run with the Raylib engine
chasm run --engine raylib game.chasm
The CLI compiles your script and links it against Raylib automatically.
3
Watch mode (hot reload)
chasm watch --engine raylib game.chasm
Save the file → the engine reloads your script instantly without restarting.
Script Structure
A Raylib Chasm script uses on_init, on_tick, and on_draw:
@player_x :: script = 400.0
@player_y :: script = 300.0
@speed :: script = 200.0
def on_init() do
# Called once at startup
end
def on_tick(dt :: float) do
if key_down(:right) do @player_x = @player_x + @speed * dt end
if key_down(:left) do @player_x = @player_x - @speed * dt end
if key_down(:down) do @player_y = @player_y + @speed * dt end
if key_down(:up) do @player_y = @player_y - @speed * dt end
end
def on_draw() do
clear_background(0x181820ff)
draw_rectangle(@player_x - 16.0, @player_y - 16.0, 32.0, 32.0, 0x4488ffff)
draw_text("Move with arrow keys", 10, 10, 20, 0xffffffff)
endDrawing
| Function | Description |
|---|---|
clear_background(color) | Fill the screen with a solid color |
draw_rectangle(x, y, w, h, color) | Filled rectangle |
draw_rectangle_lines(x, y, w, h, color) | Outlined rectangle |
draw_circle(cx, cy, r, color) | Filled circle |
draw_circle_lines(cx, cy, r, color) | Circle outline |
draw_line(x1, y1, x2, y2, color) | Line segment |
draw_text(text, x, y, size, color) | Text with built-in font |
Colors are 0xRRGGBBAA packed integers. Common values:
white = 0xffffffff
black = 0x000000ff
red = 0xff0000ff
transparent_white = 0xffffff80 # 50% alphaInput
Keyboard
| Function | Returns | Description |
|---|---|---|
key_down(key) | bool | True every frame the key is held |
key_pressed(key) | bool | True only on the first frame the key is pressed |
key_released(key) | bool | True only on the frame the key is released |
Key names are atoms. Common keys: :right, :left, :up, :down, :space, :enter, :escape, :a–:z, :f1–:f12.
# Move while held
if key_down(:right) do @x = @x + @speed * dt end
# Fire once per press
if key_pressed(:space) do fire_bullet() endMouse
| Function | Returns | Description |
|---|---|---|
mouse_x() | float | Current mouse X position |
mouse_y() | float | Current mouse Y position |
mouse_down(button) | bool | True while button is held (:left, :right, :middle) |
mouse_pressed(button) | bool | True on the first frame button is pressed |
Screen
| Function | Returns | Description |
|---|---|---|
screen_width() | float | Current window width in pixels |
screen_height() | float | Current window height in pixels |
get_fps() | int | Current frames per second |
get_time() | float | Seconds elapsed since startup |
Textures and Fonts
@player_tex :: persistent = 0
@font :: persistent = 0
def on_init() do
@player_tex = load_texture("assets/player.png")
@font = load_font("assets/mono.ttf")
end
def on_draw() do
draw_texture(@player_tex, @player_x, @player_y, 32.0, 32.0, 0xffffffff)
draw_text_ex(@font, "Score: #{@score}", 10, 10, 24, 1.0, 0xffffffff)
endLoad textures and fonts in on_init into persistent attrs so they survive hot-reload.
Audio
@shoot_sfx :: persistent = 0
def on_init() do
@shoot_sfx = load_sound("assets/shoot.wav")
end
def on_tick(dt :: float) do
if key_pressed(:space) do
play_sound(@shoot_sfx)
end
end