I'm currently writing a world generator for a Tilemap-Engine in C++. But there is a little problem concerning the Water to Land ratio. My DiamondSquare-class returns a field of random float-values between 0 and 1, and my condition to let my tilemap-class generate a Land-Tile on the given spot, is that the returned value is bigger than 0.5. The problem is, that the amount of values bigger or smaller than 0.5 fluctuates with every call of my float-field-generation function, so that i often only have a few little Islands/a few little lakes on my map. How could i manipulate my code, so that a 50/50 distibution is more likeley to happen?
include "DiamondSquare.h"
include <Windows.h>
pragma comment (lib, "winmm.lib")
floatfield /*typedef floatfield is std::vector<std::vector<float>>*/ DiamondSquare::generate(int n, float randomness) {
// Initializing stuff
srand(timeGetTime());
fieldSize = pow(2,n)+1;
randField.resize(fieldSize);
for (int i=0; i<fieldSize; i++)
{
randField[i].resize(fieldSize);
for (int j=0; j<fieldSize; j++)
{
randField[i][j] = 0;
}
}
stepDist = pow(2, n-1);
m_randomness = randomness;
// Setting corner point values
randField[0][0] = (float)(rand()%1001)/1000;
randField[fieldSize-1][0] = (float)(rand()%1001)/1000;
randField[0][fieldSize-1] = (float)(rand()%1001)/1000;
randField[fieldSize-1][fieldSize-1] = (float)(rand()%1001)/1000;
// Core Algorithm
for (int i=0; i<n; i++)
{
for (int k=0; k<pow(2,i); k++)
{
for (int l=0; l<pow(2,i); l++)
{
// Getting position of current tile
int xPos = k*2*stepDist+stepDist;
int yPos = l*2*stepDist+stepDist;
// Getting Average of sorrounding tiles
randField[xPos][yPos] = (randField[xPos-stepDist][yPos-stepDist]+randField[xPos+stepDist][yPos-stepDist]+
randField[xPos+stepDist][yPos+stepDist]+randField[xPos-stepDist][yPos+stepDist])/4;
// Random displacement
if (rand()%2 == 1)
randField[xPos][yPos] += (float)(rand()%1001)/1000/pow(randomness,i+1);
else randField[xPos][yPos] -= (float)(rand()%1001)/1000/pow(randomness,i+1);
// Doing the same for the Square-Step tiles left of and above the current tile
squareAvg(xPos-stepDist, yPos, i);
squareAvg(xPos, yPos-stepDist, i);
// If diamond-step-tile is part of the right side row
if (k == pow(2,i)-1)
squareAvg(xPos+stepDist, yPos, i);
// If diamond-step tile is part of the bottom row
if (l == pow(2,i)-1)
squareAvg(xPos, yPos+stepDist, i);
}
}
stepDist /= 2; // Self explanatory
}
return randField; // Return random field.
[![Often, insted of maps like this, there is stuff like 10% water or 10% land][1]][1]}
void DiamondSquare::squareAvg(int x, int y, int i) {
// Testing if square-Tile lies at on of the sides of the map, if so, adding 0 (i tried implementing wrapping, but this option generated better looking landscapes)
randField[x][y] = (x!=0) ? randField[x-stepDist][y] : 0;
randField[x][y] += (x!=fieldSize-1) ? randField[x+stepDist][y] : 0;
randField[x][y] += (y!=0) ? randField[x][y-stepDist] : 0;
randField[x][y] += (y!=fieldSize-1) ? randField[x][y+stepDist] : 0;
// If 4 values were added /= 4, otherwise /=3.
if (x!=0 && x!=fieldSize-1 && y!=0 && y!=fieldSize-1)
randField[x][y] /= 4;
else randField[x][y] /= 3;
// Displacement
if (rand()%2 == 1)
randField[x][y] += (float)(rand()%1001)/1000/pow(m_randomness,i+1);
else randField[x][y] -= (float)(rand()%1001)/1000/pow(m_randomness,i+1);
}
Is it maybe even possible to preciseley control n<0.5 to n>0.5 ratio ? That would be ideal. I just don't know how and where to manipulate the code. That's about it.
rand()
isn't really right for this. Look at Perlin noise or simplex noise. \$\endgroup\$