So I’m making a turn-based tactics game (think Tactics Ogre, Final Fantasy
Tactics, Disgaea, etc.). I need a way to build levels, but I have neither the
artistic talent to work in a modelling program or the time to really build
myself a level editor.
Since I’m still in the prototyping/flesh out stage, my level needs are pretty
simple. The goal I’m shooting for is easier to show than to tell, so take a
look:
That’s the basic level I’m shooting for at this point. Basically a chessboard
with differing heights. It’s inspired by Danc’s Miraculously Flexible
Prototyping Tiles. So think Legos, or Minecraft.
I want an easy way to specify this, in just a text file. So what pieces of
information do I need at this point?
Dimensions of the board (width/height in squares)
Heights at any given place
And because I’m incapable of running with just blank squares, what sort of
texture to use on each block
And because I want to make things pretty:
Background texture
Light color/direction
I’ll need to add more in the future (object placement, unit starting
locations, etc), but that’s enough to get going. Let’s take a first pass at a
text format for this:
Most of those fields are self explanatory. Dimensions are just width and
height, light-color is a HTML/CSS style color specifier, the direction is a 3
component vector.
Remember, the level is structured like a collection of legos that all happen
to be a uniform size, so we can consider it as a set of flat layers. There are
2 layers in this map, hence num-layers.
Finally, the layer fields give you the actual block layouts. Each number
corresponds to a block type in the game code, with 0 representing an empty
space. (If you’re curious, 2 is dirt, 3 is grass, 5 is stone and 6 is water).
There will be (width * height) numbers following each layer command.
It’s simple and relatively easy to type in by hand. But damn, that means I
have to write a parser. I hate writing text parsers. But I have an idea! Let’s
try massaging that text format into something a little more structured:
That is an s-expression (http://en.wikipedia.org/wiki/S-expression). They
happen to be super easy to parse and are probably best known as the syntax of
the Lisp family of languages. But I still don’t want to write a parser.
Instead, I’m going to fire up a Common Lisp environment and let that handle
parsing it:
Now easy as that, instead of a text file I have a data structure that I can
pull apart and use to define the level.
First, let’s make a basic container class to hold the information, and a quick
function to take the list (s-expression) above and turn it into an instance of
that container class.
Now to load a file and turn it into a blockmap object we do:
Sweet, now all that’s left is to make it easily available to C. We could
probably just write out .c files, but generating the proper syntax for that
sounds tedious, so I’m just going to write out a binary format that we can
load easily. Something like:
That can be loaded in one shot with a simple fread() or [NSData
dataWithContentsOfFile:];. From there, just verify that the magic/version is
good and you’re good to go.
To write that out from Common Lisp, we’ll need to pull in an extra library to
deal with encoding floating point values. I use Marijn Haverbeke’sieee-
floats. With that, the code to write out a binary block map file looks
like this:
I’ve left out some helper functions (make-c-string, write-int32 and make-argb); they’re in the source package linked below. But really, that’s all
there is to it.
So technically yes, I wrote a parser. But the language did all the hard work
for me; I just took the data it provided and chucked it into a binary file.
And importantly, it’s extremely easy to add/remove fields from this.