Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transpiling to Lua

There are a whole host of languages out there that compile to Lua, allowing you to write your Usagi games in something other than vanilla Lua 5.5. Those languages might have other features or a style or syntax that you prefer. This recipe breaks down and shows some examples of how to go about this.

Transpiling works by taking the source language and spitting out a main.lua file that usagi then uses. What’s nice about this is that you can read through the Lua code that gets generated to help see what’s really happening under the hood and debug potential issues.

TypeScript

Using the TypeScriptToLua library, you can write your Usagi games in TypeScript, which is a typed version of JavaScript that’s widely used in web development. You can use it with the npm package manager, possibly even with Bun or Deno too (but that hasn’t been tested).

Here’s an example of a TypeScript Usagi game: https://codeberg.org/brettchalupa/usagi/src/branch/main/examples/transpile/ts_to_lua

Note: the typedefs are currently very minimal and incomplete. Someone maintaining them as an external package would be a good community project. Or just write them by hand as you need them.

Usagi relies a lot upon global functions, tables like gfx and input, and does not use objects or self. So when writing the TS, you’ll need to set special parameters or add comments for the TypeScript compiler. Useful references:

Teal

Teal is a statically-typed dialect of Lua. Teal is to Lua what TypeScript is to JavaScript. It allows you to add types for your code and check those types.

Website: https://teal-language.org/

You install the tl binary to check your types and compile your Teal code into Lua. tl check main.tl checks the types. tl gen main.tl outputs the main.lua that Usagi uses.

You have to handwrite the Usagi types that you use if you don’t want the type checker to fail. It’d be nice if in the future there was a community-maintained typedef if people end up using Teal. Docs on typedef: https://teal-language.org/book/latest/declaration_files.html

Here’s an example of a Teal usagi game: https://codeberg.org/brettchalupa/usagi/src/branch/main/examples/transpile/teal

Here’s an example of main.tl:

-- barebones typedef example for Usagi's `gfx` functions and constants
global record gfx
  clear: function(color: number)
  text: function(text: string, x: number, y: number, color: number)
  COLOR_BLACK: number
  COLOR_WHITE: number
  COLOR_PEACH: number
end

global function _draw(dt: number)
  gfx.clear(gfx.COLOR_BLACK)
  gfx.text("Hello, Teal!", 10, 10, gfx.COLOR_WHITE)
  gfx.text("dt: " .. dt, 10, 32, gfx.COLOR_PEACH)
end

YueScript

YueScript is a programmer friendly language that compiles to Lua, heavily inspired by the indentation-based syntax of CoffeeScript. It’s a fork of MoonScript (see below).

In order to use YueScript with Usagi, you need the yue executables installed. You then compile your main.yue into main.lua with yue main.yue.

Website: https://yuescript.org

Here’s a very simple working example: https://codeberg.org/brettchalupa/usagi/src/branch/main/examples/transpile/yuescript

Here’s an example of main.yue:

export _config, _draw

global _config = -> { name: "YueScript Ex" }

global _draw = (dt) ->
  gfx.clear(gfx.COLOR_BLACK)
  gfx.text("Hello YueScript!", 10, 10, gfx.COLOR_WHITE)
  gfx.text("dt: " .. dt, 10, 32, gfx.COLOR_PEACH)

MoonScript

MoonScript is a programmer friendly language that compiles to Lua, heavily inspired by the indentation-based syntax of CoffeeScript. The syntax is fairly different than Lua.

In order to use MoonScript with Usagi, you need the moon and moonc executables installed. You then compile your main.moon into main.lua with moonc main.moon.

Website: https://moonscript.org/

Here’s a very simple working example: https://codeberg.org/brettchalupa/usagi/src/branch/main/examples/transpile/moonscript

Here’s an example of main.moon:

export _config, _draw

_config = -> { name: "MoonScript Ex" }

_draw = (dt) ->
  gfx.clear(gfx.COLOR_BLACK)
  gfx.text("Hello MoonScript!", 10, 10, gfx.COLOR_WHITE)
  gfx.text("dt: " .. dt, 10, 32, gfx.COLOR_PEACH)

Browse the Examples

The Usagi source code repository has a folder of transpiled examples: https://codeberg.org/brettchalupa/usagi/src/branch/main/examples/transpile