Exray - Raylib NIFs for Elixir

Exray is a library which leverages Unifex and Bundlex to create NIFs for Raylib’s various modules. Currently, it’s in a functional enough state that I’m confident enough to remove “don’t use this - wip build” from the Hex package description.

Broad strokes, Exray is intended to be a tool for game developers to leverage the BEAM to create games and native desktop apps with a clean syntax using liberal use of defdelegate. Once it’s at the point it has almost 1:1 parity, I hope to have it added to the list of Raylib’s confirmed bindings and then create a game. Or a game engine. Or both.

Parity as of 0.6.0 is pretty decent, with my initial focus being on the Core module, Text, Drawing, Textures and Math. Math, however, is being translated directly to Elixir per-struct so we can do cool things like…

alias Exray.Structs.Vector2

vec1 = Vector2.new(50, 50) 
#= %Exray.Structs.Vector2{x: 50.0, y: 50.0}

vec2 = Vector2.add(vec1, 5)
#= %Exray.Structs.Vector2{x: 55.0, y: 55.0}

The less developers directly write to the Exray structs directly, the less chance for C receiving something it doesn’t expect and triggering a segfault. Have a squizz through the source, or this out-of-date example from 0.3(?).0 which shows the completed rough flow of the step-by-step from the Hexdocs.

Hope to have a chat about cool things you make either in response to this post or a post using the new exray tag!

8 Likes

I see you’ve got commits in Rayex, just curious why a new library?

1 Like

That’s a fantastic question and one I was expecting, actually. While I initially began working in Rayex, I was concerned that if I were to make too many wild foundational changes to the project I’d be met with some push-back or even have my flow halted. The maintainer picked it back up a while ago, asked me if they could merge changes into base from my fork (yes, of course!) but the main structure of the project (and my fork) were an issue.

You only have to look within c_src/ to see what I mean; the code had become unmaintainable very quickly, so I chose to spend time on my own solution to the one-specfile problem. It’s not a rip on Rayex by any means, it’s probably what I would’ve done given the knowledge and tools we had at the time. But Unifex had fixed issues with nested structs by the time I began picking it back up and tinkering, so I could try more esoteric things like loading spec types into Unifex’s sandboxed environment during compile time, letting me copy paste code more effectively and segmenting it down into maintainable chunks.

Raylib 5.5.0 (thanks @harrisi) came out yesterday which is hilarious timing, but I’ve already upgraded to 5.5.0 on a testing branch which isn’t yet committed. The good thing about segmenting the code down this much into per-module specs is that when your compiler fails, you don’t just get “You failed to compile this one file”, you get “You failed to compile this one file, except we know which module and function is broken and can likely guess why”.

I’m pretty active at working on it and I’ve gotten quite adept at understanding the Unifex preprocessor, so instead of having dread I’ll make changes that I have to wait for, or get denied, I can just have more control over the project.

Also, leveraging Bundlex’s precompiled blob configuration it lets developers just get precompiled .so files to bake into the project so you don’t have to compile from source. I’m working on a custom pre-precompiler that spits releases we can use in Exray from a forked ‘Elixir friendly’ edit of Raylib which will contain code from the multi-window-experimental code. It should let us have image loaders, draw calls and all of that on separate GenServers which can be called from a main loop to quell segfaults. But yeah, these changes are bordering on using Raylib to create my own game library.

tl;dr- I like my stuff done quick, maintainable and experimental so I’m rolling my own.

2 Likes

I think you mean raylib 5.5 :slight_smile:

1 Like