Procedural generation is the state of the art for all rogue-lite crafting games, and it is also the goal we’ve set for ourselves. The game structure of Highrisers requires that whenever you restart the game, the buildings you encounter in are all different and new.
So, how has that worked out so far?
For that, we have to go one step back and look at how objects are placed and stored in Highrisers.
Highrisers uses a grid-like structure we dubbed “slots”, where interactive objects are placed in. That’s also a pretty basic system that has been around for a long time:
So, it seems pretty obvious that we would be using something similar for Highrisers right?
Well… actually, we do now, but for a very long time, our slots were nothing more than a 1-dimensional line.
Why didn’t we see right from the start that a grid would be much more useful?
The answer lies in the history of our project. Our earliest prototype looked like this:
Do you note the flat perspective with depth in z-direction? When you do not have any depth of the floor visible, why should there be a need for a 2-dimensional grid?
Objects, like the apples, where simply placed one by one next to each other.
Later, though, we found it much more useful, realistic and aesthetically interesting to change the perspective of the game so that the top surface of floors and objects would become visible. The slots remained a one-dimensional string; we just added second line in the back. So, slots became something like this:
The front row was reserved for gameItems – small objects that can be picked up; while the back row was only for gameFurniture – large furniture objects that could hold gameItems and that can only be disassembled.
The first drafts of auto-furnishing thus worked like this:
Basically, the program checked where there were any empty slots, randomly selected a fitting object and then placed it. As you can see, this does not exactly make for exciting furniture arrangements.
In the worst case, the algorithm would place 8 copy machines in one row and be done with it.
Even putting a chair in front of a desk would not have been possible under that system (as a chair is not a gameItem – it cannot be picked up, and the front row was reserved for gameItems).
The obvious solution – the change of the 1-dimensional slot line into a 2-dimensional slot grid – would also help us address another issue.
So, we worked to change our slot system into the new one. This touched nearly all parts of our object system and reached deep into the code. In the end, it turned out to have taken several month, but now we could create believable furniture group arrangements and have a proper z-layering and occlusion of all objects, thus solving the dreaded washing machine problem, too.
Now, it seems hard to believe how we ever worked without the grid system. In the next entry, we’ll explain more how this affected procedural level generation.