// July 1st, 2012 // Comments Off // Ugly Baby
Our June, 2012 has focused on creating “patterns” — scripts that compose simple geometric solids in a scene that you can fly through. In particular, “foreground” patterns are all the pieces you’re trying to avoid smacking into when playing the game. Combine enough individual pieces (such as these arcs), and you get a tunnel:
When we begin creating one of these patterns, we typically have an end result in mind (though we may often achieve something entirely unexpected). For example, we were thinking “simple geometric city,” and decided to begin with one that represented buildings as a grid of blocks:
Interesting, but not actually a usable city. Sure, someone could live there, and it looks neat, but it’s not exactly what we had in mind, and there’s no path through it. If you played that level, you’d have to avoid this thing entirely (or smack into it and hope you had enough health left afterwards). So, to refine, we did this:
- Constrain it by not overlapping pieces. Pretty straightforward: generate fewer “buildings,” farther apart.
- Create some tall, narrow, green pieces and some short, wide, beige ones. The former represent buildings, and the latter represent walkways.
A really, really simple and abstract city representation:
There are now gaps formed in the pattern, such that the player can get through it without dying. The pieces are spaced farther apart, and there’s also a “thinning selector” that randomly tosses away buildings (to create the gaps). We can easily do all sorts of things here. For example, what if we made everything tall, and changed their colors? Here’s two lines we added to the script:
- mutator.scale(queue, [1, 1, 16])
- mutator.set_color(queue, hsv_to_rgb(rndsym(20), 50, 50))
And here’s what that produced:
There are all these paths you could take around the buildings, and spaces for hidden treasure (points? free gum?). Just for fun, tweaking a few parameters more (hue, scale, rotation) gave us confetti:
And constraining one dimension and using T-shaped pieces (fading from pink to red) or white 45-degree elbows looked like these:
That’s the basics of the system we’ve been working to create over the past year. Ideally, we should be able to change one variable (or two) and create something new and cool. These are simple examples, but our next step will be to layer multiple patterns to increase complexity. Here’s how we’d do a more cohesive structure like a tunnel of blocks:
- Create a grid of boxes.
- Hollow out that grid, keeping everything outside a square prism volume (a center column).
- Add “jitter” (slight randomization) to the remaining pieces’ lateral and vertical positions.
- Give them random hues (purple-blue) to mix things up.
Here’s that in action:
It’s fun to fly through, and immediately made us consider refinements. For example, if the level had an interesting skybox, we could randomly erase individual blocks, allowing the player to peek through the tunnel and see that skybox, or even to fly outside the tunnel. Or, what if we did this:
- Go for rings instead of a grid.
- Turn all the generated pieces to face vertical axis:
A simple transformation, but something that’d take a long time to do by hand, if we had to place each piece. Procedural content generation’s most powerful when you can make tiny changes to your algorithm and come up with something that changes an entire level (preferably in a useful fashion).
Now, by this point, we were getting tired of plain, untextured polygons. Fie. We wanted to try out a shader on some hexagons.
Shader (Wikipedia): In the field of computer graphics, a shader is a computer program that is used primarily to calculate rendering effects on graphics hardware with a high degree of flexibility. Shaders are used to program the graphics processing unit (GPU) programmable rendering pipeline, which has mostly superseded the fixed-function pipeline that allowed only common geometry transformation and pixel-shading functions; with shaders, customized effects can be used.
Importing a new model into Unity is pretty sweet. You just sorta drag it in there. So: hexagons:
Very orderly. Let’s add a random rotation (jitter) and a semirandom purple hue to them:
And now, the piece de resistance: shaders. We made the prisms much taller, and added a glass sahder:
Note that not only are the pieces transparent, but the glass shader allows us to create reflections (clouds!) on the hex surfaces. This is the first time we’ve done this in the new Unity prototype, so we’re excited.
Okay, last tidbits, before we talk your ears off for an hour. Tunnels in two (2!) different ways. First, using arcs in a sort-of McDonalds color scheme:
- Create tall, narrow arcs and short, fat arcs.
- Go from the level’s top to bottom — every 2m, place an arc.
- Rotate that arc randomly around the vertical axis.
That looks like this:
As it happened, it looked neat from the side, but flying through it was disconcerting. Perhaps there wasn’t enough information for the eye to pick out how close each arc was to you? It looked like a fun but overwhelming blur of reds, oranges, yellows; we might solve this by giving them borders to make each one more individually visible.
Anyway, another type of tunnel was the “perturbed washer surface”:
The steps there were:
- Create a “washer” (a disc with hole in center).
- Subdivide the surface into small squares.
- Push the corners of those squares up or down so that the washer looked jagged.
That was all done within Maya, using our DING utility, and imported into Ugly Baby as one solid model.
There you have it!
Much of our July involved getting Unity set up to talk to the Python-based procedural content generator. For the first time, we now have something that (as far as level layout goes) is more capable than the original 3DGS-based Ugly baby. Next up: we’ll create many more of these foreground patterns, then fill them out with backgrounds that are visually interesting.
More to come.