Friday, July 31, 2015

Coding Beauty: Part 2

Last time, I talked about the level and art design of Ori and the Blind Forest. I spoke of the two broad steps to creating its sumptuous platformer levels: first, design the basic platform layout; then texture it and add details to bring it to life. I've begun implementing the algorithm that will achieve step one of that process.

Here's what the results look like so far:



Not much, yet. Eventually, those red rectangles will be replaced with forest paths and trees and such. Even this little bit took quite a few iterations though. I started with a simple algorithm that placed platforms a random distance apart along a straight line. That algorithm also placed some upper-level platforms above the base level. It produced results like this:


It actually wasn't that bad - but it had a couple problems. First of all, it didn't look natural. Straight lines don't occur all that often in nature, and having all the platforms in straight lines on each height level didn't work so well. Although that problem could have been solved by clever texturing, the second issue did not have such an easy fix: the algorithm was unacceptably slow. An image like the one above took somewhere between 60 to 120 seconds to generate. Because I'm trying to generate these levels dynamically, while the player is in the game, I needed to cut that time way down.

So I scrapped the whole algorithm and started over. My original, inefficient algorithm included nested loops -- specifically, the algorithm iterated over every platform in every height level, and then iterated over ever pixel in every platform to draw them. In the new new algorithm, I needed a simple equation to determine where to place the platforms that didn't involve nested loops. To accomplish this, I turned to Perlin noise. Perlin noise is an algorithm that outputs smoothed, pseudo-random numbers. This means that, for a given sequence of inputs, the output will appear random, but the random values will not have any big leaps - helpful for creating a natural-looking environment. Furthermore, the same input will always produce the same output, which is useful in procedural generation because allows easy re-generation of a level. I used Unity's built-in Perlin noise function, although I may end up writing my own at some point for increased customization of the output. Using Perlin noise to determine where to place each platform gave me the result in the first picture - much more natural looking and also much faster (usually 2 to 5 seconds to generate). I'm not done with it yet, though. I still need to add functionality to generate upper-level platforms, and also a way to link the levels together smoothly.

After that, the next step is writing the script to dynamically generate these levels as the player moves through the world. Then, I will create a player input system that interacts smoothly with the level script, and then start adding in the art assets (that's a ways away - we're talking maybe in a few months, if I work fast).

There won't be any more blog posts for the next couple of weeks as I am going on vacation (to sail around the coast of MA!!). Once I get back, school is starting up again, so progress will be slow but hopefully steady. Stay tuned on Facebook and Twitter for updates until the next post.


A couple articles from Rock, Paper, Shotgun this week: first, an article about the level generation algorithms in retro rogue-like Brogue; second, a British police officer about the morally gray areas of law enforcement both in games and real life.

No comments:

Post a Comment