raylib-apl is a library made to write cross-platform graphical applications using the Dyalog APL programming language.
- Input-methods: Keyboard, Mouse, Controler and Touchscreen.
- 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
Breaking changes to any feature in raylib-apl should be expected for now, as this library is very young and experimental. You will crash Dyalog a lot. If you experience code 999, there was likely a "segfault"/error in raylib. These are usually due to using functions in the wrong contexts, like drawing a box before rl.BeginDrawing
, or loading an image before opening the window.
raylib-apl currently only supports Linux. This is due to a bug in ⎕NA
that makes functions taking structs as arguments error.
Feel free to watch How to install raylib-apl on Linux on youtube.
raylib-apl requires a libtemp-c-raylib.so
file, downloadable here.
The examples expect the file to be located at the raylib-apl/
directory.
To import raylib-apl as a namespace, run the following:
#!cd $dir && /usr/bin/dyalogscript $fileName
dir ← ⊃1⎕NPARTS''
rl ← 0⎕Fix dir,'../link/raylib.apln'
rl.Init (dir,'../link/')⍬
You can give rl.Init
a path as second argument that points to libraylib.so
.
Use ⍬
to use the default path raylib-apl/libraylib.so
.
You may ]Link to the raylib-apl/link
folder.
This imports raylib.apln
, rlgl.apln
, and raymath.apln
, each of which are from raylib. A 2d physics library called physac is also included as physac.apln
, and a GUI library called raygui as raygui.apln
.
Example using raylib with ]link
is shown below:
]cd /home/brian/Persinal/Scripts/APL/raylib-apl/link
]link.create # .
raylib.Init '' ⍬
⍝ Your raylib code starts here
_←raylib.InitWindow 800 800 'Hello!!!'
:While ~raylib.WindowShouldClose
_←raylib.BeginDrawing
_←raylib.ClearBackground ,⊂8↑raylib.color.gray
_←raylib.EndDrawing
:EndWhile
_←raylib.CloseWindow
Developing an application with raylib-apl is very low level. The entirety of raylib-apl is about 200 functions that take in a list of inputs and returns some outputs, and/or change the state of the application. An example of changing the state of the application is the following:
raylib.InitWindow 400 400 'Title'
This function opens a new window, with width=400, height=400, and window title being "Title". This changes the state of the computer screen of course, but it also changes something very important, it creates a kind of scope.
# Begin scope where window is open
raylib.InitWindow 400 400 'Title'
# Inside this scope, I am allowed to use a lot more functions.
# End scope where window is open, meaning closing window
raylib.CloseWindow
Inside this scope, you are allowed a lot more. You can use functions like SetWindowIcon
, GetScreenWidth
, GetMonitorCount
, LoadShader
, GetMouseRay
, and many more.
In the current version of raylib-apl, running a function that requires a scope outside that scope can crashe the Dyalog interpreter, or lead to unintended output. Not closing a scope after starting it may also crash or give unintended output.
There are other functions that start and end scopes, like StartDrawing
and EndDrawing
. StartDrawing
and EndDrawing
require the InitWindow
scope. Inside the StartDrawing
scope you can use functions like ClearBackground
, which sets the background of the window to a given color. An important note about EndDrawing
is that it automatically delays to whatever frame-rate you choose, which by default is your monitor refresh rate. As an example, if your monitor has a refresh rate of 60 frames per second, EndDrawing
will delay a maximum of ÷60
. I say "maximum", because EndDrawing
delays just enough to keep your :while
loop running 60 times a second, so if your loop takes ÷60
seconds to run, EndDrawing
wouldn't delay.
Applications made with raylib-apl have a common structure and style. As you can see by the below example, there's a :while
loop used that draws the frame using BeginDrawing
, where the frame being drawn is gray because of ClearBackground
. This example is intentionally very simple, simply drawing a window with a black background.
rl.InitWindow 800 800 'abc' # Begin InitWindow scope
:While ~rl.WindowShouldClose # Run this loop per frame
rl.BeginDrawing # Begin a drawing scope to draw the current frame
rl.ClearBackground ⊂ 8↑ rl.color.gray # Set backrgound to gray
rl.EndDrawing # End the Drawing scope
:EndWhile
rl.CloseWindow # End InitWindow scope
There are two exceptional things to notice in this example, soon to be changed in a future raylib-apl release, the line ClearBackground ⊂ 8↑ rl.color.gray
. The two things to notice are the 8↑
and ⊂
.
Because of a low-level bug with the current version of raylib-apl, colors and some other structures given as arguments to functions must be padded by enough 0s. Colors require only 4 numbers to represent it, RGBA values, but the bug causes them to require 8 numbers. The low-level reason for this is that ⎕NA
, which raylib-apl relies upon, doesn't automatically pad the underlying representations of the structures automatically to make them align with C. This bug will hopefully be fixed soon, either by raylib-apl or by Dyalog.
If a raylib-apl function takes 1 or more arguments, they're expected to be a rank 1 or rank 0 array of arguments. This is why rl.color.gray
is enclosed before given to ClearBackground
, since it takes one argument that's a color, not 8 number arguments. This quirk is planned to be replaced, such that a function that takes 1 argument doesn't require the enclosed argument.
To get a good start into raylib, mess around with the examples and see what you can make!
All raylib-apl examples support using dyalogscript, by having the following on the top of every example:
#!cd $dir && /usr/bin/dyalogscript $fileName
⎕NA
can't return F4
, it formats them incorrectly on Linux. Instead, give a struct in a pointer that C modifies.
argument of type >U8
is ignored, but you still need to give ⎕NA the input type.
Use :require ../parse-raylib-apl/setup.apln
syntax for doing proper imports relative to the file rather than current directory.
Auto pad stuff on APL side.
Sound visualization example. Game of life. Visualize 3d arrays.
The auto-parsing isn't needed since the parser output is premade, though if you still need to parse, install CBQN to run it.
raylib-apl has been financially supported by Dyalog Limited. Brian was hired as an intern by Dyalog Limited at about 7th of July 2024 to develop raylib-apl, alongside Asher. The Dyalog team have helped a lot with the development of this library.
raylib-APL relies on the raylib C library. Lots of thanks to raysan5 and the raylib community for this great library.
The current version of raylib-apl relies on json.bqn made by Marshall Lochbaum, more specifically json.bqn.