Willis Tower Constructor (Security Management Simulator - Post 2)
I’m working on leveling up my building generator, from creating a rectangular cube, to making something that looks like a more defined skyscraper. Specifically I’m trying to emulate the Willis Tower or NEMA in Chicago.
They have a tiered, cubical structure that should be a pretty good place to start for making a more complex building, before diving into something even more complicated like the art deco Empire State Building.
If you look at Willis or NEMA from above, it looks like a simple grid. My basic building function takes in values for the width (x), height (y), and number of floors (z). The NEMA building function will do the same, but starts with rounding the x and y inputs to values that are multiples of the simple grid. More on that later.
My minimum grid size will be 3x3 (Like Willis), and the max will be 5x5. Any bigger than that and I think it’ll lose the simplicity of the design. The x and y will be assigned independently and randomly, so each side will get an integer in the 3 to 5 range.
Because there are only 9 possible building grids, I hard-coded a bunch of if/else statements to find the closest configuration that matches the height-width ratio of the values passed to the function. The lowest ratio is a 3x5 at .6, and the highest is a 5x3 at 1 and 2/3rds. In the case of a square configuration, the algorithm randomly picks between a 3x3, 4x4, and 5x5 layout, since the ratios for those are all the same.
Then I make sure the “squares” are actually square. I take the height divided by grid height (perhaps 23 / 4) and the width divided by grid width (22 / 4) and get the average of the two rounded to the nearest who number. (5.75 and 5.5 -> 5.65 -> 6) That will be the size of the squares. For this example, an input of 23 width and 22 height would get rounded to 24x24, which is a 4x4 grid where each square is made up of 6x6 tiles.
Next I split the building up vertically into tiers. I’ll refine this later, but I currently have some hard-coded if/else statements to determine how many tiers. It picks from a range of 4-10 tiers, but the upper end of the range is only available if certain conditions are met. The taller the building and the bigger the grid, the more tiers there can be.
One of the challenging elements to figure out that I wanted to have is to set both the height of the tiers and the distribution of the tiers according to a curve. For the purpose of example, let’s say you had 4 tiers with 10 squares. It could be arranged with 1 square at the highest tier, 2 at the next tier, 3 at a lower tier and 4 at the bottom. But that’s pretty linear. You could also set it with 1 at the highest tier, 1 at the 2nd tier, 3 at the 3rd tier, and 5 at the lower tier. The constraints is that no tier can have more squares than a tier above it, and the highest tier should consist of 1, 2, or 3 squares. This was important to me so that I could have more controlled variation among my procedurally generated elements. By following a curve, hopefully it looks planned and intentional instead of randomly assigned.
I just wasn’t sure how to implement this, but I thought remapping would be helpful. I first made a linear mapping function, like linear() in After Effects. It takes an input value (t) and looks at where it falls between two values (t_min and t_max). It then linearly maps it between two other values (value1 and value2).
Then I used my linear mapping function to make an exponentially mapping one. It takes in a value, the minimum and maximum range for the value, and exponent. It works by remapping the range to a range of 0.0-1.0, raising value to an exponent, and then remapping it back to the original range.
Unfortunately, this doesn’t work for this purpose, even though those functions came in handy elsewhere. I don’t know the maximum value, because it varies, so that’s no good. And it’s important that the resulting values add up to the number of squares used. But how do you ensure that? Here’s the solution I settled on.
Make a loop: [for i in “number of tiers”] Use the integer as a base and multiply it by a weight. Raise that value to the power of an exponent (I used a range of 1.0 to 10.0). Round it to the nearest whole number. Then total up the values. If it’s bigger than the number of grid squares, the weight is too big, and needs to be decremented by a factor. If the total is too small, then increment the factor to increase the weight. And anytime you switch from incrementing to decrementing or vice versa, cut the factor in half. Eventually the total will get closer and closer until it equals the number of grid squares, kind of like a binary search. It required an average of 10 iterations to get it right, and I never saw more than 20, so it’s not a very expensive operation. Then I just assign those values to an array.
I used the exponential mapping function from earlier to assign floor heights for each tier. Each of these floors is the top of a tier. The maximum end of the range will be the top floor of the building, and the minimum will be a floor 20-50% up from ground level. (All the other tiers will be somewhere in this range, hence the mapping). The exponential mapping function allows me to influence how these floors are distributed, whether equally distant from each other or bunched at the higher or lower end.
Now I just have to implement the algorithm that places these grid squares in relationship to each other. I’m still struggling to wrap my head around that part.
In the process of working on this, I realized I don’t have a great building visualizer. So far I’ve been taking a floor slice out of my building and applying it to a tile map, but I don’t have a way to visualize it as a whole. It makes debugging hard. I built a simple 3d generator that spawns a cube resource in positions that correspond to the array. I just needed a camera to frame it and a light to see the faces.
A side not I’ve been thinking about: One of the things you hear in the game development space is to get a working prototype out as soon as possible. That’s fair, but I don’t really have that many tools in my game dev tool kit yet. I don’t know the first thing about prototyping. It’s all a learning experience for me. For now I’m gonna focus on building stuff that interests me, and learning what I can along the way. Even if this game comes to nothing and I never use these procedurally generated buildings, it’s not a waste because it’s a learning opportunity. I think the most important things for me right now are chasing things that keep me motivated.
More to come!