다이아몬드 사각형 알고리즘은 프랙탈 지형 (하이 맵) 생성 알고리즘입니다. 여기서 어떻게 작동하는지에 대한 좋은 설명을 찾을 수 있습니다.
http://www.gameprogrammer.com/fractal.html (참조로 사용)
http://www.playfuljs.com/realistic-terrain-in-130-lines/ (훌륭한 JS 구현, 아마도 그의 렌더러를 훔치고 싶을 수도 있습니다.이 알고리즘이 http : // demos 가 가능한 기능을 여기에서 살펴보십시오 . playfuljs.com/terrain/ )
일반적으로 종자는 4 개의 모서리를 시드 (a)로하고 4 개의 모서리를 평균화하고 임의의 값 (예 : -0.5와 0.5 (b))을 추가하여 중심점의 높이를 계산합니다. 이것을 그리드에 적용하면 다이아몬드 그리드 (45도 사각형)를 다시 얻을 수 있고 동일한 (c, d) 반복하지만 랜덤 범위는 더 작아집니다 (예 : -0.125 ~ 0.125 등).
프로그램은 다음과 같은 많은 입력을 수용해야합니다.
l=1,2,3,...
변의 길이가 사각형 격자의 크기를 결정 하는 정수 입니다2^l+1
. 에서l=10
당신은 약 백만 번호를 저장해야합니다.- 각 코너에 4 개의 씨앗 (부동 소수점)
- 무작위 범위의 초기 크기를 의미하는
0<h<1
거칠기 (H
링크) 를 결정 하는 매개 변수 a,b
랜덤 범위의 초기 하한 및 상한을 나타내는 매개 변수h
는 각 세분화 단계에서 곱해집니다 . 임의의 숫자는a
및 사이에서 균일하게 선택b
됩니다.
출력은 완성 된 2D 그리드로 구성되어야합니다.
따라서 대략적인 알고리즘은 다음과 같습니다.
Create a square grid with sidelength 2^l+1
Place seed values in the corners
Repeat:
| Perform square steps
| Refine Range: a = a*h; b=b*h;
| Perform diamond steps
| Refine Range
알아야 할 세부 사항이 하나 있습니다. 격자의 경계에는 다이아몬드의 정점이 3 개뿐이므로이 세 점의 평균도 계산해야합니다.
일부 예제의 시각화 (사용한 매개 변수를 알려주십시오)는 선택 사항이지만 높이 평가되며 물론 바이트 수에 추가하지 않습니다.
이 알고리즘의 약간 변형 된 구현은 여기에서 찾을 수 있습니다 : 평행 투영 복셀 지형 생성기
2d에서 하이트 맵을 그레이 스케일 이미지로 대체하기 위해 자바 스크립트에서 작은 그리기 함수를 만들었습니다. http://jsfiddle.net/flawr/oy9kxpsx/
당신의 누군가가 멋진 3D에 있고 3D로지도를 볼 수있는 스크립트를 만들 수 있다면 알려주십시오! =)
답변
자바, 1017 바이트
입력은 다음과 같이 공백으로 구분 된 목록 l s1 s2 s3 s4 h a b
입니다.
출력은 숫자를 포함하는 2 차원 배열입니다.
프로그램:
import java.util.*;import static java.lang.Math.*;class C{public static void main(String[]a){int b=a.length,d=0;float[]c=new float[b];for(;d<b;){c[d]=Float.parseFloat(a[d++]);}e=(int)(pow(2,c[0])+1);f=new float[e][e];f[0][0]=c[1];f[0][e-1]=c[2];f[e-1][0]=c[3];f[e-1][e-1]=c[4];g=c[5];float h=c[6],i=c[7];s(0,0,e-1,e-1,h,i);System.out.print(Arrays.deepToString(f));}static int e;static float[][]f;static float g;static void s(int q,int r,int s,int t,float h,float i){if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)return;float o,p;int m=(q+s)/2,n=(r+t)/2;f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i-h)-h);d(m,r,m-q,o=h*g,p=i*g);d(q,n,m-q,o,p);d(m,t,m-q,o,p);d(s,n,m-q,o,p);}static void d(int x,int y,int e,float h,float i){float o,p;f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)-h);s(x-e,y-e,x,y,o=h*g,p=i*g);s(x,y-e,x+e,y,o,p);s(x-e,y,x,y+e,o,p);s(x,y,x+e,y+e,o,p);}static float a(int...j){float k=0,l=0;for(int d=0;d<j.length;d+=2){if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)continue;l++;k+=f[j[d]][j[d+1]];}return k/l;}}
들여 쓰기되어 맵을 표시하는 프로그램 :
import java.util.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.Math.*;
class D{
public static void main(String[]a){
int b=a.length,d=0;
float[]c=new float[b];
for(;d<b;){
c[d]=Float.parseFloat(a[d++]);
}
e=(int)(pow(2,c[0])+1);
f=new float[e][e];
f[0][0]=c[1];
f[0][e-1]=c[2];
f[e-1][0]=c[3];
f[e-1][e-1]=c[4];
g=c[5];
float h=c[6],i=c[7];
s(0,0,e-1,e-1,h,i);
showImage(f);
}
static int e;
static float[][]f;
static float g;
static void s(int q,int r,int s,int t,float h,float i){
if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)
return;
float o,p;
int m=(q+s)/2,n=(r+t)/2;
f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i+h)-h);
d(m,r,m-q,o=h*g,p=i*g);
d(q,n,m-q,o,p);
d(m,t,m-q,o,p);
d(s,n,m-q,o,p);
}
static void d(int x,int y,int e,float h,float i){
float o,p;
f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)+h);
s(x-e,y-e,x,y,o=h*g,p=i*g);
s(x,y-e,x+e,y,o,p);
s(x-e,y,x,y+e,o,p);
s(x,y,x+e,y+e,o,p);
}
static float a(int...j){
float k=0,l=0;
for(int d=0;d<j.length;d+=2){
if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)
continue;
l++;
k+=f[j[d]][j[d+1]];
}
return k/l;
}
public static void showImage(float[][] f){
float maxHeight = Float.MIN_VALUE;
float minHeight = Float.MAX_VALUE;
for (float[] row : f){
for (float height : row){
if (height > maxHeight){
maxHeight = height;
}
if (height < minHeight){
minHeight = height;
}
}
}
int e = f.length;
BufferedImage image = new BufferedImage(e, e, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < e; x++){
for (int y = 0; y < e; y++){
Color color = Color.getHSBColor((float)((f[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
image.setRGB(x,y,color.getRGB());
}
}
JFrame frame = new JFrame("Picture");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JComponent(){
@Override
public void paint(Graphics g){
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
});
frame.setVisible(true);
frame.setBounds(0,0,e,e);
}
}
Java에서 맵을 표시하는 함수는 다음과 같습니다.
public static void showImage(float[][] map){
float maxHeight = Float.MIN_VALUE;
float minHeight = Float.MAX_VALUE;
for (float[] row : map){
for (float height : row){
if (height > maxHeight){
maxHeight = height;
}
if (height < minHeight){
minHeight = height;
}
}
}
int size = map.length;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < size; x++){
for (int y = 0; y < size; y++){
Color color = Color.getHSBColor((float)((map[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
image.setRGB(x,y,color.getRGB());
}
}
JFrame frame = new JFrame("Picture");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JComponent(){
@Override
public void paint(Graphics g){
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
});
frame.setVisible(true);
frame.setBounds(0,0,size,size);
}
이 이미지의 크기는 모두 7
입니다. 4 씨앗은 5
, 10
, 15
,와 20
.
a
하고 b
있습니다 -10
및 10
각각.
거칠기는에서 시작 .1
하여 .1
최대 증가 합니다 1
.
지형 생성 코드가 곧 나옵니다 !!!
이미지가 곧 온다 !!!