Perlin Noise Plugin

This forum is currently in read-only mode.
0 favourites
From the Asset Store
Sound effects of monsters, ghosts, beasts and more
  • I have released my Perlin Noise Plugin. I still have a bit of testing to do, and of course, I'll want you guys to report any bugs you find in this thread. I'm going to use this first post as a tutorial on how to use this object, and to explain what it can do for you.

    Please keep in mind this is a beta, I want to see how far you guys can push this thing, and how hard you can break it. When you do, tell me how you did so here.

    DOWNLOAD LINK

    Introduction

    So what is Perlin Noise? Well, in 1985, Ken Perlin came up with an algorithm for noise that wasn't quite so random. It had smooth transitions, and to this day that algorithm is used to generate everything from cloud textures, to detail maps on "dirty" textures, and more importantly - to generate terrain. If you use the values given by this algorithm in a grid, you can create random, persistent terrain. The algorithm is pseudo-random, and uses a seed. If you feed it the same seed, you will get the same noise out of it, which means you can generate as much noise as you need, on the fly, and if you generate it again, it will be the same as it was, without actually storing all the noise into a gigantic texture. I'm going to be using this for generating as much terrain as I need on the fly in my game, and terrain will be the focus of this tutorial, but please keep in mind that there are many applications for Perlin Noise outside of terrain.

    Tutorial

    Alright, first of all you are going to want to open the zip file you downloaded, inside you will see a folder called "Runtime", and another plugin: "PerlinNoise.csx". You are going to want to drag the contents of this zip file into your Scirra\Construct\Plugins folder. If any warnings pop up, just ignore them and continue extracting.

    Now fire up Construct, and double click inside the layout to drop a new object on it. Once the dialog pops up, you should see the Perlin Noise object inside. It looks like this:

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/b31604d6-d811-44a2-8974-81d5b305393a/TheObject.png">

    Drop one of those into the layout, and select it. You will notice that it has many properties on the left. Among these are "Width", "Height", "Octaves", "Frequency", "Amplitude", and "Seed". I will briefly explain each one of these settings for you.

    Width and Height are the size of the object, but you will notice that there is not actually a physical object on the layout. That is because the noise is generated at runtime, and acts more like an array than a sprite. The size of the object is arbitrarily chosen by you, but for now let's keep it at 640x480, which by the way should be the same size of your layout and application window. This will make it easier to fill the layout with noise. If you had to generate noise on a smaller scale, say for a sprite, you might want to change these values.

    Octaves are basically how many passes the Perlin algorithm makes, the less octaves you use, the cloudier the noise will look, and the more you use, the grainier it will look. For most purposes, a value of 4 to 8 is fine. For our terrain, we will keep it at 4.

    Frequency is similar to the frequency of sound. If you look at a frequency wave, a higher pitched sound has the waves closer together. In our noise, the higher the frequency, the tighter the noise is going to get - there will be less whitespace and more activity. Values between 1 and 8 are fine as frequencies, and we will be using 4 for our terrain.

    Amplitude is a bit easier to understand. It is simply how high and how low the noise will go. The noise at any given position on the grid is a decimal value between negative amplitude and positive amplitude. So if your amplitude is 4, you will get values between -4 and 4.

    Seed is the unique identifier for the noise you are generating. If you change this, the noise will change to represent the new seed. If you go back to the original seed, the noise will return to how it was.

    Alright, now create a new sprite on your layout, size 32x32, and name it Tile. Color it white, and make sure it's hotspot is centered. Now position it at position 16,16, so it is in the top left corner of the layout. Right click on the tile, and choose "Array Paste". Click on the 2D option, set the 1D field to 15, and the 2D field to 20. Now set the X Row Offset to 32, and the Y Move Transformation to 32. It should look like this:

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/ec8cf95f-88bd-4dd6-8391-3ac207504d54/Array_Paste.png">

    Hit OK. You should have just filled the entire layout with white tiles, now right click the Tile object in the object list, send it to the back of the order list, and lock selection so it won't be in our way.

    Now create a button named GenButton, and set it's caption to "Generate". We're now ready to generate some terrain, but first we need to set up the event sheet.

    Alright, now add a condition for clicking the button, and a subcondition of that that: "For Every Object", choose the Tiles as the object. Now here's the easy part. Create two more subconditions using the Perlin Noise object "Compare Noise At", set the X and Y values of both to Tile.X and Tile.Y, and the value to 0, but make one of the conditions "Less than" and the other "Greater or equal to". What we are doing right now is checking the position of each tile against the noise map that is covering the whole layer invisibly. We are taking the value of the noise at that point, and checking to see if it is below our artificial "Water Line", which is 0. You should currently have an event sheet that looks like this:

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/e3259c7e-7c3c-4443-ac71-6c2e2b21a028/EventSheet.png">

    Lastly, we want to color everything in. On the condition that says the noise is below 0, set an action to colorize the tile object as a blueish color. On the other one, do it again as a greenish color. Now the tile map can easily be rendered, but we have to do one last thing before the program is done. We want to see how random this Perlin object is, so go back up to the condition where GenButton is clicked, and on that level, add an action for the Perlin generator: SetSeed. For the value, choose Random(2000). This way, our perlin map will be updated every single time that button is clicked. This is how your final event sheet should look:

    <img src="http://content.screencast.com/users/Arsonide/folders/Jing/media/b7bc8e7f-7123-4333-97e0-930119bb00ba/FinalSheet.png">

    Now hit that preview button! You should end up with something like this: http://screencast.com/t/T6D9oR19 Keep in mind that the blockiness is caused by the size of our tiles, the noise map is MUCH more detailed than that. It looks a little like this:

    <img src="http://infohost.nmt.edu/~imcgarve/perlin_noise/perlin_noise2.jpg">

    You could make the tiles 16x16 instead for a more detailed map, and instead of checking if it was above and below zero, to check if it was BETWEEN certain values using that action to create layers for darker blues in the deep ocean, lighter blues near the shoreline, yellow sand along the shore, green hills and dark green forests in the center of the mainland. If you changed the amplitude from 1 to 10, you'd have a lot more room to add more of these layers in. The amount of detail you can generate is limited only by your creativity.

    Do keep in mind that you don't want to use 16x16 tiles in a real game, that's why I didn't do it here in this tutorial. That many sprites at once would start to choke up Construct. Keep in mind that here we were generating the entire world, but your player isn't always going to see the entire world. You only need to show what is in his field of vision, so he's going to be looking at a small portion of the map at any given time. However, the noise map adds a lot of realism to the terrain that wouldn't be possible otherwise.

    Conclusion

    You will find that there are enough actions, conditions, and expressions in the plugin to do whatever you need to do.

    I have a few names to drop in here at the end. I have to thank Ken Perlin for his algorithm, you will notice the default seed for a Perlin object is 1985, homage to when he made the algorithm. Secondly I have to thank John Ratcliff, as he came up with this implementation of Perlin Noise, and I am simply porting it to Construct. Lastly, I have to thank my buddy Alex for cranking out a little TV with static on it at 4AM in the morning for my stupid project.

    I will be releasing the plugin very soon. You can use the plugin for whatever you want to use it for. It is my first plugin ever, so PLEASE report any inconsistencies or bugs you might encounter. And please, be on the lookout for my future projects. Anything that comes out of me will involve randomizing or procedurally generating something...

  • Just when you don't expect it there comes another awesome plugin. Can't wait to try it out Arsonide!

  • I'd like to point out the awesomeness.

    That'll be all.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Sounds great. Can't wait to give it a whirl.

  • Plugin download link is active at the top of the first post. I haven't noticed any glaring bugs myself, but you guys will find some. Remember to post them here when you do, so I can make it better.

    Other than that I can't wait to see what you do with it.

  • If rendering is a problem, you could always consider text mode.

    Uploaded a limited example here.

  • So the noise will always have the absolute coords of the layout, starting at x=0, y=0?

  • So the noise will always have the absolute coords of the layout, starting at x=0, y=0?

    The width and the height of the noise object are arbitrary. They can be any number you choose, but if you set the width and height of the noise object to the width and height of your layout, then yes...that would be the case. I did it that way so that people could use it for other purposes, I'm sure someone could come up with a use for a noise map that's smaller than the size of the layout.

  • Ok, just wanted to make sure as a sprite distort map's coords are only relevant to the sprite.

    So setting a vertex z height will only work as long as the sprite lines up with the noise.

  • The noise has no position, so it can't "line up". Remember, it's not a physical object like a Sprite. It is more like an Array, except this array can stretch to any size you need it to, since it calculates based on percentages rather than absolutes. If you took a 640x480 noise map and condensed it down to 4x4, it'd still be the same noise map, squished down into 4x4 pixels. You'd lose a lot of detail obviously, but the calculations would be the same because the seed was the same. The size is irrelevant to what comes out of the noise map - it gives it more detail at higher resolutions, that's all. I could just as easily make the noisemap 20x15 - one for each tile, and it would look exactly the same...but keeping it big like this would let you stretch the world out to bigger proportions than one screen without losing detail.

    Don't think of the resolution of the noise map in "pixels", rather they are entries of an array that is spread over a constant noise map based on the seed it was given. Higher resolution and you get more detail because there are more entries. Think of it this way. The noise map is a nice beautiful picture, but the picture is under a floor made of glass tiles that distort it. These glass tiles represent the width and height of the noise map. If there are more glass tiles in the floor, you see more detail in the picture underneath. If there are less tiles, or if the resolution of the noise map is lower, you don't see as much detail, but the picture is still the same.

    When you reference X and Y coordinates in my conditions, you are referencing the coordinates of the noise map, not the layout. Perhaps I should reword the conditions to make that more clear. It is, however, much easier to think about, when the layout and the noise map are the same size, because those coordinates line up.

    If you made the noise the same width and height of the Sprite, and paired them together, it should work. I'd be able to explain it better if I knew exactly what you were trying to do.

  • Absolute ace plugin man. I have a lot of potential uses for this.

  • Ok I see.

    http://dl.getdropbox.com/u/666516/perlinzheight.cap

    Now where's that Mr Burns gif at... oh here it is.

    <img src="http://dl.getdropbox.com/u/666516/mr_burns.gif">

  • VERY nice. That's definitely something I wasn't expecting.

    I duplicated the Sprite as another sprite and bumpmapped it with the light set at the mouse's position, a black background, and Multiply Plus on the water. Nearly looked like something out of a fairly modern 3D game.

  • Dude, we absolutely need lighting to go with that! Rising/setting sun, shadows etc.

  • Once that transparency bug is fixed we should be able to do all of that.

    Plus I'll have semi-transparent animated water, and fairly realistic fog.

    Hmmm, guess I could probably do some interpolation between two different seeds as well.

    Oh yeah there's more, much more you can do with this. Imagine grass applied to plains, snow applied to peaks.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)