Generating 2D map out of Simplex Noise

Hello,

Just registered. It might be that I’ve found a new home for my new hobby.

I’m toying around with Java’s AWT and Swing, and trying to generate a visual 2D map “for a game”.
I’m using SimplexNoise class to generate the numbers, from this step, seems like I can’t find much more information about what and how.
I understand that I need to convert my numbers to a Colors and apply them to the “map” I’m generating.

So I have this initialization:


SimplexNoise.genGrad(677);
		
int initX = 0, initY = 0;
int mapWidth = 1000, mapHeight = 700;

for (int i = initX; i < mapWidth + initX; i++) {
			for (int j = initY; j < mapHeight + initY; j++) {
				double res = 512;
				double tile = SimplexNoise.noise(i / res, j / res);
			}
		}

Which gives me numbers from -1 to 1.

I then proceed to create a blank Window:


public static void createWindow() {
		JFrame frame = new JFrame("MapGenerator");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(1000, 700);
		
		// make the frame half the height and width
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int height = screenSize.height;
		int width = screenSize.width;

		// center the jframe on screen
		frame.setLocationRelativeTo(null);
	
		frame.setVisible(true);
	}

And now I assume I need to use Graphics2D and draw every pixel on it by the color my numbers are related to and then somehow attach this element to the JFrame.

Am I right? I’m not asking for a “copy&paste” examples (but this is awesome as well), but at least a direction of what to do. What class to use, and which approach to apply to accomplish this task.

My desired output is something like:

Thanks a lot!

Firstly, if you are planning on making a game, maybe Java2D is not the most suitable choice. You can see my opinion on that here.

Regardless of the framework you choose, the concept is the same. You need to manipulate your noise values (-1.0 to 1.0) to colours. Java2D typically stores this in ARGB format, where each byte is in the range 0 - 255. More modern frameworks (built on OpenGL and hardware accelerated rendering) might expect RGBA format, using floats in the range 0.0 to 1.0.

For the sake of example, I’m going to assume you are using LibGDX. This will make your life easier, and the resulting code will be more to the point (no need for game loops, or buffer strategies, or any of that crap).

You can read about textures and pixmaps here – it introduces a lot of the essential concepts.
LibGDX Textures

LibGDX includes some utilities for handling pixmaps and color data, so your code might look like this:
http://www.java-gaming.org/?action=pastebin&id=553

You can do some pretty cool stuff with noise. If you plan on rendering it real-time (i.e. every frame), you might rather learn about shaders. Here is one I wrote a while ago that uses noise:
http://glsl.heroku.com/e#7662.3

If you want to use Java2D, then shaders won’t be possible. Instead, you’ll be forced to write the color data to an image yourself. The best way to grab the color data in ARGB format:

		//create a new buffered image, type ARGB
		image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		//grab the pixels array for modification
		pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

There are countless tutorials on the web explaining how to render a BufferedImage with Java2D.

Hi,

Thanks for the answer.

Now I think I should have spent more time explaining what I’m actually trying to do.

Basically, I’m not making a game using Java at all. Just using it to write a Map Generator and pre-generate a world.

The game is web based, no 3D graphics, similar to Travian I guess, just lacks the map.
I cannot generate it via PHP, as this is a very slow process and this language is not made for this calculations.

I just want, in the final result, to get a set of images that will represent the “world”. Images that will be a pieces of the world like this one:

http://www.watimbox.com/wp-content/uploads/2011/07/Travian_main-map.jpg

This is just one piece, I will need a lot of those. Currently, I want to generate a height/color map, to see which seed gives me the best results, then, instead of the color, I will apply my textures to the noise heights and it will give me a map.

But anyway, I will take a look at LibGDX and see if it can help me.

Thanks

In that case, Java2D would actually be a pretty good choice. Granted, you won’t have the luxury of Pixmap.drawPixel or Color.rgba8888, and you’ll have to pack/unpack the color data yourself into ARGB format.

Maybe simplex noise is not the best choice for this problem, though. It might be more suitable to just use a two-dimensional array and random values. That way, you can tweak the randomization… e.g. have trees appear 20% of the time, and rivers appear 30%, etc.

Tried my best to find any information about “packing/unpacking” color data or doing anything useful with Noise outputs.

I’ve managed to understand and write an app that draws points on JPanel using drawLine() method, but I still can’t get a reasonable conversion from noise numbers to any kind of a color code.
I don’t want to manually map colors to noise numbers, as I find it weird… right?

And what is the idea behind 2-dim array?

EDIT:
I’ve tried to map color table like that:


private static void putMap() {
		colors = new HashMap();
		colors.put(-5.0,Color.blue);
		colors.put(-4.0,Color.cyan);
		colors.put(-3.0,Color.red);
		colors.put(-2.0,Color.gray);
		colors.put(-1.0,Color.green);
		colors.put(0.0,Color.black);
		colors.put(1.0,Color.magenta);
		colors.put(2.0,Color.pink);
		colors.put(3.0,Color.orange);
		colors.put(4.0,Color.yellow);
		colors.put(5.0,Color.lightGray);
	}

And use it that way:


for (int i = initX; i < mapX + initX; i++) {
			for (int j = initY; j < mapY + initY; j++) {
				double res = 512;
				double tile = Math.round( (SimplexNoise.noise(i / res, j / res) * terrainTypes) / 2 );

				System.out.println(colors.get(tile));
				g2d.setColor( (Color) colors.get(tile) );
				g2d.drawLine(i, j, i, j);
			}
		}

Which produces something like:

Am I any close to my target? :slight_smile:

Sorry for annoying questions. I’m not lazy, I’m trying my best to do it solo, but seems like I need some pro help.

Thanks


// Member variables:
private BufferedImage noiseImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
// Or whatever size...
~~~~
// Method for getting color:
public Color computeColor(float value) {
    if (value < -4) return Color.blue;
    else if (value < -3) return Color.cyan;
    else if (value < -2) return Color.red;
    else if (value < -1) return Color.gray;
    else if (value < 0) return Color.green;
    else if (value < 1) return Color.black;
    else if (value < 2) return Color.magenta;
    else if (value < 3) return Color.pink;
    else if (value < 4) return Color.orange;
    else if (value < 5) return Color.yellow;
    else return Color.lightGray;
}
~~~~
// Setup method: (Called once at the beginning, ONCE)
for (int x = 0; x < noiseImage.getWidth(); x++) {
    for (int y = 0; y < noiseImage.getHeight(); y++) {
        double res = (noiseImage.getWidth() + noiseImage.getHeight()) / 2.0;
        double tile = (SimplexNoise.noise(x / res, y / res) * terrainTypes) / 2;

        noiseImage.setRGB(x, y, computeColor(tile).getRGB());
    }
}
~~~~
// Drawing method:
public void paintComponent(Graphics g) {
    g.drawImage(x, y, noiseImage, null);
}
// or, wherever you've got your Graphics2D object...:
g2d.drawImage(x, y, noiseImage, null);

How I’d do it.
But in the end this doesn’t really help you create something like in Travian. (Awesome game back in the old days, btw. Loved it. Was young…even younger)