C++ 使用柏林噪波生成二维地形(基于瓷砖)
我一直在研究柏林噪声的一个应用程序,我正在开发一个基本上是“二维侧视”的游戏(模拟)。我不完全理解柏林噪声是如何工作的,但我能大致了解 我找到了这篇包含代码的文章,并决定在几年前发布,目前我设置world gen的方式是,每个“块”都有16x16个瓷砖,我刚刚声明,如果Y>=HEIGHT/2使所有瓷砖为“实心”,否则为“空气”,这样就行了。。但是,正如你想象的那样,这片土地非常平坦。这就是我认为柏林墙噪音的原因,所以我使用了上面网站上的代码,但我不确定如何将噪音转化为实心/空心瓷砖 正如你所看到的,地形不是很真实 我更喜欢下面的地形。应该看起来像山和起伏的小山)我不担心尖锐的边缘(正方形) 我不知道如何通过迭代的瓷砖阵列,把噪音变成上面 目前,我正在像这样遍历瓷砖阵列(2d),但正如您从第一张图片中看到的,它只是随机化瓷砖是否为实心,它不会创建任何起伏的山丘或山脉C++ 使用柏林噪波生成二维地形(基于瓷砖),c++,perlin-noise,C++,Perlin Noise,我一直在研究柏林噪声的一个应用程序,我正在开发一个基本上是“二维侧视”的游戏(模拟)。我不完全理解柏林噪声是如何工作的,但我能大致了解 我找到了这篇包含代码的文章,并决定在几年前发布,目前我设置world gen的方式是,每个“块”都有16x16个瓷砖,我刚刚声明,如果Y>=HEIGHT/2使所有瓷砖为“实心”,否则为“空气”,这样就行了。。但是,正如你想象的那样,这片土地非常平坦。这就是我认为柏林墙噪音的原因,所以我使用了上面网站上的代码,但我不确定如何将噪音转化为实心/空心瓷砖 正如你所看到
for(int Y = 0;Y < HEIGHT;++Y) {
for(int X = 0;X < WIDTH;++X) {
Tile Tile;
if(noise(X,Y) < 0) {
Tile.Type = BLOCK;
} else {
Tile.Type = Air;
}
// Then I push the Tile on to a vector
for(int Y=0;Y
我还应该提到,在这个16x16“块”的右侧,还有一个块需要与这个块匹配,之后的下一个块也需要匹配。块不应该与前面的块相同,只要让它们看起来不是单独的块,如果这有意义的话
非常感谢您的帮助!谢谢
更新
我已将我的柏林函数更改为的,并实现了phresnel建议的:
PerlinNoise *test=new PerlinNoise(0.25, 6); //0.25 is Persistance 6 is Octaves
float f,h;
float seed = 804.343;
for (int X=0; X!=MAP_WIDTH; ++X) {
f = test->GetNoise((X * ChunkX) * seed);
h = f * MAP_HEIGHT + (MAP_HEIGHT / 2);
for (int y=0; y<h; ++y) {
Tile tempTile;
tempTile.Tile = TILE_NONE;
Tiles[X][y] = tempTile;
}
for (int y=h; y<MAP_HEIGHT; ++y) {
Tile tempTile;
tempTile.TileID = TILE_BLOCK;
Tiles[X][y] = tempTile;
}
}
PerlinNoise*test=newperlinnoise(0.25,6);/0.25是持续性6是八度音阶
浮点数f,h;
漂浮种子=804.343;
对于(int X=0;X!=MAP_WIDTH;++X){
f=测试->获取噪声((X*ChunkX)*种子);
h=f*地图高度+(地图高度/2);
对于(int y=0;y您的结果很好,因为您有岛屿、大陆、池塘和海洋。柏林噪声帮助您生成非随机特征的随机地形
基本上,你可以将噪波函数的无限分辨率(数学上)减少为两个不同分片的离散集,再加上块的非常有限的分辨率。考虑到这一点,你的结果看起来很好
不同的事情可能会改善结果。例如,在平铺图形之间进行lerp:
// Exemplary p-code, fine-tuning required
Color color_at (x, y) {
Real u = x / width, v = y / height
Real f = min (max(noise(u,v), 0), 1);
Color c = water*f + hill*(1-f);
return c;
}
您可以将lerp函数推广到任何平铺计数
锐利边缘的另一种可能性来自(1)。您具有与上述相同的功能,但不是插值,而是使用最接近噪波值的瓷砖:
Color color_at (x, y) {
Real u = x / width, v = y / height
Real f = min (max(noise(u,v), 0), 1);
if (f<0.5) return water;
else return hill;
}
(x,y)处的颜色{
实际u=x/宽度,v=y/高度
实际f=最小值(最大值(噪声(u,v),0),1);
如果(f抱歉,如果我没有充分解释这个问题,我需要的是一个“侧视图”,而不是鸟瞰图。我想我理解,你肯定知道你的东西。我实际上不使用setPixel,我要做的是一旦在for循环中设置了磁贴,比如说tile=block
,它定义了程序中稍后渲染的磁贴。我在您的回答中,您似乎只迭代x(上面的每个像素都是天空的一部分,下面的每个像素都是[实心]),我启动地图的方式是[0][0]->[15][15]那么y然后x,如果我按照你的建议做了,它似乎又会变成一个混乱,我需要改变这个吗?@Elgoog:是的,我的解决方案假设你可以画单个像素。你可以在CPU上,或者甚至在GPU上足够快地做这件事(但我没有真正的GPGPU经验)。你真正的问题是块状,还是有太多的“棕色”呢瓷砖?
for (int x=0; x!=width; ++x) {
// Get noise value:
f = noise1d (x/width);
h = f * height + (height/2); // scale and center at screen-center
// Select tile:
Tile *tile;
if (h < waterLimit) {
h = waterLimit;
tile = waterTile;
} else {
tile = terrainTile;
}
// Draw vertical line:
for (int y=0; y<h; ++y)
setPixel (x, y, skyColor(x,y));
for (int y=h; y<height; ++y)
setPixel (x, y, tileColor(x,y, tile));
}