The large map is rendered on the scale of pixel = tile.
It is very true that fractal landscapes have scaling difficulties; this is because real landscapes are not uniform fractals. That is, mountains, hills, plains, and coastlines all form via different processes. No one equation can cover all of these. What I've done with mine is used several different "fractals" (well, actually one crude fractal that is distorted differently several times) and blended them together; Coastlines are defined by one pattern, forests by annother, swamps by a third. It is also possible to have one pattern influence annother, such as having places close to shore be more likely to become swamps, or conceivably have areas far from swamps potentially become dry dirt. I could even have forests cause landscapes to raise up.
Luckily for us, the current tile system actually does a good job of hiding artifacts; even the crude current map looks kind of good from in-game.
Take a look at the large map and zoom in to see what the in-game map would be like; each pixel is one tile.
-
Vattic
- Posts: 232
- Joined: Sat May 30, 2009 1:47 am
- Location: United Kingdom
Re: World Gen
If that is the case then I would love to see one of your maps rendered by the games engine and then posted up here
.
-
Peter
- Posts: 1491
- Joined: Thu Jun 04, 2009 3:36 am
Re: World Gen
I'd like to see that myself, but I don't have the knowledge here. I would like to know how map information is saved, and then I might be able to make a more importable map format. Of course, the generator it'self could be built into the server, which would allow live map growth, and allow the server to "forget" old areas and regenerate them exactly as they where before!
A small area 1px=1tile (roughly):

Latest worldish map:

Now, to demonstrate the scale of this map:







Now, the remarkable thing is each and every inch of even the largest map can be generated on the fly, and with perfect accuracy. Of course, over very large scales the world becomes homogeneous, but it is possible to change the generator slightly to add annother layer of complexity that can resolve even that.
A small area 1px=1tile (roughly):

Latest worldish map:

Now, to demonstrate the scale of this map:







Now, the remarkable thing is each and every inch of even the largest map can be generated on the fly, and with perfect accuracy. Of course, over very large scales the world becomes homogeneous, but it is possible to change the generator slightly to add annother layer of complexity that can resolve even that.
Surprise.
-
theTrav
- Posts: 3464
- Joined: Fri May 29, 2009 11:25 pm
Re: World Gen
There's a video? I can't see it.
I also didn't realize how the procedurally generated bit worked, that's pretty neat. Are you a programmer? If not I might try to bang up something that just plonks down H&H tiles based on those image files just to see how it goes.
As for the "recognising areas / forests" I still reckon the game should assign forest tiles based on the density of trees in the area rather than have pre-determined forests. The map gen should only be able to specify areas where trees find it very difficult to grow (desert, swamp, maybe steppe & mountain if they do that).
I also didn't realize how the procedurally generated bit worked, that's pretty neat. Are you a programmer? If not I might try to bang up something that just plonks down H&H tiles based on those image files just to see how it goes.
As for the "recognising areas / forests" I still reckon the game should assign forest tiles based on the density of trees in the area rather than have pre-determined forests. The map gen should only be able to specify areas where trees find it very difficult to grow (desert, swamp, maybe steppe & mountain if they do that).
-
Peter
- Posts: 1491
- Joined: Thu Jun 04, 2009 3:36 am
Re: World Gen
If you are familiar with DF terms, I am a dabbling Programmer.
There's a link to the video on the first page. I have a colossal 30 second clip that I'll try to downconvert to something portable, but take a look at the earlier clip to see some of the stuff you can do with some parameters.
I'd be glad to share what I've got.
The key thing is the noise generator- a random heightmap or fractal that- and this is key- has consistent slopes. This is opposed to a really noisy heightmap where each pixel has a random value with no connection to adjacent ones. That is:

(Note that red is extreme highs, blue extreme lows, Greens for elevation lines.
Then, you scale it down, shift it and add it to original pattern so that the larger noise has finer details from the smaller noise. This process can be repeated several times so as to have many levels of detail. In my map I have two levels for most terrain features.
Then we can simply create a slightly different grayscale for each terrain type, then cause interactions between terrains (for instance, add 0.2 to swamp when elevation is at 0 and subtract 0.2 from it at elevation at 1). Once you have the final grayscale map, at any point that is higher than X, make it 1, else 0. The effect is that you'll have this nice, organic looking terrain borders like I have above. Some terrain might need more detail (for instance, the high-contrast change from water to land means that there should be one or two extra layers for it on the greyscale. X can be selectable, and small changes can cause more or less of the relevant terrain to be present. Finally layer each terrain pattern on top of each other and there's your map.
Now, for a better system, you could compare all maps at each point and select what is most intense at any point rather than just culling, but I don't know how that would look for you.
Here's the "source code", as it's built in art of illusion, so it's not getting out of there.

Trust me, that's actually pretty good for what we're working with.
Oh, there's one more thing that I've discovered, and that is that real terrain has a non-linear, non-sine distribution- that is, most terrain is slightly above or below water, with exponentially less terrain at higher elevations. I figured out that if you're starting with a noise patten that's linear, like the one I have at the top of this post, that you just need to decrease the prevalence of extreme values and increase common ones, something like an inverted sine curve. for the actual data (which isn't all that useful, but interesting nonetheless).
Heh, I didn't realize it, but I invented procedural brownian motion...
There's a link to the video on the first page. I have a colossal 30 second clip that I'll try to downconvert to something portable, but take a look at the earlier clip to see some of the stuff you can do with some parameters.
I'd be glad to share what I've got.
The key thing is the noise generator- a random heightmap or fractal that- and this is key- has consistent slopes. This is opposed to a really noisy heightmap where each pixel has a random value with no connection to adjacent ones. That is:

(Note that red is extreme highs, blue extreme lows, Greens for elevation lines.
Then, you scale it down, shift it and add it to original pattern so that the larger noise has finer details from the smaller noise. This process can be repeated several times so as to have many levels of detail. In my map I have two levels for most terrain features.
Then we can simply create a slightly different grayscale for each terrain type, then cause interactions between terrains (for instance, add 0.2 to swamp when elevation is at 0 and subtract 0.2 from it at elevation at 1). Once you have the final grayscale map, at any point that is higher than X, make it 1, else 0. The effect is that you'll have this nice, organic looking terrain borders like I have above. Some terrain might need more detail (for instance, the high-contrast change from water to land means that there should be one or two extra layers for it on the greyscale. X can be selectable, and small changes can cause more or less of the relevant terrain to be present. Finally layer each terrain pattern on top of each other and there's your map.
Now, for a better system, you could compare all maps at each point and select what is most intense at any point rather than just culling, but I don't know how that would look for you.
Here's the "source code", as it's built in art of illusion, so it's not getting out of there.

Trust me, that's actually pretty good for what we're working with.
Oh, there's one more thing that I've discovered, and that is that real terrain has a non-linear, non-sine distribution- that is, most terrain is slightly above or below water, with exponentially less terrain at higher elevations. I figured out that if you're starting with a noise patten that's linear, like the one I have at the top of this post, that you just need to decrease the prevalence of extreme values and increase common ones, something like an inverted sine curve. for the actual data (which isn't all that useful, but interesting nonetheless).
Heh, I didn't realize it, but I invented procedural brownian motion...
Surprise.
-
Peter
- Posts: 1491
- Joined: Thu Jun 04, 2009 3:36 am
World Gen: Now with CODE!
Code: Select all
//Peter Cymbalski; Nowhere Publishing Browninan Layer Map Generator v0.05
#include <iostream>
using namespace std;
//The Index:
float fractalMap(int,int,int);
int mapLayer(float,float,float,float,float);
void textout(int);
float floatcap(float);
int main()
{
cout << "NWP BLMG (c) Peter Cymbalski\nPlease enter the X co-ord.\n";
int iXin;
cin >> iXin;
cout << "Please enter the Y co-ord.\n";
int iYin;
cin >> iYin;
float fFracElvtn = fractalMap(iXin, iYin, 1);
float fFracSwamp = fractalMap(iXin, iYin, 2);
float fFracSand = fractalMap(iXin, iYin, 3);
float fFracForst = fractalMap(iXin, iYin, 4);
float fFracClay = fractalMap(iXin, iYin, 5);
return(0);
}
float fractalMap(int mapX, int mapY, int mapOffset) //mapX and mapY refer to the xy coords of the tile in the world. "Browninan" refers to Fractoral Browninan Motion, the basis for this generator.
{
//Offest adjustments:
mapX = mapX+(mapOffset*100);
mapY = mapY+(mapOffset*100); //*100 so that small values for mapOffset radically change the part of the noise we're looking at
//Generator fine-tuning: Universal for all layers, an improved but bulkier version may add these as variables
float fScaleLevelA = 1; //Defines the scale of the top layer of each Noise map
float fIntenseLevelA = 1; //Defines the intensity of the top layer of each Noise map
float fNLevelB = 2; //As above, for next layer intensity and scale.
float fIntenseLevelB = 0.5;
float fNLevelC = 4;
float fIntenseLevelC = 0.25;
float fLA = 0, fLB = 0, fLC = 0;
float fTotalHeight = 0;
//Combines, or "draws" the map layers and scales them:
fLA = ((Noise(mapX*fScaleLevelA),(mapY*fScaleLevelA))*fIntenseLevelA); //Draws and modifies layer A
fLB = (((Noise(mapX*fScaleLevelB),(mapY*fScaleLevelB))*fIntenseLevelB)-(0.5*fIntenseLevelB)); //Draws and modifies layer B, Displaces it for next step
fLC = (((Noise(mapX*fScaleLevelC),(mapY*fScaleLevelC))*fIntenseLevelC)-(0.5*fIntenseLevelC)); //Deaws and modifies layer C, Displaces it for next step
fTotalHeight = fLA+fLB+fLC;
fTotalHeight = floatcap(fTotalHeight);
return(fTotalHeight);
}
int mapLayer( float fElevation, float fSwamp, float fSand, float fForest, float fClay)
//BIG NOTE HERE: Replace magic numbers with variables that allow map customization, eventually
{
//subsection: transform terrain due to others. Lots of magic numbers here, but kind of unavoidable. These numbers should come from a config file, really.
float fElevSea = (fElevation-0.5); //Height above sea level.
if (fElevSea < 0) fElevSea = 0;
fElevSea = floatcap(fElevSea * 2);
fSwamp = floatcap(fSwamp-((0.4*fElevSea)-0.2));
fSand = floatcap(fSand-((1*fElevSea)-0.95));
fForest = floatcap(fForest-((0.1*fElevSea)-0.05));
fClay = floatcap(fClay+((0.4*fElevSea)-0.2));
//subsection: select tile.
int iTileOut = 0;
//Threshold variables. Magic Numbers good for changing later.
float fThElev = 0.5;
float fThSwmp = 0.5;
float fThSand = 0.5;
float fThFrst = 0.5;
float fThClay = 0.5;
if (fClay > fThClay) iTileOut = 5;
if (fForest > fThFrst) iTileOut = 4;
if (fSand > fThSand) iTileOut = 3;
if (fSwamp > fThSwmp) iTileOut = 2;
if (fElevation < fThElev) iTileOut = 1; //supposed to be reversed; if it's less than a value, it's under water!
return(iTileOut);
}
void textout(int iTerrainout)
{
if (iTerrainout = 0) cout << "Tile is grass.\n";
if (iTerrainout = 1) cout << "Tile is water.\n";
if (iTerrainout = 2) cout << "Tile is swamp.\n";
if (iTerrainout = 3) cout << "Tile is sand.\n";
if (iTerrainout = 4) cout << "Tile is forest.\n";
if (iTerrainout = 5) cout << "Tile is clay.\n";
return();
}
float floatcap(float x)
{
if (x < 0) (x = 0);
if (x > 1) (x = 1);
return(x);
}
The goal would be to have a function you could simply call with X and Y coords, and have that return from 0-5 with the tile type.
I think my buddy can transpile this from C++ to Java. What's your server based on?
Now, the way you might use this is that every time someone gets near the current map edge, the server generates a 100x100 area, spawns trees, rocks, and rivers as appropriate for the underlying terrain, and sticks this onto the map. You can even unload and entirely forget areas that haven't been visited in x hours and regenerate them later exactly the same (admittedly loosing things like constructions.
Surprise.
-
jorb
- Posts: 18715
- Joined: Fri Apr 03, 2009 7:07 am
- Location: Here, there and everywhere.
Re: World Gen
@ Peter: Very impressive.
"The psychological trials of dwellers in the last times will be equal to the physical trials of the martyrs. In order to face these trials we must be living in a different world."
-- Hieromonk Seraphim Rose
-- Hieromonk Seraphim Rose
-
Peter
- Posts: 1491
- Joined: Thu Jun 04, 2009 3:36 am
Re: World Gen
I saw your new sticky comment, and I understand what you mean. I'll probably continue working on this because I like the concept, but if you aren't interested I'll stop posting it here.
The code I posted up there is non-functional, but just to be on the safe side, I want to say that I relinquish any rights to the code sample I provided, blablabla, I can't sue you just because I think you have used that particular code, even if you should decide to profit from it.
This does not include any derivations of that code that I might make at a future date, and should you like to work with me in the future, I'd be glad to discuss a more formal agreement.
So, to summarize this whole thread:
"Consider generating world maps using Perlin or Simplex noise as a basis of Fractal Brownian Motion to generate terrain procedurally, as this would allow expandable and consistent maps."
P.S.: There is a way to use such fractals to make tiling or looping areas- thus, you could conceivably make a cylindrical world (impassible or infinite to the north, e-w passage), a toroidal world, or even a spherical world... somebody mentions something...
The code I posted up there is non-functional, but just to be on the safe side, I want to say that I relinquish any rights to the code sample I provided, blablabla, I can't sue you just because I think you have used that particular code, even if you should decide to profit from it.
This does not include any derivations of that code that I might make at a future date, and should you like to work with me in the future, I'd be glad to discuss a more formal agreement.
So, to summarize this whole thread:
"Consider generating world maps using Perlin or Simplex noise as a basis of Fractal Brownian Motion to generate terrain procedurally, as this would allow expandable and consistent maps."
P.S.: There is a way to use such fractals to make tiling or looping areas- thus, you could conceivably make a cylindrical world (impassible or infinite to the north, e-w passage), a toroidal world, or even a spherical world... somebody mentions something...
Surprise.
-
loftar
- Posts: 9096
- Joined: Fri Apr 03, 2009 7:05 am
- Location: Your character database
Re: World Gen
I have a few reactions on this;
On the one hand, I had not considered the idea of fractal landscape generated functionally, but it is of course true that such generation would make it extensible. It is a fascinating idea, and I may well explore it. Thank you!
On the other hand, there are a few other features planned in the map generator that are far from obvious how they would be implemented in a fractal landscape. It may not be completely impossible, though, and I'll keep considering it.
At the very least, I may well take the time to load your map into an alternative world so that I can explore it on a tile-scale and see what it looks like.
On the one hand, I had not considered the idea of fractal landscape generated functionally, but it is of course true that such generation would make it extensible. It is a fascinating idea, and I may well explore it. Thank you!
On the other hand, there are a few other features planned in the map generator that are far from obvious how they would be implemented in a fractal landscape. It may not be completely impossible, though, and I'll keep considering it.
At the very least, I may well take the time to load your map into an alternative world so that I can explore it on a tile-scale and see what it looks like.
"Object-oriented design is the roman numerals of computing." -- Rob Pike
-
Raephire
- Posts: 648
- Joined: Wed Jun 10, 2009 3:34 pm
Re: World Gen
I saw the current ocean and it made me very sad.
BUT! The game, even at this stage, is just so absolutely intoxicating that It's a detail I can neglect.
BUT! The game, even at this stage, is just so absolutely intoxicating that It's a detail I can neglect.