Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  LWJGL: Procedurally Generated Simplex/Perlin Noise 2D world  (Read 1122 times)
0 Members and 1 Guest are viewing this topic.
Offline GamerIDGoesHere

Junior Member





« Posted 2014-02-05 09:09:54 »

Hi,

I am trying to create a procedurally generating world for a 2D platformer similar to the likes of Terraria or Starbound, but in Java/LWJGL

These are examples of what I am trying to achieve:
http://www.youtube.com/watch?v=SwHWhPaxbHA (Preferrably this one)
http://www.youtube.com/watch?v=tv7wFF97odI

I would like to know how I should best go about doing this as there seems to be pretty much nothing in the way of tutorials for 1d perlin noise procedural generation.

Thanks,
- Dan
Offline trollwarrior1
« Reply #1 - Posted 2014-02-05 09:29:24 »

I found this simplex noise generator somewhere online.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
public class SimplexNoise {  // Simplex noise in 2D, 3D and 4D

     public static int RANDOMSEED=0;
     private static int NUMBEROFSWAPS=400;  

     private static Grad grad3[] = {new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
                                    new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
                                    new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)};

     private static short p_supply[] = {151,160,137,91,90,15, //this contains all the numbers between 0 and 255, these are put in a random order depending upon the seed
    131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
     190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
     88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
     77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
     102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
     135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
     5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
     223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
     129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
     251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
     49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
     138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180};

     private short p[]=new short[p_supply.length];

     // To remove the need for index wrapping, double the permutation table length
    private short perm[] = new short[512];
     private short permMod12[] = new short[512];
     public SimplexNoise() {
     
       p=p_supply.clone();

       int seed = SimplexNoise.RANDOMSEED;
       
       if (seed==RANDOMSEED){
           Random rand=new Random();
           seed=rand.nextInt();
       }

       //the random for the swaps
      Random rand=new Random(seed);

       //the seed determines the swaps that occur between the default order and the order we're actually going to use
      for(int i=0;i<NUMBEROFSWAPS;i++){
           int swapFrom=rand.nextInt(p.length);
           int swapTo=rand.nextInt(p.length);

           short temp=p[swapFrom];
           p[swapFrom]=p[swapTo];
           p[swapTo]=temp;
       }


       for(int i=0; i<512; i++)
       {
         perm[i]=p[i & 255];
         permMod12[i] = (short)(perm[i] % 12);
       }
     }

     // Skewing and unskewing factors for 2, 3, and 4 dimensions
    private static final double F2 = 0.5*(Math.sqrt(3.0)-1.0);
     private static final double G2 = (3.0-Math.sqrt(3.0))/6.0;

     // This method is a *lot* faster than using (int)Math.floor(x)
    private static int fastfloor(double x) {
       int xi = (int)x;
       return x<xi ? xi-1 : xi;
     }

     private static double dot(Grad g, double x, double y) {
       return g.x*x + g.y*y; }


     // 2D simplex noise
    public float noise(float xin, float yin) {
       double n0, n1, n2; // Noise contributions from the three corners
      // Skew the input space to determine which simplex cell we're in
      double s = (xin+yin)*F2; // Hairy factor for 2D
      int i = fastfloor(xin+s);
       int j = fastfloor(yin+s);
       double t = (i+j)*G2;
       double X0 = i-t; // Unskew the cell origin back to (x,y) space
      double Y0 = j-t;
       double x0 = xin-X0; // The x,y distances from the cell origin
      double y0 = yin-Y0;
       // For the 2D case, the simplex shape is an equilateral triangle.
      // Determine which simplex we are in.
      int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
      if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
      else {i1=0; j1=1;}      // upper triangle, YX order: (0,0)->(0,1)->(1,1)
      // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
      // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
      // c = (3-sqrt(3))/6
      double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
      double y1 = y0 - j1 + G2;
       double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
      double y2 = y0 - 1.0 + 2.0 * G2;
       // Work out the hashed gradient indices of the three simplex corners
      int ii = i & 255;
       int jj = j & 255;
       int gi0 = permMod12[ii+perm[jj]];
       int gi1 = permMod12[ii+i1+perm[jj+j1]];
       int gi2 = permMod12[ii+1+perm[jj+1]];
       // Calculate the contribution from the three corners
      double t0 = 0.5 - x0*x0-y0*y0;
       if(t0<0) n0 = 0.0;
       else {
         t0 *= t0;
         n0 = t0 * t0 * dot(grad3[gi0], x0, y0);  // (x,y) of grad3 used for 2D gradient
      }
       double t1 = 0.5 - x1*x1-y1*y1;
       if(t1<0) n1 = 0.0;
       else {
         t1 *= t1;
         n1 = t1 * t1 * dot(grad3[gi1], x1, y1);
       }
       double t2 = 0.5 - x2*x2-y2*y2;
       if(t2<0) n2 = 0.0;
       else {
         t2 *= t2;
         n2 = t2 * t2 * dot(grad3[gi2], x2, y2);
       }
       // Add contributions from each corner to get the final noise value.
      // The result is scaled to return values in the interval [-1,1].
      return (float) (70.0 * (n0 + n1 + n2));
     }



     // Inner class to speed upp gradient computations
    // (array access is a lot slower than member access)
    private static class Grad
     {
       double x, y;

       Grad(double x, double y, double z)
       {
         this.x = x;
         this.y = y;
       }

     }

   }


I don't really think there is a point in trying to understand it, unless you really need to..
Offline GamerIDGoesHere

Junior Member





« Reply #2 - Posted 2014-02-05 09:41:22 »

Great thanks, do you have the link where you found that for reference?

Thanks
- Dan
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline trollwarrior1
« Reply #3 - Posted 2014-02-05 09:52:35 »

I found a good tutorial on perlin noise. It should be enough for a simple game :O If you're making 1d, 2d noise, perlin noise is plenty.

http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html

Uhm here is the full code for simplex noise.
I think..
http://webstaff.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java
Offline GamerIDGoesHere

Junior Member





« Reply #4 - Posted 2014-02-05 10:06:51 »

Hi just having a look at the code, thanks for helping,

Sorry, I'm a bit of a novice when it comes to world generation and perlin noise, how should I use the code, like draw it in a function for example?

Thanks,
- Dan
Offline trollwarrior1
« Reply #5 - Posted 2014-02-05 10:26:23 »

Noise cannot be generated every render cycle. Its too expensive. You can create an array of tiles, which would contain tiles with x,y coordinates. Now, you put those x,y tile coordinates into PerlinNoise.noise(double xin, double yin) method, and it will give you a height. You need to divide the x,y by some factor, because otherwise your tiles will look completely random. Simplex/Perlin noise basically interpolates data. You should just take a look at Perlin noise tutorial I put a link to. So, when you put in x,y coordinates, do something like .noise((float) x / 30, (float) y / 30). Now that you have a height from this method, you can use it to determine what kind of tile it should be. Lets say that height values from -1 to 0 will be dirt tiles, and tiles with height 0 to 1 will be grass tiles. You just check that height and put in the tile into your array of tiles.

After you made your tile array, you just render it.
Offline GamerIDGoesHere

Junior Member





« Reply #6 - Posted 2014-02-05 10:36:47 »

Right thanks, sorry to ask this, but could you give me a basic example of how I could do that?

Here is how I was drawing a basic line of tiles as an example:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
      // Draw the ground

      glBegin(GL_QUADS);

      glColor3d(0.6, 0.2, 0.1);
      glVertex2d(0, 0);
      glVertex2d(Display.getWidth(), 0);

      glVertex2d(Display.getWidth(), 32);
      glVertex2d(0, 32);

      glEnd();

      // Draw the grass

      glBegin(GL_QUADS);

      glColor3d(0.2, 0.8, 0.2);
      glVertex2d(0, 25);
      glVertex2d(Display.getWidth(), 25);

      glVertex2d(Display.getWidth(), 32);
      glVertex2d(0, 32);

      glEnd();


Thanks,
- Dan
Offline trollwarrior1
« Reply #7 - Posted 2014-02-05 10:38:46 »

http://pastebin.java-gaming.org/ad503871884

Here is the code..

You can adjust values such as:
* width, height, size, frequency to change the look of output Cheesy
Press R to recalculate tiles.

I assume you put your native path for LWJGL in your project already.
Offline GamerIDGoesHere

Junior Member





« Reply #8 - Posted 2014-02-05 11:07:11 »

Hi,
Thanks for that it seems to work well, however, it is top down and I need it to be for a sidescroller (like terraria)

How can I modify that code so that it works for that? or do you have a different way I could render it so that it is a sidescrolling map as opposed to top down?

Thanks so much for you help I really appreciate it!
- Dan
Offline trollwarrior1
« Reply #9 - Posted 2014-02-05 11:21:46 »

I changed makeTiles method only.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
   private void makeTiles() {

      tiles = new int[width * height];

      SimplexNoise noise = new SimplexNoise();

      int freq = 30;
     
      for(int x=0;x<width;x++) {
         float h = (noise.noise((float) x / freq, 0) + 1) / 2; // make noise 0 to 1
       
         for(int y=0;y<height;y++) {
            float current = (float) (height - y) / height;
           
            if(current > h) tiles[x+y*width]=2;
            else tiles[x+y*width]=1;
           
         }
      }

   }
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline GamerIDGoesHere

Junior Member





« Reply #10 - Posted 2014-02-05 21:22:53 »

Awesome thats pretty great, just a question, my background is now the green tile for some reason, and it should be this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
      // Draw the sky
     glBegin(GL_QUADS);

      glColor3d(0.7, 0.8, 0.9);
      glVertex2d(0, 0);
      glVertex2d(Display.getWidth(), 0);

      glColor3d(0.5, 0.6, 0.8);
      glVertex2d(Display.getWidth(), Display.getHeight());
      glVertex2d(0, Display.getHeight());

      glEnd();


so that should be the background and the grass should be just on the edge of the dirt

Thanks so much for your help,
- Dan
Offline GamerIDGoesHere

Junior Member





« Reply #11 - Posted 2014-02-06 08:40:27 »

Sorry to be annoying, but did you see the message about the sky and the grass not quite working properly?

Thanks,
- Dan
Offline trollwarrior1
« Reply #12 - Posted 2014-02-06 11:27:56 »

Lol i don't think you're annoying to anyone.

Its just I don't think you realize that you don't understand a thing in my code, because you're asking such simple question. I can make the whole game for you if you want, if you pay me of course Cheesy

This isn't the place to ask to make games. This is a place to discuss / ask for help. And the help should be technical, such as "How can I change opengl rendering color?" or "how can I render a quad using opengl?" although you should first try to google such question, and if you can't find the answers, then post a question here! Smiley

You should try to make your own games / implementations. If you can't generate terraria looking terrain, then its not the time to do it yet.

I mean, your first question was how to generate terrain from perlin / simplex noise and I answered that question Smiley
If your background is green, you need to change the color of the tile that is being rendered in the "back ground". So when you render background tile, you could try rendering it with color 1f, 1f, 1f.
Offline GamerIDGoesHere

Junior Member





« Reply #13 - Posted 2014-02-06 11:29:26 »

Right yes sorry nevermind, I do understand most of the code, but am still wrapping my head around LWJGL.

Thanks so much mate,
- Dan
Pages: [1]
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

E.R. Fleming (20 views)
2014-07-29 03:07:13

E.R. Fleming (7 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (50 views)
2014-07-17 23:47:54

danieldean (42 views)
2014-07-17 23:41:23

MustardPeter (45 views)
2014-07-16 23:30:00
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!