As good as existing editing tooling for LÖVE2D, sometimes source debugging is hard to beat. I don’t feel the strong need for an IDE; the tooling available for vim and VSCode is excellent for editing, reading and running these games. But especially without a compiler, it can be really helpful to be able to set breakpoints and inspect values at runtime.

After the most recent GD-50 project, I found myself more interested in a source debugger for Lua running in LÖVE2D. For whatever reason, that doesn’t seem to be a topic of great community interest. After a timebox worth of searching, I decided that Zerobrane Studio, one of the editors I’d disregarded when I originally set up my environment, looked like the most promising tool.

I’d disregarded Zerobrane partly because it looks like it is built around the Scintilla component. Don’t get me wrong… Scintilla is a marvel. I’ve even embedded it in my own software in the past, when I wanted a syntax highlighting editor for small things. It worked amazingly well with almost no effort from me. I just wouldn’t personally find it very comfortable for use at length, at least in the forms I’ve tried it so far. And these projects are going to have me in an editor a whole lot. That by itself wouldn’t have stopped me from even kicking the tires, though. The other reason was because its linux download was a Makeself script that immediately caused sudo to ask for my password without any explanation, and when I inspected the script there had been no occurrences of the word sudo. At that point I wasn’t interested enough to unpack the archive and find what was asking and why.

After reading more on its debugging facilities, it seemed worth revisiting. Looking at the makeself docs, it is easy enough to unpack and inspect:

bash --noexec --target zerobrane

unpacked the archive into a newly created zerobrane directory.

From there, reading the source to the short script made it plain. It wanted to use sudo for two reasons:

  1. It wanted to install in /opt/zerobrane. I have no objection whatsoever to that.
  2. It wanted to write things to and create symlinks in /usr/local/bin. I object strenuously to that. If anything that’s not my package manager wants to write there, I’d better understand a very good reason for it. And, honestly, already be very certain I want to use it.

All in all, though, I’d rather just install this to my home directory without root privileges involved in any way. So here’s what I wound up doing:

Unprivileged Install and Uninstall Scripts

Changing the install location and removing the need for privileges was simple. Here’s




echo Installing ZeroBrane Studio $VERSION...

if [ -d "$INSTALL_PATH" ]; then
  if [ -e "$INSTALL_PATH/cfg/user.lua" ]; then
    echo "Copying cfg/user.lua file..."
    cp "$INSTALL_PATH/cfg/user.lua" "app/cfg/user.lua"

mkdir -p $INSTALL_PATH

cp -rp app/* $INSTALL_PATH

for ICON_SIZE in 16 22 24 32 48 64 256
  xdg-icon-resource install --novendor --size $ICON_SIZE $INSTALL_PATH/zbstudio/res/icons/${ICON_SIZE}x${ICON_SIZE}/apps/zbstudio.png "zbstudio"

UPDATE_MENUS="`which update-menus 2>/dev/null`"

xdg-desktop-menu install --novendor $INSTALL_PATH/zbstudio/res/zbstudio.desktop

if [ -x "$UPDATE_MENUS" ]; then

if [ -e "${HOME}/.local/bin/zbstudio" ]; then
  rm ${HOME}/.local/bin/zbstudio
ln -s $INSTALL_PATH/ ${HOME}/.local/bin/zbstudio
chmod +x $INSTALL_PATH/

echo $VERSION | tee $INSTALL_PATH/VERSION >/dev/null

cp ${HOME}/.local/bin/zbstudio-uninstall
chmod +x ${HOME}/.local/bin/zbstudio-uninstall

echo Done.
echo To uninstall ZeroBrane Studio at a later time, run:
echo -e '    zbstudio-uninstall'

And the corresponding uninstall script:




if [[ $VERSION == "" ]]; then
  echo No ZeroBrane Studio install found, aborting.

echo Uninstalling ZeroBrane Studio $VERSION...

for ICON_SIZE in 16 22 24 32 48 64 256
  sudo xdg-icon-resource uninstall --novendor --size $ICON_SIZE "zbstudio"

sudo xdg-desktop-menu uninstall --novendor $INSTALL_PATH/zbstudio/res/zbstudio.desktop

UPDATE_MENUS="`which update-menus 2>/dev/null`"

if [ -x "$UPDATE_MENUS" ]; then
  sudo update-menus

if [ -e "/usr/bin/zbstudio" ]; then
  sudo rm /usr/bin/zbstudio

sudo rm -r $INSTALL_PATH

if [ -e "/usr/bin/zbstudio-uninstall" ]; then
  sudo rm /usr/bin/zbstudio-uninstall

echo Done.

After this, I needed to modify ${HOME}/.local/bin/zbstudio similarly:


if [[ "$(uname -m)" == "x86_64" ]]; then ARCH="x64"; else ARCH="x86"; fi
CWD="$PWD" # save the current directory, as it's going to change

(cd "${HOME}/.local/zbstudio"; bin/linux/$ARCH/lua src/main.lua zbstudio -cwd "$CWD" "$@" 2>/dev/null) &

Using Zerobrane Studio as a debugger for my LÖVE2D game

After that, it was simple. I opened my game’s main.lua from a shell prompt:

zbstudio main.lua

In the IDE, I then had to:

  • Go to the Project menu, then the Project Directory submenu and choose Set From Current file.
  • In the same Project menu, go to the Lua Interpreter submenu and choose LÖVE
  • In my game’s love.load() function, add a line before the first line of the function:

if arg[#arg] == "-debug" then require("mobdebug").start() end

Then I could launch the debugger, set breakpoints, step in/out/over, inspect variables, etc.

The final project for this course will either use the LÖVE or Unity environment. Having a usable source-level debugger removes one of the items that had me leaning toward Unity. (I still haven’t chosen my game for that, but everything I’ve considered so far would be very reasonable with either one.)

I’m still trying on Kev Quirk’s “100 Days To Offload” idea, after a weekend off. You can see details and join yourself by visiting