Sign in to follow this  
slicer4ever

Generating a minimap

Recommended Posts

so, i'm working on a minimap for an rts right now, and it's coming along alright. right now i want to generate the background geometry for the minimap, but i'm unsure how to create a good quality background image.

at the moment when i start a game i generate a texture that is the same size as my world map(in this case 256x256) i then go through each tile and check what image they are using to be drawn as, and take the center pixel and draw this to my minimap.

this produces this result:

9tTDDay.png

which is relatively bland. some ideas are to sample the surrounds pixels from the center to get an average color, or even sampling random pixels in the texture for the minimap to draw from, but i think both of these aren't going to solve my issue.

any suggestions on what i can do to improve it

Share this post


Link to post
Share on other sites
Hi.
Just render the whole terrain to a render target and use it as mini map.
Place camera looking down on the map at some hight above the terrain.

Share this post


Link to post
Share on other sites

One idea might be to associate each tile type with an image of the same size as the minimap view--pixellated grass for grass tiles, low-resolution foliage for trees, etc.--and then, for each minimap pixel, examine the corresponding tile and by the aforementioned association pick the appropriate image and draw the respective pixel from it. The result should be that you see the grass image where there is grass, the foliage image where there are trees, and so on.

 

In rough psuedocode:

for minimapPixelX:
    for minimapPixelY:
        id = getTileIDForMinimapPixel(minimapPixelX, minimapPixelY)
        if id == ID_GRASS:
            pixel = grassImage.getPixel(minimapPixelX, minimapPixelY)
        if id == ID_TREES:
            pixel = forestImage.getPixel(minimapPixelX, minimapPixelY)
        # And so on for further IDs...
        minimapSurface.setPixel(minimapPixelX, minimapPixelY, pixel)

Share this post


Link to post
Share on other sites

You could try smoothing/blurring it to get rid of some of the blocky-ness, then just use a somewhat-transparent textured overlay to add some interesting features to the minimap. Also, if you first distort the minimap (e.g. subtle non-uniform horizontal or vertical waves), it may (or may not) look less blocky and more natural.

 

Using the average colour around the centre will give the same colour for every tile of a particular type (which is what you have atm), and random selection will give you a random-looking result (you could try smoothing or a median filter after to reduce the range of values, though this may not be so good either).

Share this post


Link to post
Share on other sites

Howdy.

 This is how my minimap looks I Take the image in the map editor and save it as a .dds file so Im not allways rendering my terrain in game.

 

MiniMap.jpg?psid=1

Share this post


Link to post
Share on other sites

Howdy.
 This is how my minimap looks I Take the image in the map editor and save it as a .dds file so Im not allways rendering my terrain in game.
 
MiniMap.jpg?psid=1


can i get a technical answer to what you do? i'm looking to do something similar, but am still working on it.
edit: nvm i didn't realize you were the one that posted above.

i did the random seletion from the texture, and actually get an ok result:
huG5i3g.jpg

however if i place the camera high up, and take a snapshot of the ground, this is what i can expect to get:

A3VilZM.jpg

which kinda looks similar to the random sampling i did, obviously the geometry in the game isn't that appealing at the moment either, so perhaps i should work on that before i worry about getting the minimap looking good. Edited by slicer4ever

Share this post


Link to post
Share on other sites

Hmm, I was able to get a minimap for my terrain system up and running in about 30 minutes. Here is a screenshot sample:
[attachment=23610:minimap.jpg]


These are my design requirements:
1. The minimap dimensions may be any size. There's no relationship to the actual terrain system. The terrain could be 512x512, 1024x1024, 128x768, etc. The minimap is going to be something like 256x256.

2. I want to have height information color coded into the minimap, with contour lines to give it more of a "map" look. You should be able to tell what the elevation is.

 

 

This was my approach:

1. We get a width/height for the minimap from the user and we return a Texture2D to them.

2. We're going to go through each pixel in the minimap and map it to a position on the terrain.

2a: Since the terrain and minimap dimensions are independent, I am going to want to normalize my sample point.

 

For example, if my minimap is 256x256 and my terrain is 512x1024 (arbitrary size), and I am sampling the pixel (50,60) on the minimap, the normalized position is going to be:
normX = 50 / 256;
normY = 60 / 256;


Then, we sample the height map or terrain system by taking the normalized coordinate and switching it into their coordinate space...

sampleX = normX * terrainWidth;
sampleY = normY * terrainHeight;

 

And then we sample the terrain with these coordinates.
You would only super-sample neighboring pixels if the size of the minimap is greater than the size of the terrain (but why would you ever do that?!).
I figure you can just say that a map is a rough sketch of what the terrain actually looks like. If the spacing between sample points skips a few data points on the terrain, who cares? Can the player tell the difference? Nope! So don't over-engineer it.


Anyways, here is my implementation code which generated the minimap above:
 

public Texture2D GenerateMinimap(int width, int height)
{
	Texture2D ret = new Texture2D(BaseSettings.Graphics, width, height);
	Color[] data = new Color[width * height];

	float maxElevation = m_settings.MaxElevation;

	float t0 = 0;                           //sand height
	float t1 = maxElevation / 4.0f;           //grass height
	float t2 = t1 * 2;    //granite height
	float t3 = t1 * 3;    //snow height

	Color sand = new Color(255, 128, 0);
	Color dirt = new Color(128, 64, 0);
	Color grass = new Color(0, 192, 0);
	Color granite = new Color(192, 192, 192);
	Color snow = new Color(240, 240, 240);

	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			float h = m_heightMap.SampleTexel(x, y);
			Color c;

			if (h % 32 == 0)
				c = new Color(0, 0, 0);
			else
			{
				if (h < t1)
				{
					//should lerp colors
					float f = h / t1;
					c = Color.Lerp(sand, dirt, f);
				}
				else if (h >= t1 && h < t2)
				{
					float f = (h - t1) / (t2 - t1);
					c = Color.Lerp(dirt, grass, f);
				}
				else if (h >= t2 && h < t3)
				{
					float f = (h - t2) / (t3 - t2);
					c = Color.Lerp(grass, granite, f);
				}
				else
				{
					float f = (h - t3) / (maxElevation - t3);
					c = Color.Lerp(granite, snow, f);
				}
			}

			data[y * height + x] = c;
		}
	}

	ret.SetData<Color>(data);
	return ret;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this