The last time
we looked at how to enabled Lua scripting in your C++ code.
This time, we take a step forward and actually write something
So, in the game-specific layer, I have three methods that get
called from the engine: create(), update() and draw(). In
the create() method, all the systems are created and the start-up
script is loaded and called. In update() the systems are updated,
and in the draw() function, all the “passive” rendering systems
are updated. All in all it looks like this:
I’ve taken some of the code out for clarity’s sake, but the
basic idea is still there. The Lua portion can be updated
by calling the loadFromScript() method whenever we want,
for example when the user presses F3 or when any of the scripts
has been modified. Nifty!
So, that’s pretty much what’s going on in C++ to get things
rolling. Let’s take a look at Lua now.
Finally, some scripting!
First off, let’s take a look at the stage.lua script we loaded
in the previous snippet:
This script should be pretty self-explanatory, but let’s go
through it anyway. First, we define the stage table and set
a couple of properties there. This could also be dynamically
loaded from different files that denote different stage set-ups.
Then, we have the create() method that gets called from C++.
This method loads the level from a file, sets the camera
position and marks the stage as successfully created. Great!
Although… Nothing happens yet. Let’s look at the loadLevelFromFile()
function a bit closer:
Here we load a Tiled map from a file. The actual loading code is
in C++, but it could just as well be done in Lua - that’s up to you.
If the file exists, the map is loaded and passed on to a new
function called processTiledMap(). This function is responsible
for looking through the objects in the map and creating them. This
is where the magic starts to really happen!
The main thing I wanted to incorporate was dynamic object creation.
I want to create Tiled maps, place objects here and there and not
really care whether or not I have already implemented them in code.
When I design the levels, I want to focus on that and not care about
the code - or worse, jump back and forth between coding and level
creation. So, let’s take a look at the processTiledMap() function:
Looks rather simple, doesn’t it? We go through the map layers,
and if the map layer is called “Spawns”, we process it further.
At the moment, this is the only layer we’re interested of.
Moving onward, let’s look at the processSpawns() function:
What happens here? We go through the map objects and check
if we have a script with the same name as the object. If we
have such a script, we load it with require() and call new()
method on it (which acts as a constructor). For example, if we
have an objects named “Torch” in our map, we check if there’s
a file called “torch.lua” in the scripts folder. If there is,
we construct a new Torch game objects by calling the new()
function on the script. By using require() we ensure that
each item module is loaded only once and none of the scripts
are loaded that we do not need.
Next, let’s look at the Torch.lua file to see how we construct
the item in the end:
With the help of underlying C++ and its helper methods, constructing
a new Torch is rather simple. We create a new entity, add a physics
body sensor, create a sprite and set the position of the torch
to where the map objects says it should be.
Using Lua along with C++ is rather simple and provides a nice set
of dynamic functionality that’s missing from C++. Creating
the underlying engine and bindings can be rather tedious, but
it will definitely pay off in the end.