This post is all about how the
rooms are created randomly in LOTWK.
It’s a pretty extensive subject, so I’ll divide it up into two meaty
posts, instead of one giant one. The
first step for the room generation in LOTWK is to create the room shape, which
we do by placing the floor tiles. The
result of this first stage looks something like this:
The floor tiles are placed based on
some descriptors in the XML data files.
These descriptors set out some simple factors such as how many blocks of
tiles to place, their approximate size, and any limitations on where and how to
place them. The details are pretty dull,
so I’ll just throw in this example XML and you can pick it apart yourselves:
<room name="test room"><mainBlock width="12" height="12" /><block1 width="8,8" height="10,10" count="1,2" angle="180,180" tag="x" /><block2 width="3,3" height="10,10" count="1,2" angle="180,180" startType="previous" /><block3 width="8,8" height="4,4" count="1,1" angle="90,90" startType="tagged" tag="x" /><block4 width="6,6" height="4,4" count="1,1" angle="90,90" startType="previous" /><block5 width="2,4" height="2,4" count="4,8" startType="random" /><columns1 width="2,2" height="2,2" count="1,3" buffer="3" /><templates1 category="furniture" count="4,12" tags="normal,desks" /><templates2 category="furniture" count="4,12" tags="normal,benches" /><templates3 category="loot" count="1,4" /><templates4 category="decor" count="5,15" /><templates5 category="structural" count="1,5" /></room>
As you
can see, there are a series of “blocks” elements, and it is these that describe
the approximate shape of the room. Each
location theme (snow caves, forest, dungeon, etc) will have a large variety of
room styles described through XML “room” nodes, so that a noticeable variety of
rooms exists, instead of them all being hewn from the same cloth.
The
next phase is to throw in the walls.
This is pretty straightforward – because the room is tile based,
determining which tiles should become walls is a simple matter of finding floor
tiles with empty tiles adjacent to them.
Corner wall tiles can be identified in a similar way. This results in something like this:
Gah! What’s with the six bajillion lights on the
walls!? This is how LOTWK determines
where to place wall-torches and other wall-mounted light sources. Each wall segment is a template (a group of
objects) which gets placed. This allows
for things like paintings, banners, torches, and all other manner of objects to
sit neatly aligned with the walls.
Because the walls can be any shape, a system that tried to automate placement
of objects on walls would result in a lot of ugly clipping issues, or worse,
floating objects! So we use a template grouping
approach, where templates are randomly placed for each wall segment, including
wall decoration and lighting.
So the next phase is to clean up
all those extra lights. This is dead
simple – the game iterates through the lights and deletes those that are too
close together. The end result is
something like this:
Next up we need to fill in dark
areas. These dark areas are created
because there are no nearby walls, and therefore no wall-mounted light sources
to fill the darkness. So let’s place
some floor-based light sources. And
while we’re at it, let’s also extinguish a few of the existing light sources to
add a little variety. The result looks something
like this:
The room is still very barren though
– it’s just walls and light sources. It
needs some furniture. This is achieved
in a similar fashion to the wall placement – it uses template groups of objects
and tries to place them around the room.
An example grouping might be a writing desk, which would consist of the
desk, a chair, the quill and ink, and perhaps some scrolls of paper. These items are all grouped together in a
template data file, so that the game engine can then attempt to place them all
together up against a wall.
This brings me to the real power of
the template system – placement types.
Each template group has a placement type variable associated with it,
which tells the engine how best to place the template in the room. These types are things like “up against a
wall”, “in a corner”, “in open space in the middle of the room”, “between two
walls”, or “tucked away in an alcove”.
By only allowing a template to be placed in a specific fashion, it
prevents weird situations like a bookshelf sitting alone in the middle of the
room. With some furniture thrown in, the
room looks something like this:
(note, the game is still early in development, so there is
not much furniture to place yet, and so the room is still quite barren with
only a few rotting desks and some pipes on the wall)
The final stage of room generation
is to make the room look a bit prettier.
This is done through floor patterning and edge bordering. Floor patterns work much as object templates,
but instead of a group of objects, it’s a group of floor tiles which get placed
around the room. The bordering is where
the game detects the tiles that run alongside the walls and makes them into nice
border tiles, which makes the room look like it was designed rather than thrown
together using a random number generator.
The result of the floor additions looks a bit like this:
And there it is; a room with stuff
in it and torches on the walls. What
more could a band of psychopathic, money-hungry adventurers ask for?
Next time I’ll go into the
specifics of how monsters are selected for placement in the room, and how the
game will try and balance the room layout with the type and quantity of
monsters.