OpenGL-rendered Breakout clone in Elixir

I made a breakout clone in Elixir with no dependencies. It’s mostly terrible, but I’ve tested it on macOS, Windows, and Ubuntu. Find it here: GitHub - harrisi/elixir_breakout: learn opengl breakout port in elixir. You can clone the repo and run the game with iex -S mix or mix run --no-halt. A/D, H/L, or left/right arrows to move left/right, space to launch the ball, N to switch levels, and P to profile for ten seconds (if you’re interested).

The code is quite bad. It’s a mostly straightforward port of the breakout implementation on https://learnopengl.com. My intention is to now make it more “BEAM-y”, but I think it’s an interesting project already.

Let me know if you have any problems running it or playing it. My machines are reasonably powerful, so I’m not sure how it runs in general.

EDIT: I posted in the blog post thread, but if anyone’s interested in random thoughts about this, Breakout Musings.

14 Likes

I honestly had no idea that OTP had an OpenGL library in it. Thanks for sharing. Ran fine on my Macbook Air.

1 Like

It’s via wxWidgets, which is what observer uses for its GUI.

The best example of its use is https://wings3d.com, which is a 3D modeling software written in Erlang (primarily by two Erlang maintainers). I use it to export 3D models that I render in Elixir in another project, actually.

EDIT: Thanks for testing it!

This is extremely cool and inspiring!

Don’t be so hard on yourself, plenty of production code around the world is “bad” and nobody will ever notice. Focus on what you did right, which is make a working game with Elixir! Very few people have done that.

4 Likes

Thanks for the kind words!

I’m not too worried about the code quality. I’m not new to programming, but I’ve only recently started working with Elixir, OpenGL, or any sort of game development, so I don’t expect much.

This is really the continuation of an exploration into what the BEAM can do in a game development situation. It started with a triangle, went to a (bad) ray tracer, the start of some 3d physics simulations, 3d modeling, and now a 2d game. Slightly going backwards, but it’s good progress I think.

I pushed an update with some text rendering. It’s basically a copy of the OpenGL text rendering in the :wx demo. There’s also a menu for selecting levels, and some more bugs! :slight_smile:

Text rendering is the last main thing I can do without bringing in some dependencies. I think it’s worth mentioning all the things Elixir can do by itself:

  • OpenGL Core Profile rendering with shaders
  • Windowing
  • Input handling
  • Text rendering
  • All the other normal things Elixir is good at

Really the only thing missing is audio playback. I’ve already tested Membrane, which seems to be the best (only?) option. I really wish there was a way to do audio playback without any dependencies. Oh well.

I’ll be adding audio playback soon, which will, I think, put this over the line into the lonely category of “finished games written in Elixir”.

3 Likes

I added Membrane, with looped background audio and a few sound effects. I haven’t tested it on anything other than my M2 MacBook Air, but I think it should work elsewhere.

It’s not the ideal way to do it, but I’m not sure yet what is. There’s a PR just adding the audio code, if anyone is familiar with Membrane and has suggestions (I asked in the Membrane Discord as well).

This is also the first use of the supervision tree, although it’s not really necessary.

There is still no win condition. Call it “art”. :slight_smile:

1 Like

If anyone can’t be bothered with building the project after adding some dependencies (this is not a dig at Membrane - it’s fantastic), I made standalone executables for Windows, macOS, and Linux with the help of burrito.

I haven’t tested the Windows, Linux, or non-arm macOS builds, but I’m hopeful that things just work. As long as those work, this project actually seems much closer to being a game written in Elixir distributed on Steam, Gog, itch.io, etc., which is pretty exciting. If I get to that point, it would be a different game, but probably something reasonably simple (maybe 3D though).

There’s still a lot to prove, but it’s still coming along nicely, I think. Any suggestions on what to do next would be great. What would help convince you to work on a game in Elixir?

1 Like

I have such dreams of writing a game in Elixir, and you’ve basically followed the exact path I’ve envisioned (compiling for each platform with Burrito)

I’d thought it would be more straightforward to wrap something like Raylib, but mostly because I didn’t know about using OpenGL directly.

What’s keeping me from making a game? A full time job and a baby :sweat_smile:

4 Likes

FWIW I’ve tried this on Windows and the application crashes complaining about missing .mp3 files

1 Like

It probably is easier to do something like what Rayex is doing, but the main reason I’ve not spent effort improving that instead is that I think shoehorning a C-based state machine-like API into Elixir isn’t what will make a great tool for making a game in Elixir. Of course, you can abstract a more idiomatic layer in Elixir on top of Raylib, but I think it would end up being confusing to reason about. Needing to understand Elixir, the abstraction layer, Raylib, and how the abstraction layer communicates to Raylib, just seems like too much. That doesn’t even get into the complexities of actual game development. It’s no wonder nobody is hungry for that system to exist.

The ease I’ve had in jumping into various projects in Elixir and understand what’s going on and even make changes has been inspiring. I personally feel like that ease could apply to game development as well, which would allow for rapid development. Which isn’t a new idea - that’s exactly why scripting languages are used in many games. I just have a crazy idea of using Elixir for the core engine and the “scripting” language.

There’s also a ton of interesting things thanks to easy DSLs, like creating shaders, objects, scenes, etc., but that’s a ways away.

:wave: congrats on a cool project! One problem with using Membrane for this is that it only works via WSL on Windows if you use plugins with C dependencies (which you do). We’re happy to receive contributions on that matter, but cannot prioritize that right now :slightly_frowning_face:

1 Like

Ah, thanks for the heads up! I’m definitely interested in native Windows support.

The parsing and everything is easy enough to reimplement (I have experience doing this in other languages), but I imagine the portaudio plugin is a problem. Is this the issue I should look at? [Bundlex] Refactor Unix toolchain · Issue #700 · membraneframework/membrane_core · GitHub

Not really, that one is more about refactoring out some accumulated debt :wink: The discussion went on in various places, particularly here: Cannot run on livebook windows · Issue #775 · membraneframework/membrane_core · GitHub, I’ll create a proper issue tomorrow :wink: In short, we managed to make it work in a specific environment years ago and haven’t touched it since. I guess that using Zig toolchain is the first thing I’d try :thinking:

2 Likes

I completely agree. I was searching for a shortcut for doing cross-platform immediate mode graphics rendering, and that seemed like the most straightforward way, but I was wrong!

I’d love for there to be a fully abstracted, cross-platform immediate mode graphics toolkit (something that could handle using DirectX on Windows or, say, Vulkan) but honestly I’m not at the point in my graphics programming journey for that to actually matter.

The ease I’ve had in jumping into various projects in Elixir and understand what’s going on and even make changes has been inspiring. I personally feel like that ease could apply to game development as well, which would allow for rapid development. Which isn’t a new idea - that’s exactly why scripting languages are used in many games. I just have a crazy idea of using Elixir for the core engine and the “scripting” language.

YES!

2 Likes

Here it is: Support for Windows · membraneframework · Discussion #857 · GitHub

2 Likes

I have a couple of neat updates.

  • I got Bundlex compilation (mostly) working on Windows, which might help with Windows builds. Still work to be done for all the plugins to work but it’s a start.
  • figured out some issues with Burrito (entirely my fault), so resources should work (haven’t pushed new releases yet).
  • I got a very simple Metal rendering NIF working. You can see it at GitHub - harrisi/elixir_metal: Elixir rendering with Apple Metal backend.

I’m mainly excited about the Metal renderer. I do most of my dev work on macOS, which has pretty poor support for OpenGL. This has caused several issues and also makes it not clear if I have performance issues due to the OpenGL layer or with Elixir code. I’m hoping that using the Metal backend will make it more clear where performance issues are coming from.

The other interesting thing about it is that macOS has some requirements about what thread drawing is done from. Erlang does a sort of hacky thing to get wxWidgets working on macOS since drawing has to happen on the main thread. I think I’ll have an easier time getting DirectX and Vulkan rendering working for Windows and Linux (and, hopefully, macOS with MoltenVK).

I want to work through the rest of the Membrane/Bundlex issues to get sound working better across platforms, but I should be able to start looking at doing actually interesting stuff in terms of game development soon.

1 Like

You’ve inspired me to start working through the examples on https://learnopengl.com. VERY cool to be able to render anything like this from Elixir!

I have your breakout clone checked out locally, and I am still not able to get the window to open (and stay open), even if I comment out the audio bits. Looks like something OpenGL-y is failing? It is really a shame how poor the debuggability of OpenGL is, compared to the rest of Elixir.

I’ll have to give it another shot when I’m back at my main machine

3 Likes

Are you compiling from WSL or Windows itself? I don’t think I tested compiling it in WSL. You might want to try checking out a previous commit, like 86fb31b8c0b98a332026ff070433ad1c479a2a1c maybe.

By the way, there’s a really handy library someone beat me to making that helps with the wx/gl consts/records: GitHub - kerryb/wx_ex: Elixir wrappers for wx. They just included the OpenGL macros as well, so it’s a bit easier to follow along with things from learnopengl!

1 Like

I’m compiling in WSL. My own stuff works as I’m going through the tutorials. I’ll give it a shot on that commit.