도시 거리 네트워크를 생성하는 방법?


16

게임용 도시 생성기를 만들고 싶습니다만 세대가 시작될 때 도로 시스템에 문제가 있습니다.

중세 세계이기 때문에 많은 현대 도시와 같은 그리드 계획을 원하지 않습니다 . 나는 이상적으로 길을 잃을 수도 있지만 여전히 완전한 미로가 아닌 일부 논리로 의사 거리가 아닌 큰 도로와 작은 거리의 의사 난수 생성을 선호합니다.
자연스럽게 자란 도시처럼 보일 것입니다.

간단하게 유지하기 위해 도시가 강을 건너거나 구호 문제없이 평평하고 안정적인 지형에 있다고 가정 해 봅시다. 나중에 솔루션에 통합하려고 시도 할 수 있습니다.

나는 도시의 정확한 크기 또는 배치를 결정하지 않았으므로 정확한 형태 (정사각형, 원, 사각형 등)의 도시에서만 작동하는 솔루션이 있다면 그것을 취할 것입니다.


2
Subversion을 위해 만든 Introversion Software의 절차 적 도시 생성기를 살펴볼 수 있습니다. 게임 자체가 취소되었지만 생성기 주변에는 많은 장면이 있습니다.
Philipp

당신이 원하는 것의 예가 있습니까 (목표 기간의 실제 예, 다른 게임, 스케치 등의 예)? '격자 없음'과 '완전한 음순'사이에는 많은 옵션이 있습니다.
Pikalek

@Pikalek 나는 그것을 가지고 있지 않기 때문에 더 정밀하지 않습니다. 나는 매우 구체적인 것을 찾고 있지 않습니다. 미로 나 그리드 계획을 생성하지 않는 세대의 예는 저를 만족시킬 수 없습니다.
Aracthor

답변:


21

절차 적 도시 생성으로 시작하기에 좋은 곳은 Parish and Müller의 절차 적 모델링 모델입니다 . 이 논문 은 인구 밀도 및 도로 패턴 (직사각형 그리드, 방사형 및 최소 고도 변화)에 관한 규칙을 결합한 다음 물 정면 및 도로 미학과 같은 로컬 제약 조건을 수용하도록 고정 하는 L 시스템 을 제시합니다 . 이 시스템의 결과는 인상적이지만 불필요하게 복잡하다는 비판을 받았습니다 . Barrett의 대체 솔루션은 Rudzicz의 Spare Parts dev 블로그 에 다음과 같이 정리 되어 있습니다.

  • "제안 된"도로 목록 유지
  • 순서대로 평가하다
  • 수용 가능한 경우 (약간의 수정이 있거나없는)
  • 허용 된 각 도로를 저장하고 그로부터 더 많은 분기를 "제안"

이 접근 방식은 교구 및 ül 러의 L- 시스템에서 대부분의 심볼 재 작성 하우스 키핑 상속을 제거합니다. 여기에서이 방법데모를 볼 수 있습니다 .

이 접근 방식의 이점은 도시 모양에 구애받지 않는다는 것입니다. 필요에 따라 윤곽 제약 조건을 추가 할 수 있으므로 알고리즘보다는 게임 디자인 요구에 따라 도시 모양을 결정할 수 있습니다. 도시 크기에 따라이 정도면 충분할 수 있습니다. 세그먼트 제한이 100 인 위의 데모 결과는 다음과 같습니다. 여기에 이미지 설명을 입력하십시오 그러나 큰 것이 필요한 경우 문제가있을 수 있습니다. 다음은 세그먼트 제한이 500 인 결과입니다. 여기에 이미지 설명을 입력하십시오

부분적으로, 도로 분기 규칙을 변경하고 90도 각도 등을 피하여이를 조정할 수 있습니다. 레이아웃이 여전히 규칙적인 경우 다음과 같이 수정하십시오.

각 거리가 가장자리이고 각 교차점이 노드 인 도시 그리드를 그래프로 변환하십시오. 다음으로 그래프를 미로로 변환 하기를 원하는 알고리즘을 사용 하십시오 . 다음은 미로로 전환 된 마지막 예입니다. 여기에 이미지 설명을 입력하십시오

이제 출력에 반대의 문제가 있습니다. 너무 미로입니다. 그러나 이제 Jamis Buck의 Dungeon Generator 비밀 작업 에서 몇 가지 기술을 적용 할 수 있습니다 . 먼저 막 다른 통로를 제거하여 희미 함을 높이십시오. 그런 다음 루프를 생성하는 도로를 추가하여 연결을 증가시킵니다 (예 : 그래프에주기를 도입). 결과는 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

참고 : 도시 그리드에 가장자리 제거 만 적용하여 이전 그리드 지향 레이아웃 단계 (미로를 생성하기 전에)에서 직접 동일한 최종 결과를 얻을 수 있습니다. 이 접근 방식의 문제점은 모서리를 제거해도 도시가 분할되지 않으므로 부분에 도달 할 수 없게해야합니다.


6

Google 에서 중세 / 오래된 도시 계획을 찾으면 대부분 도시의 기원 (예 : 무작위 정착 대 조직화 된 군사 위치)을 기반으로 다양한 변형이 있습니다.

나는 당신 이보다 자연스럽게 자란 / 혼란스러운 정착지를 찾고 있다고 가정합니다.

이를 위해 다음과 같은 접근 방식을 시도합니다.

  • 한쪽 끝에서 다른 쪽 끝으로가는 주요 도로부터 시작하십시오 (그리고 다른 정착지를 연결하는 것이 이상적입니다. 원하는 경우 세 번째 도로를 만들어 합의를 시작하는 교차점을 찾으십시오.
  • 도로를 따라 일부 주택을 배치하십시오 (한쪽 만).
  • 이제 집을 따라 그 도로를 넓히고 반대편에 주요 랜드 마크를 추가하십시오 (일반적으로 교회이지만 밀이나 비슷한 것일 수도 있습니다). 이것은 당신의 센터 / 시장이 될 것입니다.
  • 이제 주택 바깥 지역의 두 위치를 선택하고 주택을 둘러싸는 새로운 도로를 만드십시오.
  • 선택적으로 이전 도로와 새 도로를 연결하는 집 사이에 작은 동맹을 만들 수 있습니다.
  • "핵심"에 만족할 때까지 반복하십시오.
    • 집을 몇 개 더 추가하십시오.
    • 그들을 둘러싸고있는 다른 도로를 추가하십시오.
    • 도로를 연결하는 뒷골목을 추가하십시오.
  • 당신이 그것에 만족하면, 당신은 끝났습니다. 도시가되어야한다면 벽으로 둘러싸고 벽 바깥에 집을 더 추가하여 마지막 단계를 몇 번 더 반복하십시오.

3

우선, 절차 적 생성을 수행하는 방법에는 loooooot가 있으며 그중 어느 것도 전혀 쉽지 않습니다. 어떻게 작동시킬 수 있는지에 대한 접근 방식을 만들 것입니다. 수행, 수정 또는 폐기에 달려 있습니다.

이해하기 쉽기 때문에 JS에서 의사 코드를 작성합니다.

1º는 시작점을 정의합니다. 중세 도시를 짓고 싶을 때 사각형으로 시작하겠습니다. 따라서 도시에 300 제곱 단위가 있고 정사각형이 중간에 위치한다고 가정합니다 (X로 표시).

       300
________________
|               |
|               |
|               | 300
|       X       |
|               |
|               |
|_______________|

const square = [ 150, 150 ];

2º 이제 애비뉴가 나옵니다. 그중 임의의 숫자가 있습니다. 그들은 곧고 중간 광장이나 다른 애비뉴에서 시작합니다.

let avenues = [] // will contain start and end [[sx,sy],[ex,ey]]
const n_avenues = RANDOM(4, 8); // number of avenues
const n_av_from_square = RANDOM(0, avenues); // starting in the square

for av in av_from_square
  avenues.push(square, [RANDOM(0, 200) + 100, RANDOM(0, 200) + 100])
  // we want avenues to have, at least 100 units length, thats why we randomize just te last 200 units of the whole town size

이것은 당신에게 광장과 커플 메인 스트리트를 제공해야합니다

       300
________________
|   \\          |
|    \\         |
|     \\        | 300
|       X=====  |
|               |
|               |
|_______________|

이제 우리는 메인 광장에서 시작하지 않는 길을 설정해야합니다. 그들은 다른 길과 교차합니다.

for av in (n_avenues - av_from_square){
  const av_to_intersect = avenues[RANDOM(0,avenues.length)];

  //check av_to... and get a perpendicular vector (explained bellow)
  av[0] = [ av_to_intersect[0][1], - av_to_intersect[0][0] ];
  av[1] = [ av_to_intersect[1][1], - av_to_intersect[1][0] ];

}

수직 벡터를 얻으려면 x, y 코드를 바꾸고 새로운 y를 무효화해야합니다.

스 와이프 == x : noswiped.y, y : -1 * (noswiped.x)

지금 당신은 이것과 비슷한 것을 가져야합니다. 도시처럼 보이지 않습니까? :피

       300
________________
|   \\  //      |
|    \\//  ||   |
|     \\   ||   | 300
|    //\X=====  |
|   //     ||   |
|          ||   |
|_______________|

3º는 이제 거리를 짧은 거리와 상호 연결하기 만하면됩니다. 또한 마을 전체에 임의의 사각형을 스폰하고 위와 동일하게 만들거나 일부 사각형에서 작은 거리를 스폰 할 수 있습니다.

거리가 가장 짧을수록 도시가 혼란스러워 보이는 것을 기억하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.