Important News: 26/10/2016 - Call for Presentations to Lua Devroom at FOSDEM 2017
Important News: 04/05/2016 - Community news #2
Important News: 11/12/2015 - Blog opening and contribution guide

Community news #2

By Etiene Dalcol May 04 2016 23:46 General Comments

Meet-ups and conferences!


luaconf logo



Featured Releases

Using Lua coroutines to create an RPG dialogue system

By Jeremy Clarke Apr 11 2016 07:31 Gamedev Reblogged Comments

Recently I've been working on an RPG with a friend, for whom coding is not their strong point. We're using the excellent LÖVE framework, so the whole game is written in Lua.

Scripting of dialogues, animations and in-game events is a hugely important aspect for any RPG, and I wanted to build a scripting system that's easy to use and doesn't require any knowledge about the rest of the game's engine, but is also powerful enough for me to extend with new functionality as needed. This post aims to show how a few simple Lua features can be combined to create a scripting environment that's pleasant to use.

First, let's take a look at the XSE language used in Pokémon modding, as this was probably my main point of inspiration. It has a very straightforward, imperative style, even though each instruction doesn't correspond to a single function in-game.

By this I mean, the whole game engine doesn't freeze just because you are talking to an NPC, however there are points at which the dialogue script cannot progress until the text animations have finished and the player has pressed the [A] button.

XSE Example

Another interesting tool is Yarn, a dialogue editor in which you connect nodes of text together to form complete conversations. It has variables, conditionals and custom commands which you can hook up to different parts of your engine to trigger animations and such. I'd say it's definitely worth checking out especially if you're using Unity or similar.

So how would we go about creating such a system in LÖVE without creating our own language or writing an interpreter for an existing language such as Yarn?

Part 1: Chaining Callbacks Together

The first thing we need is the ability to 'say' some text from inside a script, which boils down to setting a string and then waiting for the user to press a button before we resume execution of the script. The game should still be updating on every frame, even when text is being displayed.

In true JavaScript fashion, we could create an asynchronous API that looks a bit like this:

text = nil
callback = nil

function say(str, cb)
    text = str
    callback = cb

Our game logic & rendering code could look something like this:

function love.update(dt)
    if not text then
        -- player movement code

function love.draw()
    -- code to draw the world goes here

    if text then, 10, 10)

function love.keypressed(key, isRepeat)
    if text and key == "space" then
        text = nil
        if callback then
            -- execute the next part of the script

Then we could write a dialogue script that looks like this, potentially fetching it at runtime with a call to dofile() or something:

say("Hello there!", function ()
    say("How's it going?", function ()
        say("Well, nice talking to you!")

This kind of code grows unwieldy very quickly. It's confusing for non-coders and also error prone (many places to miss out a comma or a closing bracket). You could try some variations such as giving a name to each function, but it still turns out quite unpleasant to work with because managing all those functions gets in the way of what matters: writing good dialogue and scenes. At this point we'd surely be better off writing a Yarn interpreter or using some other existing solution.

But this is not JavaScript, and we can do better!

Part 2: Using Coroutines

For the uninitiated, coroutines are chunks of code that can be jumped to much like functions. A coroutine can suspend itself (yield) at will, returning to the point at which it was called. At a later stage, the program can jump back into the coroutine and resume where it left off.

I suppose this puts them in a sort of middle ground between functions and threads. They are more powerful than functions, but you still have to manage them explicitly - you can't just leave them running in the background to do their own thing. Typically they are used to break up an intensive task into small bursts, so that the program can still function as normal (receive user input, print to console, etc.)

Hang on a minute, doesn't this sound a lot like what we want from the dialogue scripting system? Executing a single line and then suspending the script while we give control back to the game loop?

Let's see how we could achieve the same result as Part 1, only using a coroutine instead of a chain of callbacks.

text = nil
routine = nil

function say(str)
    text = str
    text = nil

function run(script)
    -- load the script and wrap it in a coroutine
    local f = loadfile(script)
    routine = coroutine.create(f)

    -- begin execution of the script

The important difference here is the implementation of the say function. Instead of setting a callback for later use, we tell the current coroutine to yield. This means we can't call say directly from the main program, only from inside a coroutine. Also there is now a loader function which creates a new coroutine and tells it to run the script.

Next we need to rewrite love.keypressed to make it resume the coroutine on the press of the space bar.

function love.keypressed(key, isRepeat)
    if text and key == "space" then
        if routine and coroutine.status(routine) ~= "dead" then
            -- execute the next part of the script

And finally, we can write a script that looks like this:

say("Hello there!")                -- the script suspends once here
say("How's it going?")             -- it suspends again here
say("Well, nice talking to you!")  -- it suspends for the 3rd time here

Part 3: Sandboxing and Advanced Usage

If we declare a global variable, 'n', we can create an NPC that remembers how many times the player has spoken to it.

say("Hey kid, I'm Mr. Red!")

if n == 0 then
    say("I don't believe we've met before!")
    say("You have spoken to me "..n.." times!")

n = n + 1

It's great that this works, because it does exactly what you would expect and it's super easy to use. However, there are some problems.

If all the variables are stored in the global environment, we risk running into naming collisions which at best will cause scripts to behave incorrectly and at worst could replace key functionality and crash the game.

Additionally, having our game's state scattered across a ton of globals makes things very difficult when we want to think about serialising the gamestate to produce a save file.

Fortunately Lua makes it easy to swap out the environment of a function for any table, using setfenv in Lua 5.1 or _ENV in Lua 5.2 or greater. We don't need to change our scripts at all, we just need to make sure that they still have access to the say function, by placing it in their environment (the game table below).

game = {}

function game.say(str)
    text = str
    text = nil

function run(script)
    local f = loadfile(script)
    setfenv(f, game)
    routine = coroutine.create(f)

    -- begin execution of the script

It also might be helpful to have a script that is called once at startup, to initialise all the game variables to default values, or load them from a save file.

As far as animation goes, we can drop in a tweening solution like flux, along with a few helper functions which will allow us to pause the script until the animation completes.

game.flux = require "flux"

game.pause = coroutine.yield

function game.resume()

and then we could tween a character to x = 800 with a script like this:, 2.0, { x = 800 }):ease("linear"):oncomplete(resume)

which yes, is a mouthful for non-coders, and it introduces an asynchronous aspect back into the scripting API. We would probably benefit from a custom animation system that's more more tailored to our game, but this hopefully goes to show how easy it is to make scripts that can interact with any other part of the engine.

What Next?

I hope I was able to teach some interesting ideas here! I wanted to share this because coroutines are something I've known about for a while, but until now I've never had a good reason to use them. I would be interested to know which other languages can be used to create a system like this.

Here are some things you might want to do next, to create a more full-featured RPG engine:

  • Add lock() and release(), so it's possible to display text while the player is moving, or stop the player from moving even when there is no text.
  • Add an ask(str, ...) function whereby the player can choose from a list of options (e.g. yes/no)
  • Download a level editor such as Tiled, or create your own. Try attaching some scripts to game objects such as buttons and NPCs. Relevant tutorial on using Tiled with LÖVE
  • Create an easy-to-use animation system with commands such as 'face X direction' or 'move N steps'
  • Add character portraits so that the player knows who's speaking (this might require you to add an extra parameter to say() or some new functions)
  • Consider how you would go about handling save data. How to distinguish it from data which is part of the gamestate but does not need to be saved permanently?

Build a Standalone Executable

By Eric R. Schulz Mar 28 2016 12:15 Tools Comments

luastatic is a command line tool that builds a standalone executable from a Lua program. The executable runs on systems that do not have Lua installed because Lua is embedded alongside the program. Lua 5.1, 5.2, 5.3 and LuaJIT are supported. luastatic can be downloaded from GitHub or LuaRocks.

Lua is commonly used as an embeddable scripting language as part of a larger program written in another language. However, Lua can also be the primary language used to implement a program. Programmers using C are accustomed to building an application to a single executable that is distributed to the end user. luastatic does the same for Lua programs.

Below is a description of the arguments luastatic supports:

luastatic main.lua[1] require.lua[2] liblua.a[3] module.a[4] -Iinclude/lua[5] [6]
[1]: The entry point to the Lua program
[2]: One or more required Lua source files
[3]: The Lua interpreter static library
[4]: One or more static libraries for a required Lua binary module
[5]: The path to the directory containing lua.h
[6]: Additional arguments are passed to the C compiler

The shell script below shows how to use luastatic to build this program for GNU/Linux and Windows. The program uses Lua, LuaSQLite3, and SQLite3. I tested the script on Ubuntu 15.04.


# download build tools (if necessary)
sudo apt-get install build-essential make mingw-w64 unzip libreadline-dev

# download program dependencies
wget -O simple.lua

# extract dependencies
tar -xf lua-5.2.4.tar.gz

# create build directories
mkdir linux windows
cp simple.lua linux
cp simple.lua windows

# build Lua for GNU/Linux
cd lua-5.2.4
make linux
mv src/lua ../
mv src/liblua.a ../linux
make clean
# build Lua for Windows
make mingw CC=x86_64-w64-mingw32-gcc
mv src/liblua.a ../windows
cd ../

# build luastatic using itself
./lua luastatic.lua luastatic.lua linux/liblua.a -Ilua-5.2.4/src
cp ./luastatic linux
cp ./luastatic windows

# build SQLite3 for GNU/Linux
cd sqlite-amalgamation-3110100
cc -c -O2 sqlite3.c -o sqlite3.o
ar rcs ../linux/sqlite3.a sqlite3.o
# build SQLite3 for Windows
x86_64-w64-mingw32-gcc -c -O2 sqlite3.c -o sqlite3.o
x86_64-w64-mingw32-ar rcs ../windows/sqlite3.a sqlite3.o
cd ../

# build LuaSQLite3 for GNU/Linux
cd lsqlite3_fsl09w
cc -c -O2 lsqlite3.c -I../sqlite-amalgamation-3110100 -I../lua-5.2.4/src -o lsqlite3.o
ar rcs ../linux/lsqlite3.a lsqlite3.o
# build LuaSQLite3 for Windows
x86_64-w64-mingw32-gcc -c -O2 lsqlite3.c -I../sqlite-amalgamation-3110100 -I../lua-5.2.4/src -o lsqlite3.o
x86_64-w64-mingw32-ar rcs ../windows/lsqlite3.a lsqlite3.o
cd ../

# build simple.lua for GNU/Linux
cd linux
./luastatic simple.lua liblua.a lsqlite3.a sqlite3.a -I../lua-5.2.4/src -lpthread
strip simple
cd ../

# build simple.lua for Windows
cd windows
CC=x86_64-w64-mingw32-gcc ./luastatic simple.lua liblua.a lsqlite3.a sqlite3.a -I../lua-5.2.4/src -lpthread
strip simple.exe

luastatic generates the C source file simple.lua.c containing the Lua program and runs the following command to build the executable:

cc -Os simple.lua.c lsqlite3.a liblua.a sqlite3.a -rdynamic -lm -ldl -I../lua-5.2.4/src -lpthread -o simple

If you are familiar with C you can read the file simple.lua.c to see the generated calls to the Lua C API.

If you find a program that luastatic does not build or where the resulting executable does not behave the same as when run with Lua, please report the issue or email with enough detail to reproduce the build.


Subscribe to Lua.Space by Email