Monday, March 10, 2014

Mountain Climber Dev Log 03: Tetrahedral Rabbit Holes

So I decided to drop the mountain climbing theme. It's now about scaling a giant, Everlasting Gobstopper:

Okay, not really. That screenshot is the result of a spending some time down a programming rabbit hole. I ended up scrapping most of the work, but I figured I'd explain what I was going for and where I ended up.

A rabbit hole is an all-consuming task that derails your priorities. When you're down a rabbit hole, you tend to focus on the details of implementation and lose sight of the actual goal of the feature. 

My goal was to make the terrain feel less like a bunch of stairs that the player just hops up. I wanted the terrain to have longer, sloped surfaces that required the climbing pick to traverse. A secondary goal was to make the mountain look less like I lifted it straight out of Minecraft.

I started digging around on Wikipedia to find an alternative 3D shape to cubes that, a) was made of sloped surfaces, b) tessellated with no gaps, and c) fit on a regular grid, so my 3D array of voxel data was still applicable. I settled on a tetrahedral-octahedral honeycomb, which also happened to have an awesome name. I decided to horizontally bisect the octahedra into a pair of pyramids. That way, all the shapes would fit on a regular grid, and the downward facing pyramids would produce an occasional flat surface for the player to rest on. I was feeling pretty clever and excited to implement my solution. That's usually a rabbit hole red flag.

Eventually, after several sessions worth of trial and error, I got it working as I'd planned. You can see the various tessellating shapes in the screenshot above: red "upward" pyramids, orange "downward" pyramids, and green and blue tetrahedra. Unfortunately, you might also notice that it looks like a disjointed, fractal nightmare-scape. In theory, the honeycomb can produce nice, mountainous terrain under very specific patterns. In practice, it tends to produce lots of convex gaps and erratic spikes. I'd hit a dead end in the rabbit hole. 

At that point, I could have tried to finagle the nice, mountainous terrain I wanted from the shapes, perhaps using rules enforced on the voxel data that reduced the undesired arrangements. Instead, I poked my head out of the rabbit hole and reevaluated my goals. I really just wanted terrain geometry that was more fun to climb on and nicer to look at. I decided to go back to the cubic voxels and try deforming the vertices with a combination of Perlin noise, scaling, and a sin-function "bulge".

You can check out the results here in the current build. The terrain's still not perfect, but it's already more fun and visually interesting. More importantly, it was quick and easy to implement. I now also have a bunch of simple parameters I can tweak to produce further variation. I'd escaped the rabbit hole!

I should probably point out that rabbit holes aren't always bad. Yes, they're an inefficient use of time, but that might be fine if your project isn't on a schedule. If you're working on a hobby project that you're not in a rush to finish, rabbit holes can be very fun and satisfying. That's why they're so "treacherous" in the first place. I know several programmers who work on hobby projects primarily so they can spend as much time down rabbit holes as they please.

However, if you're concerned with keeping yourself on track, a good exercise is to periodically assess your goals. Is your current task in service to those goals? Is it taking longer than you'd expected? What's a faster, simpler alternative implementation?

My next goals are to add win and lose conditions to the game and further tweak the player movement and terrain. Hopefully I can hold myself to that!

No comments:

Post a Comment