map editor has much more powerful random height function

You can give parameters now, to influence the map height calculation.
This commit is contained in:
titiger 2015-02-10 02:06:02 +01:00
parent b4fabc2717
commit 4c5440f78c
6 changed files with 120 additions and 68 deletions

View File

@ -103,6 +103,13 @@ MainWindow::MainWindow(string appPath)
resourceUnderMouse=0;
objectUnderMouse=0;
// default values for random height calculation that turned out to be quite useful
randomWithReset=true;
randomMinimumHeight=-300;
randomMaximumHeight=400;
randomChanceDevider=30;
randomRecursions=3;
this->appPath = appPath;
Properties::setApplicationPath(executable_path(appPath));
@ -187,7 +194,7 @@ void MainWindow::init(string fname) {
// ---------------------------------------------------------
menuEdit->Append(miEditRandomizeHeights, wxT("Randomize &Heights"));
menuEdit->Append(miEditRandomize, wxT("Randomi&ze Heights/Players"));
menuEdit->Append(miEditRandomize, wxT("Randomi&ze Players"));
menuEdit->Append(miEditSwitchSurfaces, wxT("Switch Sur&faces..."));
menuEdit->Append(miEditInfo, wxT("&Info..."));
menuEdit->Append(miEditAdvanced, wxT("&Advanced..."));
@ -985,10 +992,40 @@ void MainWindow::onMenuEditRandomizeHeights(wxCommandEvent &event) {
if(program == NULL) {
return;
}
while(true){
program->setUndoPoint(ctAll);//randomizeHeights(-300,400,30,3);
program->setUndoPoint(ctAll);
program->randomizeMapHeights();
setDirty();
SimpleDialog simpleDialog;
simpleDialog.addValue("Initial Reset", boolToStr(randomWithReset),"If set to '0' no height reset is done before calculating");
simpleDialog.addValue("Min Height", intToStr(randomMinimumHeight),"Lowest random height. example: -300 or below if you want water , 0 if you don't want water.");
simpleDialog.addValue("Max Height", intToStr(randomMaximumHeight),"Max random height. A good value is 400");
simpleDialog.addValue("Chance Devider", intToStr(randomChanceDevider),"Defines how often you get a hill or hole default is 30. Bigger number, less hills/holes.");
simpleDialog.addValue("Smooth Recursions", intToStr(randomRecursions),"Number of recursions cycles to smooth the hills and holes. 0<x<50 default is 3.");
if (!simpleDialog.show("Randomize Height")) return;
try {
randomWithReset=strToBool(simpleDialog.getValue("Initial Reset"));
randomMinimumHeight=strToInt(simpleDialog.getValue("Min Height"));
randomMaximumHeight=strToInt(simpleDialog.getValue("Max Height"));
randomChanceDevider=strToInt(simpleDialog.getValue("Chance Devider"));
randomRecursions=strToInt(simpleDialog.getValue("Smooth Recursions"));
// set insane inputs to something that does not crash
if(randomMinimumHeight>=randomMaximumHeight) randomMinimumHeight=randomMaximumHeight-1;
if(randomChanceDevider<1) randomChanceDevider=1;
// set randomRecursions to something useful
if(randomRecursions<0) randomRecursions=0;
if(randomRecursions>50) randomRecursions=50;
program->randomizeMapHeights(randomWithReset, randomMinimumHeight, randomMaximumHeight,
randomChanceDevider, randomRecursions);
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
}
}
void MainWindow::onMenuEditRandomize(wxCommandEvent &event) {
@ -997,7 +1034,7 @@ void MainWindow::onMenuEditRandomize(wxCommandEvent &event) {
}
program->setUndoPoint(ctAll);
program->randomizeMap();
program->randomizeFactions();
setDirty();
}

View File

@ -197,6 +197,12 @@ private:
int resourceUnderMouse;
int objectUnderMouse;
bool randomWithReset;
int randomMinimumHeight;
int randomMaximumHeight;
int randomChanceDevider;
int randomRecursions;
ChangeType enabledGroup;
string fileName;

View File

@ -153,6 +153,7 @@ Program::Program(int w, int h) {
hideWater=false;
ofsetX = 0;
ofsetY = 0;
map = new MapPreview();
resetFactions(8);
renderer.initMapSurface(w, h);
@ -564,12 +565,12 @@ void Program::shiftDown() {
}
void Program::randomizeMapHeights() {
if(map) map->randomizeHeights();
void Program::randomizeMapHeights(bool withReset,int minimumHeight, int maximumHeight, int chanceDevider, int smoothRecursions) {
if(map) map->randomizeHeights(withReset, minimumHeight, maximumHeight, chanceDevider, smoothRecursions);
}
void Program::randomizeMap() {
if(map) map->randomize();
void Program::randomizeFactions() {
if(map) map->randomizeFactions();
}
void Program::switchMapSurfaces(int surf1, int surf2) {
@ -588,8 +589,7 @@ void Program::resize(int w, int h, int alt, int surf) {
void Program::resetFactions(int maxFactions) {
if(map) map->resetFactions(maxFactions);
for (int i = 0; i < map->getMaxFactions(); ++i)
map->changeStartLocation(2*i,2*(i%4)+5,i);
randomizeFactions();
}
bool Program::setMapTitle(const string &title) {

View File

@ -103,7 +103,6 @@ private:
//static Map *map;
static MapPreview *map;
friend class UndoPoint;
ChangeStack undoStack, redoStack;
void init();
@ -152,8 +151,8 @@ public:
void shiftUp();
void shiftDown();
void randomizeMapHeights();
void randomizeMap();
void randomizeMapHeights(bool withReset, int minimumHeight, int maximumHeight, int chanceDevider, int smoothRecursions);;
void randomizeFactions();
void switchMapSurfaces(int surf1, int surf2);
void loadMap(const string &path);
void saveMap(const string &path);

View File

@ -207,16 +207,16 @@ public:
void reset(int w, int h, float alt, MapSurfaceType surf);
void resize(int w, int h, float alt, MapSurfaceType surf);
void resetFactions(int maxFactions);
void randomizeHeights();
void randomize();
void randomizeHeights(bool withReset,int minimumHeight, int maximumHeight, int chanceDevider, int smoothRecursions);
void randomizeFactions();
void smoothSurface(bool limitHeights);
void switchSurfaces(MapSurfaceType surf1, MapSurfaceType surf2);
void loadFromFile(const string &path);
void saveToFile(const string &path);
void resetHeights(int height);
void sinRandomize(int strenght);
void decalRandomize(int strenght);
void realRandomize(int minimumHeight, int maximumHeight, int chanceDivider, int smoothRecursions);
void applyNewHeight(float newHeight, int x, int y, int strenght);
bool hasFileLoaded() const {return fileLoaded;}

View File

@ -704,17 +704,13 @@ void MapPreview::setAdvanced(int heightFactor, int waterLevel, int cliffLevel, i
hasChanged = true;
}
void MapPreview::randomizeHeights() {
resetHeights(random.randRange(8, 10));
sinRandomize(0);
decalRandomize(4);
sinRandomize(1);
void MapPreview::randomizeHeights(bool withReset,int minimumHeight, int maximumHeight, int chanceDevider, int smoothRecursions) {
if(withReset) resetHeights(random.randRange(8, 10));
realRandomize(minimumHeight,maximumHeight,chanceDevider,smoothRecursions);
hasChanged = true;
}
void MapPreview::randomize() {
randomizeHeights();
void MapPreview::randomizeFactions() {
int slPlaceFactorX = random.randRange(0, 1);
int slPlaceFactorY = random.randRange(0, 1) * 2;
@ -729,6 +725,40 @@ void MapPreview::randomize() {
hasChanged = true;
}
void MapPreview::smoothSurface(bool limitHeight) {
float *oldHeights = new float[w*h];
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
oldHeights[i*w+j] = cells[i][j].height;
//printf("count=%d height=%f h=%f\n",i*w+h,oldHeights[i*w+h],cells[i][j].height);
}
}
for (int i = 1; i < w - 1; ++i) {
for (int j = 1; j < h - 1; ++j) {
float height = 0.f;
float numUsedToSmooth = 0.f;
for (int k = -1; k <= 1; ++k) {
for (int l = -1; l <= 1; ++l) {
int tmpHeight=oldHeights[(j + k) * w + (i + l)];
if(limitHeight && tmpHeight>20){
tmpHeight=20;
}
if(limitHeight && tmpHeight<0){
tmpHeight=0;
}
height += tmpHeight;
numUsedToSmooth++;
}
}
height /= numUsedToSmooth;
cells[i][j].height=height;
}
}
delete[] oldHeights;
}
void MapPreview::switchSurfaces(MapSurfaceType surf1, MapSurfaceType surf2) {
if (surf1 >= st_Grass && surf1 <= st_Ground && surf2 >= st_Grass && surf2 <= st_Ground) {
for (int i = 0; i < w; ++i) {
@ -986,52 +1016,32 @@ void MapPreview::resetHeights(int height) {
}
}
void MapPreview::sinRandomize(int strenght) {
float sinH1 = random.randRange(5.f, 40.f);
float sinH2 = random.randRange(5.f, 40.f);
float sinV1 = random.randRange(5.f, 40.f);
float sinV2 = random.randRange(5.f, 40.f);
float ah = static_cast<float>(10 + random.randRange(-2, 2));
float bh = static_cast<float>((maxHeight - minHeight)) / static_cast<float>(random.randRange(2, 3));
float av = static_cast<float>(10 + random.randRange(-2, 2));
float bv = static_cast<float>((maxHeight - minHeight)) / static_cast<float>(random.randRange(2, 3));
void MapPreview::realRandomize(int minimumHeight, int maximumHeight, int _chanceDevider, int _smoothRecursions) {
int moduloParam=abs(maximumHeight-minimumHeight);
int chanceDevider=_chanceDevider;
int smoothRecursions=_smoothRecursions;
if(moduloParam<2) moduloParam=2;
//printf("moduloParam=%d minimumHeight=%d maximumHeight=%d\n",moduloParam,minimumHeight,maximumHeight);
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
float normH = static_cast<float>(i) / w;
float normV = static_cast<float>(j) / h;
// set chanceDevider to something possible
if(chanceDevider<2) chanceDevider=2;
#ifdef USE_STREFLOP
float sh = (streflop::sinf(static_cast<streflop::Simple>(normH * sinH1)) + streflop::sin(static_cast<streflop::Simple>(normH * sinH2))) / 2.f;
float sv = (streflop::sinf(static_cast<streflop::Simple>(normV * sinV1)) + streflop::sin(static_cast<streflop::Simple>(normV * sinV2))) / 2.f;
#else
float sh = (sinf(normH * sinH1) + sin(normH * sinH2)) / 2.f;
float sv = (sinf(normV * sinV1) + sin(normV * sinV2)) / 2.f;
#endif
float newHeight = (ah + bh * sh + av + bv * sv) / 2.f;
applyNewHeight(newHeight, i, j, strenght);
// set smoothRecursions to something useful
if(smoothRecursions<0) smoothRecursions=0;
if(smoothRecursions>1000) smoothRecursions=1000;
for (int i = 1; i < w-1; ++i) {
for (int j = 1; j < h-1; ++j) {
if(rand()%chanceDevider==1){
cells[i][j].height=(rand() % moduloParam)+minimumHeight;
}
}
}
}
void MapPreview::decalRandomize(int strenght) {
//first row
int lastHeight = DEFAULT_MAP_CELL_HEIGHT;
for (int i = 0; i < w; ++i) {
lastHeight += random.randRange(-1, 1);
lastHeight = clamp(lastHeight, minHeight, maxHeight);
applyNewHeight(static_cast<float>(lastHeight), i, 0, strenght);
}
//other rows
for (int j = 1; j < h; ++j) {
int height = static_cast<int>(cells[0][j-1].height + random.randRange(-1, 1));
applyNewHeight(static_cast<float>(clamp(height, minHeight, maxHeight)), 0, j, strenght);
for (int i = 1; i < w; ++i) {
height = static_cast<int>((cells[i][j-1].height + cells[i-1][j].height) / 2.f + random.randRange(-1, 1));
float newHeight = static_cast<float>(clamp(height, minHeight, maxHeight));
applyNewHeight(newHeight, i, j, strenght);
}
for( int i = 0; i<smoothRecursions;++i){
if(i+1==smoothRecursions)
smoothSurface(true);
else
smoothSurface(false);
}
}