Java-Gaming.org Hi !
 Featured games (90) games approved by the League of Dukes Games in Showcase (731) Games in Android Showcase (217) games submitted by our members Games in WIP (798) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
Pages: [1]
 ignore  |  Print
 2D terrain maps (for side-scrollers): how to modulate strata with Perlin Noise  (Read 62500 times) 0 Members and 2 Guests are viewing this topic.
philfrei
 « Posted 2015-06-11 21:01:41 »

Ken Perlin writes about using his noise function to modulate or perturb a given color on slide 20 of his talk "Making Noise", e.g., making the color lighter or darker or varying its hue. http://www.noisemachine.com/talk1/20.html When working on a 2D terrain map for a side-scroller, we can take this another step, and use the noise to modulate a strata set.

By strata, I am referring to a series of layers of various air and ground types. The basic layering function might be something like the following pseudo code function (for a board with a Y dimension of 24 blocks):

 1  2  3  4  5  6  7  8 `   getLayerType(int y) {        if y < 4 then return layer1        if y < 8 then return layer2        if y < 12 then return layer3        if y < 16 then return layer4         if y < 20 then return layer5        else return layer6    }`

Note that here, the strata depend entirely on the Y value. The X value does not matter.

The way in which you assign layer types can be calculated either bottom or top or the reverse, and at any level of granularity. In the following graphic, the dims are 500 x 300, and the layering uses the following logic:

blue > 240
green > 180
grey > 120
brown > 60
black > 0

The layers do not have to be of even thickness. For example, a thinner green layer might be a good way to suggest the ground's surface. The main point is that the basic layering, which you will use a starting point, should be something that is encapsulated in a function.

Now, you can modulate or perturb this function by adding a random component. Perlin Noise comes in various forms. I happen to like the Simplex Noise variant, but the "Improved Perlin Noise" is also a good choice. There are open source choices that can be found via search.

A 2D noise function usually takes the following form:
 1 `    noiseValue = getNoise( f(x), f(y) );`

I use the notation f(x) and f(y) instead of (x, y) for two reasons:

(1) we want the noise value to relate to the position in the board array or the graphic. In this, I'm taking x to range from 0 to the width of the board array or graphic, and y to range from 0 to the height.

(2) the exact int values used for the [x, y] inevitably have to be modified to give a desired periodicity to the perturbations. The most common modification is a simple scaling function, e.g., f(x) = x * k, but more complex functions are possible, such as equations to suggest the illusion of perspective.

When iterating through the grid of the game screen, or through the pixels of the graphic, the function that returns the  layer type consists of your basic layer function, with the Y value being altered by the noise value. Following is a pseudo code example:

 1  2  3  4 `    for each y        for each x            noiseVal = noiseFunction(x * k, y * k);            layerType = getLayerType( y + (noiseVal * modulationFactor) );`

The sharpness of the contours depends on how you scale and proportion things. Noise functions typically return values ranging from -1 to 1. This has to be scaled by some factor in order to give a return value range that works for your desired level of smoothness (modulationFactor). Too little can be too flat or boring, too much can create sharp edges or lead to pockets of layers appearing out of sequence, e.g., a cave of air, or worse, clouds of green. Unfortunately, there's no guarantee that a good middle ground exists via this method. Sometimes to get an acceptable result, another iteration is needed (e.g., make a second pass where you impose a rule that for any vertically adjacent points, the delta Y is always positive and always less than a certain maximum).

In the above, the k value is used to convert the series of integers that identify pixel or grid location into a range that relates to the 'period' of the random curve lengths. If the noise function returns a maximum of one full wave curve per one unit (this is usually the case, or something close), and you want up to 2 waves per screen (where the screen is 50 units wide), then the scaling factor should be 2 / 50, or, k = 0.04. Similarly, if you wanted an average of 3 complete waves over the course of 500 pixels, the scaling factor would be 3 / 500, or k = 0.006. Note: the k value does not have to be the same for the X and Y directions.

In the following graphic, I modulated the strata function with a moderate amount of noise. I don't have the exact amount because the tool I used to generate the graphic only gives relatives value relating to its sliders. By eye-balling, I'm going to estimate that the modulationFactor gives us a variability approximately equal to the width of a single layer (60 pixels), So, it should be equal to 30 in this case, giving us +/-30 when multiplied against the [-1, 1] range of the noise function output.

I hope the above explanation helps you to understand better understand how to use Perlin noise, and the concept of how to calculate the factors needed to scale both the periodicity and the strength of the noisiness.

One other note: you aren't restricted to making a single call to Perlin noise. Often, periodicities are combined by making multiple Noise function calls, each with a different K, with the results combined at various proportions. This technique too much to cover in this tutorial, but you can read Ken Perlin's description of a fractal example at the following location, slide 21 of his "Making Noise" presentation. http://www.noisemachine.com/talk1/21.html

The diagrams were made with SiVi (Simplex Visualizer) http://github.com/philfrei/SiVi

philfrei
 « Reply #1 - Posted 2015-06-11 21:59:16 »

How does one edit a tutorial post?

Riven

« JGO Overlord »

Medals: 1284
Projects: 4
Exp: 16 years

 « Reply #2 - Posted 2015-06-12 07:08:05 »

At the bottom of your pist you see the edit-icon.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Pages: [1]
 ignore  |  Print

You cannot reply to this message, because it is very, very old.

 Archive (335 views) 2017-04-27 17:45:51 buddyBro (533 views) 2017-04-05 03:38:00 CopyableCougar4 (975 views) 2017-03-24 15:39:42 theagentd (1011 views) 2017-03-24 15:32:08 Rule (991 views) 2017-03-19 12:43:22 Rule (972 views) 2017-03-19 12:42:17 Rule (968 views) 2017-03-19 12:36:21 theagentd (1068 views) 2017-03-16 05:07:07 theagentd (982 views) 2017-03-15 22:37:06 theagentd (758 views) 2017-03-15 22:32:18
 List of Learning Resourcesby elect2017-03-13 14:05:44List of Learning Resourcesby elect2017-03-13 14:04:45SF/X Librariesby philfrei2017-03-02 08:45:19SF/X Librariesby philfrei2017-03-02 08:44:05SF/X Librariesby SkyAphid2017-03-02 06:38:56SF/X Librariesby SkyAphid2017-03-02 06:38:32SF/X Librariesby SkyAphid2017-03-02 06:38:05SF/X Librariesby SkyAphid2017-03-02 06:37:51
 java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org