MinecraftConsoles/Minecraft.World/ClimateLayer.cpp

87 lines
3 KiB
C++

#include "stdafx.h"
#include "ClimateLayer.h"
#include "Random.h"
#include "Mth.h"
#include "IntCache.h"
ClimateLayer::ClimateLayer(int64_t seed, int octaves, double scale, shared_ptr<Layer> parent)
: Layer(seed), scale(scale)
{
this->parent = parent;
Random random(seed);
temperatureNoise = new PerlinNoise(&random, octaves);
humidityNoise = new PerlinNoise(&random, octaves);
initBiomeCenters();
}
ClimateLayer::~ClimateLayer()
{
delete temperatureNoise;
delete humidityNoise;
}
void ClimateLayer::initBiomeCenters()
{
// Çàäà¸ì öåíòðû îñíîâíûõ áèîìîâ â ïðîñòðàíñòâå (òåìïåðàòóðà, âëàæíîñòü)
// Çíà÷åíèÿ ïîäîáðàíû íà îñíîâå setTemperatureAndDownfall() èç Biome.cpp
centers.push_back({ 0.00f, 0.25f, Biome::iceFlats }); // õîëîäíûå ðàâíèíû
centers.push_back({ 0.10f, 0.80f, Biome::taiga }); // òàéãà
centers.push_back({ 0.30f, 0.30f, Biome::extremeHills }); // ýêñòðåìàëüíûå õîëìû
centers.push_back({ 0.70f, 0.40f, Biome::plains }); // ðàâíèíû
centers.push_back({ 0.70f, 0.70f, Biome::forest }); // ëåñ
centers.push_back({ 0.80f, 0.95f, Biome::swampland }); // áîëîòî
centers.push_back({ 0.95f, 0.05f, Biome::desert }); // ïóñòûíÿ
centers.push_back({ 0.95f, 0.85f, Biome::jungle }); // äæóíãëè
// Ïðèìå÷àíèå: îêåàíè÷åñêèå áèîìû íå âêëþ÷åíû — îíè áóäóò îïðåäåëÿòüñÿ ïî âûñîòå îòäåëüíî.
// Õîëìèñòûå âàðèàíòû (desertHills, forestHills è ò.ä.) ìîæíî äîáàâèòü ïîçæå,
// èñïîëüçóÿ äîïîëíèòåëüíûé øóì âûñîòû èëè âòîðîé ïðîõîä.
}
Biome* ClimateLayer::getBiomeForClimate(float temp, float hum) const
{
float bestDist = 1e9f;
Biome* bestBiome = Biome::plains; // çàïàñíîé âàðèàíò
for (const auto& c : centers) {
float dx = temp - c.temp;
float dy = hum - c.hum;
float dist = dx * dx + dy * dy; // êâàäðàò åâêëèäîâà ðàññòîÿíèÿ
if (dist < bestDist) {
bestDist = dist;
bestBiome = c.biome;
}
}
return bestBiome;
}
intArray ClimateLayer::getArea(int xo, int yo, int w, int h)
{
IntCache::releaseAll();
intArray result = IntCache::allocate(w * h);
intArray parentMap = parent->getArea(xo, yo, w, h); // ïîëó÷àåì êàðòó ñóøè/îêåàíà
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int parentVal = parentMap[x + y * w];
if (parentVal == 0) { // îêåàí
result[x + y * w] = 0;
continue;
}
int worldX = xo + x;
int worldY = yo + y;
double tempNoise = temperatureNoise->getValue(worldX * scale, worldY * scale);
double humNoise = humidityNoise->getValue(worldX * scale, worldY * scale);
float normTemp = Mth::clamp((float)((tempNoise + 1.0) * 0.5), 0.0f, 1.0f);
float normHum = Mth::clamp((float)((humNoise + 1.0) * 0.5), 0.0f, 1.0f);
Biome* biome = getBiomeForClimate(normTemp, normHum);
result[x + y * w] = biome->id;
}
}
return result;
}