编辑:在尝试了一些事情之后重写了我的问题并使其更具体。
嗨,所以我正在创建一个带有程序生成的地图的移动RTS游戏。我已经研究了如何创建一个带有基本perlin噪声的地形,并尝试将https://gamedev.stackexchange.com/questions/54276/a-simple-method-to-create-island-map-mask方法集成到一个岛上。这是迄今为止的结果:
http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/下面的图片显示了我所追求的地形。那里的教程很棒但是过于密集,因此是帖子。
我希望随机形状的岛屿具有Perlin噪声产生的陆地质量,被水包围。
编辑:基本的Perlin terrain gen现在正在工作=)
这是我的代码。附加到null的脚本,带有一个按钮以激活Begin():
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class Gen_Perlin : MonoBehaviour {
public float Tiling = 0.5f;
private bool active = false;
public int mapHeight = 10;
public void Begin()
{
if (active == false) {
TerrainData terrainData = new TerrainData ();
const int size = 513;
terrainData.heightmapResolution = size;
terrainData.size = new Vector3 (2000, mapHeight, 2000);
terrainData.heightmapResolution = 513;
terrainData.baseMapResolution = 1024;
terrainData.SetDetailResolution (1024, 1024);
Terrain.CreateTerrainGameObject (terrainData);
GameObject obj = GameObject.Find ("Terrain");
obj.transform.parent = this.transform;
if (obj.GetComponent<Terrain> ()) {
GenerateHeights (obj.GetComponent<Terrain> (), Tiling);
}
} else {
GameObject obj = GameObject.Find ("Terrain");
if (obj.GetComponent<Terrain> ()) {
GenerateHeights (obj.GetComponent<Terrain> (), Tiling);
}
}
}
public void GenerateHeights(Terrain terrain, float tileSize)
{
Debug.Log ("Start_Height_Gen");
float[,] heights = new float[terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight];
for (int i = 0; i < terrain.terrainData.heightmapWidth; i++)
{
for (int k = 0; k < terrain.terrainData.heightmapHeight; k++)
{
heights[i, k] = 0.25f + Mathf.PerlinNoise(((float)i / (float)terrain.terrainData.heightmapWidth) * tileSize, ((float)k / (float)terrain.terrainData.heightmapHeight) * tileSize);
heights[i, k] *= makeMask( terrain.terrainData.heightmapWidth, terrain.terrainData.heightmapHeight, i, k, heights[i, k] );
}
}
terrain.terrainData.SetHeights(0, 0, heights);
}
public static float makeMask( int width, int height, int posX, int posY, float oldValue ) {
int minVal = ( ( ( height + width ) / 2 ) / 100 * 2 );
int maxVal = ( ( ( height + width ) / 2 ) / 100 * 10 );
if( getDistanceToEdge( posX, posY, width, height ) <= minVal ) {
return 0;
} else if( getDistanceToEdge( posX, posY, width, height ) >= maxVal ) {
return oldValue;
} else {
float factor = getFactor( getDistanceToEdge( posX, posY, width, height ), minVal, maxVal );
return oldValue * factor;
}
}
private static float getFactor( int val, int min, int max ) {
int full = max - min;
int part = val - min;
float factor = (float)part / (float)full;
return factor;
}
public static int getDistanceToEdge( int x, int y, int width, int height ) {
int[] distances = new int[]{ y, x, ( width - x ), ( height - y ) };
int min = distances[ 0 ];
foreach( var val in distances ) {
if( val < min ) {
min = val;
}
}
return min;
}
}
答案 0 :(得分:2)
是的。有问题的文章使用的是Waaay复杂方法。
执行此操作的最佳方法是采用一个表示基本孤岛形状的函数,高度值介于0到1之间。对于图片中的孤岛类型,您基本上希望某些东西可以平滑地从边缘,然后在想要湖泊的地方平稳地回落到零。
现在,您可以将该表面添加到基本的分形表面(如果要在低海拔高度保持尖峰度),或者将其相乘(如果希望较低的海拔高度平滑)。然后,定义一个高度,在该高度以下是水。
这是我用Terragen渲染的非常快速的方法:
我使用了一种功能,该功能从地图的边缘到中间的中间呈环形上升,然后再次下降,以匹配与文章中类似的形状。实际上,您可能只用它来获得岛的形状,然后雕刻与轮廓匹配的地形,然后掩埋其他所有东西。
我使用了自己的分形景观生成器,如下所述:https://fractal-landscapes.co.uk用于基本分形。
这是修改格局的C#代码:
public void MakeRingIsland()
{
this.Normalize(32768);
var ld2 = (double) linearDimension / 2;
var ld4 = 4 / (double) linearDimension;
for (var y = 0u; y < linearDimension; y++)
{
var yMul = y * linearDimension;
for (var x = 0u; x < linearDimension; x++)
{
var yCoord = (y - ld2) * ld4;
var xCoord = (x - ld2) * ld4;
var dist = Math.Sqrt(xCoord * xCoord + yCoord * yCoord);
var htMul = dist > 2 ? 0 :
(dist < 1 ?
dist + dist - dist * dist :
1 - (dist - 1) * (dist - 1));
var height = samples[x + yMul];
samples[x + yMul] = (int) (height + htMul * 32768);
}
}
}
答案 1 :(得分:1)
您展示的图片来自article,描述如何生成