raylibAPL is a library made to write cross-platform graphical applications using the Dyalog APL programming language.

- Supports platforms Windows, Linux, and MacOS.
- Input-methods: Keyboard, Mouse,
Controler, andTouchscreen. - Graphics: 2D, 3D,
Sound, Text, Vector graphics, Images/Textures, and shaders. - Multiple Fonts formats supported (TTF,
OTF,Image fonts,AngelCode fonts). - Multiple texture formats supported,
including compressed formats (DXT, ETC, ASTC). - Full 3D support, including
3D Shapes, Models,Billboards,Heightmaps, and more! - Flexible Materials system, supporting classic maps and
PBR maps. Animated 3D models supported (skeletal bones animation) (IQM, M3D, glTF).- Shaders support,
including model shaders and postprocessing shaders. Powerful math module for Vector, Matrix, and Quaternion operations: raymath.- Audio loading and playing with streaming support (
WAV,QOA,OGG, MP3,FLAC,XM,MOD). VR stereo rendering support with configurable HMD device parameters.
This library interfaces with C code that is prone to crashing Dyalog. If you experience code 999, there was likely a "segfault"/error in raylibAPL or raylib, and so a bug report would be appreciated.
There are two ways to get started, with Tatin and without. Easiest is using Tatin, though it's not consistent in Dyalog v19.
Run the following to install temp-c-raylib into the raylibAPL/lib/
folder.
dyalogscript install-raylib.apls
Instead of running the above, you can manually download temp-c-raylib from it's releases page and move the binary into raylibAPL/lib/
.
If you're familiar with Nix, you can instead use temp-c-raylib's default.nix
and flake.nix
.
Tatin is a package manager for Dyalog APL.
Install Tatin via ]Activate tatin
if not already installed, then install raylibAPL:
]Tatin.InstallPackages raylibAPL
If you experience the error Invalid user command;
, please install without Tatin.
Importing with Tatin assumes you have installed raylibAPL with Tatin. Both of the other methods work with and without Tatin.
To import raylibAPL via ⎕Fix, take the code below and replace ../
with the path to the folder/directory containing raylibAPL:
rlDir ← '../raylibAPL/link/',⍨⊃1⎕NPARTS''
rl ← 0⎕Fix rlDir,'raylib.apln'
rl.Init rlDir
When making a script file like the raylibAPL's examples, I would recommend the .apls
file extension and adding this line at the top of the script #!/usr/bin/dyalogscript
. Remember to run .apls
files from the containing folder/directory.
⍝ Load the package
⎕SE.Tatin.LoadDependencies ('packages' '#')
rl ← raylibAPL.raylib
⍝ Initialize (Tatin handles the path automatically)
rl.Init raylibAPL.TatinVars.HOME,'/link'
You may ]Link to the raylibAPL/link
folder, which imports raylib.apln
, rlgl.apln
, raymath.apln
, physac.apln
, and raygui.apln
:
]cd /home/brian/raylibAPL/link
]link.create # .
rl ← raylib
rl.Init ''
⚠️ macOS Users: Start Dyalog with theENABLE_CEF=0
environment variable set to avoid HtmlRenderer conflicts. This can be done in the command line, or if you're using RIDE, in the environment variables textbox on startup.ENABLE_CEF=0 dyalog
Try running the following after importing raylib as rl:
rl.InitWindow 800 800 'Hello World!'
:While ~rl.WindowShouldClose⍬
rl.BeginDrawing⍬
rl.ClearBackground rl.color.gray
rl.EndDrawing⍬
:EndWhile
rl.CloseWindow⍬
raylibAPL is a direct, low-level interface to the raylib C library, providing approximately 200 functions that either return values or modify the application state.
Some raylib functions start and end scopes, like rl.InitWindow
rl.CloseWindow
.
During different scopes, different functions can run. For example, rl.GetWindowPosition⍬
can only be run after a window scope. There are many different scopes, InitWindow
→CloseWindow
, BeginDrawing
→EndDrawing
, BeginMode3D
→EndMode3D
, and so on. The naming convention for scopes is that they are either Begin...
→End...
, or Init...
→Close...
. I refer to the ...
part when speaking of a scope. All scope information can be found in this JSON file, which is used to generate replicas of raylib functions that error instead of crashing.
Here is a raylibAPL application, that creates a window and gets window position:
rl.InitWindow 800 600 'My Application'
⍝ Window scope is now active
⍝ Many raylib functions are now available, like:
WinPos ← rl.GetWindowPosition⍬
rl.CloseWindow⍬
⍝ Window scope is now closed
Most rendering must occur within a drawing scope, which is nested inside the window scope:
rl.InitWindow 800 600 'My Application'
rl.BeginDrawing⍬
⍝ Drawing scope is active
⍝ Can now use drawing functions
rl.ClearBackground rl.color.black
rl.DrawText 'Hello, World!' 10 10 20 rl.color.white
rl.EndDrawing⍬ ⍝ Throttles to make FPS be the monitor refresh rate
⍝ Drawing scope is closed and frame is presented
rl.CloseWindow⍬
EndDrawing
automatically handles frame timing, limiting your application to the monitor's refresh rate (typically 60 FPS). If your frame logic takes longer than 1/60th of a second, EndDrawing
won't add additional delay. This delay can be set via SetTargetFPS
.
Here's a minimal raylibAPL example, saying "hello world" on a gray background:
rl.InitWindow 800 800 'abc' ⍝ Begin window scope
:While ~rl.WindowShouldClose⍬ ⍝ Run this loop per frame
rl.BeginDrawing⍬ ⍝ Start drawing scope
rl.ClearBackground⍬ rl.color.gray ⍝ Set background to gray
rl.DrawText 'hello world' 10 10 20 rl.color.white
rl.EndDrawing⍬ ⍝ End scope
:EndWhile
rl.CloseWindow⍬
It is recommended that raylibAPL applications follow this pattern:
- Initialize the library
- Create a window
- Load resources (textures, sounds, etc.)
- Enter the main loop (details):
- Process input
- Update game state
- Draw the frame
- Clean up resources
- Close the window
- Examples: Check out the examples directory for practical demonstrations. They can be run via dyalogscript, for example run
duck3D.apls
viadyalogscript raylibAPL/examples/duck3D.apls
. - API Reference: Examine the raylib.apln file for available functions and constants. Please ignore the
RAYLIB
suffix on the functions, since you should call the error-checking wrapped versions. - Scope information: See this json file for all information on scopes. It is used to generate replicas of raylib functions that error instead of crashing.
- raylib Documentation: Sometimes, raylib's documentation applies to raylibAPL aswell.
The bindings are automatically generated. If you need to regenerate them:
- Install CBQN
- Run:
bqn raylibAPL/parse-raylibAPL/parseAll.bqn
This parsing system converts the raylib C headers into APL functions that interface with the compiled binary generated by temp-c-raylib.
raylibAPL has been financially supported by Dyalog Limited. Brian was hired as an intern by Dyalog Limited at about 7th of July 2024 to develop raylibAPL, alongside Asher. Brian has continued being funded for the development. The Dyalog team have helped a lot with the development of this library.
raylibAPL relies on the raylib C library. Lots of thanks to raysan5 and the raylib community for this great library.
The current version of raylibAPL has parsing that relies on json.bqn made by Marshall Lochbaum. Also the BQN programming language in general!