Mechanic #110 - LEGO World |
| Posted: 10/21/10
A modular world-building system using stacks of building blocks on a 2D grid. |
Building a World, One Brick At a Time |
A few years ago, I was building a Roguelike game engine and wanted a basic system where I could put objects on top of objects, like a sword on top of a table. I created a pretty simple system of using a stack for each grid cell, allowing me to drop objects on top of each other. The implementation was simple. Each object had a height and was the width and height of a single cell and there was a stack for each cell in the world, such that only the top object could be added or removed. I never got around to finishing that engine, but that was probably because I was spending all my time building structures in the game out of these little blocks.
Even with just a simple implementation, it was immediately obvious that such an approach could be used to create a lot of the world content for a game. Truthfully, it seemed somewhat excessive. Why would you need such modular building blocks to build a game when you can do it so much more easily using pretty much any other standard method. I still don't have an answer to that, but seeing something like Minecraft makes me think that maybe creativity is a reason unto itself. Also, such a modular system could allow procedurally generated games to produce content more easily.
Before I get to it, I just want to say that I'm not claiming the idea of building a world out of a stack of objects. This is simply some ideas for implementation, with an eye towards simplicity.
The basic building block of the world is a... well, a building block. All objects and scenery are are building block. They all take up one cell's width and height, with a variable height. To keep things simple, the common blocks used to build scenery would be built with some standardization. I've decided, as you can see above, to have 32x32 pixel grid cells, with a base height of 8. This means that four blocks stacked on top of each other would create a cube. The game characters in this example are roughly cube shaped, being around 32 pixels high.
Blocks can have a height of zero. Though they still take up physical space in the world, they are considered flat or at least flat-ish. A good example would be something like an amulet on top of a table. If you would to stick a block on top of the amulet, it would be obscured from view as the second box would be offset zero pixels.
For the sake of argument, assume that the block have no other attributes. You can certainly add attributes if you like, such as structural damage capacity, weight, or even elasticity (the height shrinks the more weight is put on top). Adding attributes and allowing you to affect blocks in a manner beyond simply stacking them would be the foundation of an interesting simulation. For instance, you could have stone walls which can't be damaged by basic weapon attacks, but can be destroyed by explosions. If you build an entire castle out of these types of blocks, you could have completely destructible scenery.
The basic way that blocks are put together is through a stack. Simply put, blocks are added to the top of the stack in last-in, first-out order. You may remove blocks from the middle of the stack, but to keep things simply, you can not insert them. Only drop them on the top. If you really wanted to add insertion, it should be possible, but things are about to get a little more complicated.
Before I do that, there are two special features of stacks that I want to point out. The first is that the stack has a height. The amount of empty space left in the stack is equal to the stack height minus the height of the blocks in the stack. For simple implementations, the stack height could effectively be infinite. However, the stack height will be important in a second when I talk about stacks of stacks.
Second, the bottom block in a stack is considered Fixed-In-Place. Again, this will be important in a moment, but the general idea is that the bottom block is stuck there. If anything is done to this block, the stack will fundamentally change - possibly being destroyed or replaced by another stack.
Quick example before I get to the complex stuff. Let's say that you have a knight who wants to move from one stack to the next. The knight is a type of block as well, like a LEGO minifig, and exists as the top element on the stack. When he attempts to move to the next stack, he checks the relative heights of the two stacks and compares it to his climbing value. If he can move, he is simply popped off the top of one stack and pushed onto the top of the neighboring stack.
If an object moves when it has something on top of it, like a knight riding on another knight's shoulders, everything above the moving knight would be popped off with him and moved to the next stack with him. This process would be simple, but has pretty cool possibilities. For instance, rather than the knight being a single block, the knight could be three separate blocks (legs, body, head), with the legs operating the movement of the entire knight.
Now, say you want to create something that is not easily modeled by a single stack of objects, like a bridge or the second floor of a building. The really simple way to solve this problem is to break each stack into two stacks, one for below the bridge and one for above it. In the above illustration, stacks 1 and 4 are single stacks that are 64 pixels tall. Stacks 2 and 3 consist of two separate stacks, the bottoms being 40 pixels tall and the upper stack being only 24 pixels tall. Moving a character around is just a matter of figuring out which of the two stacks he can enter or is most likely to enter, checking to see if there is enough room on that stack to push him on top, and then doing so.
That's where the stack height comes into play. You can break a stack into any number of smaller stacks, the heights of which should add up to the height of the original stack. Breaking a stack is instigated by the insertion of a Fixed-In-Place block somewhere in the empty area. That block becomes the base block for the new stack, and everything below it becomes the bottom stack.
The reason why the bottom block is Fixed-In-Place is because if that changes, it's stack is merged with the one below it. Say a bridge is no longer stable and collapses. That bridge pieces stops being fixed in place and it's stack is merged with the one below it - causing all blocks from the top stack to be pushed onto the bottom one. Similarly, if there are a bunch of Fixed-In-Place objects on top of each other, each will be it's own stack - albeit a stack exactly the same height as the block with not emptiness above it (there is only one Fixed-In-Place block per stack). Changing the Fixed-In-Place value of these blocks or destroying them altogether becomes a process of merging their respective stacks together with the stacks immediately below them.
Composite Blocks and Attachments |
|