Я делаю генератор мира в Java.Алгоритм работает, сначала устанавливая различные позиции с высокими точками (диапазонами) и низкими точками (траншеями), затем он усредняет все это, просматривая каждую плитку, получая высоту всех окружающих плиток, затем усредняя, затем устанавливая все окружающие плиткик новому усредненному значению.Затем он переходит к следующему тайлу и делает то же самое, проходя через оси X и Y.Надежда состоит в том, что он создаст мир, который динамически генерируется позициями диапазонов и траншей.И, посмотрев на простую картину, он действительно достигает этого.
Однако проблемы начинаются с того, что алгоритм запускается более одного раза, что необходимо для сглаживания карты.Ценности начинают стремительно расти, и я не могу понять, почему это происходит.Повторный запуск показывает этот эффект - функция среднего значения должна сдвигать значения к 0, а не к бесконечности.
Хотя местность выглядит немного шатко, при запуске по простому алгоритму шероховатости она выглядит хорошо.(В настоящее время отключено). Я могу сделать шероховатость позже, мне нужно выяснить, почему алгоритм сглаживания не работает.
Я знаю о таких инструментах, как Perlin Noise и Simplex Noise, и это становится все более и более яснымчто мне, возможно, придется начать их использовать, но я хочу выяснить, в чем заключается моя проблема.
Итак, я отследил ошибку до того факта, что ячейки среднего значения перекрываются.Усредняющий тайл 0,0 включает в себя все окружающие тайлы, но, конечно, при перемещении к следующему тайлу, он примет новое значение от 0,0 и включит его в функцию.Но это то, что я хочу.Я хочу, чтобы среднее значение распространялось по всей карте.Я исключил ошибки переполнения и потери, и сама функция среднего значения работает нормально.Интересно, что умножение значений «times» (которое должно быть 9) на 1,1 немного исправляет ошибку, но делает ландшафт слишком плоским.Это, очевидно, просто навязывает проблему.
public static void smoothHeight(int num) {
for (int z = 0; z < 1; z++) { //Run through once. Edit to find optimal?
for (int i = 0; i < toSmooth.size(); i++) { //toSmooth will contain HALF of all values on the map. It will have values on row 0, 2, 4, etc.
Integer[] pos = toSmooth.get(i);
int x = pos[0];
int y = pos[1];
Tile thisTile = FinalMap[x][y];
double avgHeightForAll = thisTile.getHeight(); //avgHeightForAll is used to eventually smooth. THIS IS THE VALUE THAT SHOULD GET AVERAGED OUT
double times = 0;
for (int x1 = x - 1; x1 <= x + 1; x1 += 1) {
for (int y1 = y - 1; y1 <= y + 1; y1 += 1) { //Go through tiles around it, and add to avg
Integer[] posToSmooth = smoothAlgFind(new Integer[] {x1, y1}, 1); //smoothAlgFind ensures that tiles across the map are included. For example, if smoothing at position 0, it will include position 499 in the smoothing, not -1
Tile tileToSmooth = FinalMap[posToSmooth[0]][posToSmooth[1]];
if (tileToSmooth.isCoastal == true || num == 0) {
double smoothTileh = tileToSmooth.getHeight();
avgHeightForAll += smoothTileh;
times++;
}
}
}
DecimalFormat df = new DecimalFormat("0.00");
avgHeightForAll /= (times); //DONT MESS WITH 1.17, REMOVING IT BREAKS EVERYTHING. NO I DONT KNOW WHY. times = 9
//thisTile.setHeight(avgHeightForAll, 0);
avgHeightForAll = Double.parseDouble(df.format(avgHeightForAll));
if (Math.abs(avgHeightForAll) > 40000) { //if something goes wrong this will trigger.
System.out.println((avgHeightForAll * times) + " / " + times + " = " + (avgHeightForAll));
}
for (int x1 = x - 1; x1 <= x + 1; x1 += 1) {
for (int y1 = y - 1; y1 <= y + 1; y1 += 1) {
Integer[] posToSmooth = smoothAlgFind(new Integer[] {x1, y1}, 1);
Tile tile = FinalMap[posToSmooth[0]][posToSmooth[1]];
if (tile.isCoastal == true || num == 0) {//don't worry about isCoastal, has been disabed for now
tile.setHeight(avgHeightForAll, 0);
}
}
}
}
for (int i = toSmooth.size() - 1; i >= 0; i--) { //now we go the other way to prevent scerw-y looking generation skewed to one side
Integer[] pos = toSmooth.get(i);
int x = pos[0];
int y = pos[1];
Tile thisTile = FinalMap[x][y];
double avgHeightForAll = thisTile.getHeight(); //avgHeightForAll is used to eventually smooth
double times = 0;
for (int x1 = x - 1 - p; x1 <= x + 1 + p; x1 += 1) {
for (int y1 = y - 1 - p; y1 <= y + 1 + p; y1 += 1) { //Go through tiles around it, and add to avg
Integer[] posToSmooth = smoothAlgFind(new Integer[] {x1, y1}, 1);
Tile tileToSmooth = FinalMap[posToSmooth[0]][posToSmooth[1]];
if (tileToSmooth.isCoastal == true || num == 0) { //don't worry about isCoastal, has been disabed for now
double smoothTileh = tileToSmooth.getHeight();
avgHeightForAll += smoothTileh;
times++;
}
}
}
DecimalFormat df = new DecimalFormat("0.00");
avgHeightForAll = Double.parseDouble(df.format(avgHeightForAll));
avgHeightForAll /= (times); //DONT MESS WITH 1.17, REMOVING IT BREAKS EVERYTHING. NO I DONT KNOW WHY.
//thisTile.setHeight(avgHeightForAll, 0);
avgHeightForAll = Double.parseDouble(df.format(avgHeightForAll));
//System.out.println("avgHeightForAll" + avgHeightForAll);
if (Math.abs(avgHeightForAll) > 40000) { //if something goes wrong this triggers!
System.out.println((avgHeightForAll * times) + " / " + times + " = " + (avgHeightForAll));
}
for (int x1 = x - 1; x1 <= x + 1; x1 += 1) {
for (int y1 = y - 1; y1 <= y + 1; y1 += 1) {
Integer[] posToSmooth = smoothAlgFind(new Integer[] {x1, y1}, 1);
Tile tile = FinalMap[posToSmooth[0]][posToSmooth[1]];
if (tile.isCoastal == true || num == 0) {
tile.setHeight(avgHeightForAll, 0);
}
}
}
}
}
System.out.println("Smoothed");
}