Bir şehir caddesi ağı nasıl oluşturulur?


16

Bir oyun için bir şehir jeneratörü oluşturmak istiyorum, ancak kuşağın en başında bir sorunla karşı karşıyayım: yol sistemi.

Bir ortaçağ dünyası olduğu için, birçok modern şehir gibi bir ızgara planı istemiyorum . İdeal olarak, kaybolmanın mümkün olabileceği, ancak bazı mantıkla - tam bir labirent değil, sahte caddelerin ve daha küçük sokakların sahte rastgele bir neslini tercih ederim.
Doğal olarak büyümüş bir kasaba gibi görünen bir şey.

Basitleştirmek için, şehirlerimin nehir geçişi veya rahatlama sorunu olmadan düz ve sabit arazilerde olacağını varsayalım. Sonra bir çözüme entegre etmeye çalışabilirim.

Şehirlerim için kesin bir boyuta veya eğilime karar vermedim, bu yüzden sadece kesin bir formdaki şehirlerle (kare, daire, dikdörtgen vb.) Çalışacak bir çözümünüz varsa, onu alırım.


2
Subversion için yaptıkları Introversion Yazılımı ile prosedürel şehir üreticisine bakmak isteyebilirsiniz. Oyunun kendisi iptal edilirken, jeneratörlerinden bol miktarda çekim var.
Philipp

Ne istediğinize dair bir örneğiniz var mı (hedef sürenizden gerçek hayat örneği, başka bir oyundan örnek, eskiz vb.)? 'Izgara değil' ile 'tam bir labirent değil' arasında birçok seçenek var.
Pikalek

@Pikalek Daha fazla hassasiyet vermiyorum çünkü sahip değilim. Çok özel bir şey aramıyorum, ne bir labirent ne de bir ızgara planı üretmeyen herhangi bir nesil örneği beni tatmin edebilir.
Aracthor

Yanıtlar:


21

Prosedürel şehir kuşağı ile başlamak için iyi bir yer, Parish ve Müller'in Şehirlerin Prosedür Modellemesi'dir . Kağıtları, nüfus yoğunluğu ve yol desenleri (dikdörtgen ızgara, radyal ve en az yükseklik değişimi) ile ilgili kuralların birleştirildiği ve daha sonra su cepheleri ve yol estetiği gibi yerel kısıtlamaları karşılamak için sabitlendiği bir L Sistemi sunar . Bu sistemin sonuçları etkileyici olmakla birlikte, gereksiz yere karmaşık olduğu eleştirilmektedir . Barrett'in alternatif çözümü Rudzicz'ın Spare Parts dev blogunda aşağıdaki gibi yeniden ifade edildi :

  • "önerilen" yolların bir listesini tutmak
  • onları bir sıraya göre değerlendir
  • kabul edilebilirlerse (bazı küçük değişiklikler olsun veya olmasın)
  • kabul edilen her yolu saklarken bir avuç daha dallanmış

Bu yaklaşım Parish ve Müller'in L Sistemindeki simge yeniden yazma kalıtımının çoğunu kaldırır. Burada bu yaklaşımın bir demosunu görebilirsiniz .

Bu yaklaşımın bir avantajı, şehir şekli agnostik olmasıdır - gerektiği gibi anahat kısıtlamaları ekleyebilirsiniz, böylece şehir şekliniz algoritma yerine oyun tasarım ihtiyaçlarınız tarafından belirlenebilir. Şehir boyutuna bağlı olarak, bu olduğu gibi yeterince iyi olabilir. Yukarıdaki demodan 100 segment sınırı olan bir sonuç aşağıda verilmiştir: resim açıklamasını buraya girin Ancak büyük bir şeye ihtiyacınız varsa sorun yaşayabilirsiniz; İşte segment sınırlaması 500 olan bir sonuç: resim açıklamasını buraya girin

Kısmen, yol dallanma kurallarını değiştirerek, 90 derece açılardan kaçınarak vb. Ayarlayabilirsiniz. Düzeniniz hala çok düzenliyse, düzeltmem:

Şehir ızgarasını, her sokağın bir kenar olduğu ve her kavşağın bir düğüm olduğu bir grafiğe dönüştürün. Ardından, grafiği bir labirente dönüştürmek için tercih ettiğiniz algoritmayı kullanın . Labirente dönüşen son örnek: resim açıklamasını buraya girin

Şimdi çıktı tam tersi bir problem, labirent gibi. Ama şimdi Jamis Buck'ın Dungeon Generator'ın Gizli İşlerinden birkaç teknik uygulayabiliriz . İlk olarak, bazı çıkmaz koridorları kaldırarak seyrekliği artırın. Ardından, döngüler oluşturan yollar ekleyerek bağlantıyı artırın (yani grafiğe döngüler ekleyin). İşte bir örnek sonuç: resim açıklamasını buraya girin

Not: Aynı nihai sonucu, doğrudan şehir şebekesine kenar kaldırmaları uygulayarak, doğrudan önceki ızgara yönelimli yerleşim aşamasından (labirent oluşturmadan önce) elde etmek mümkündür. Bu yaklaşımdaki sorun, bir kenarın kaldırılmasının şehri bölümlemediğinden ve bölümleri erişilemez hale getirmediğinden emin olmanızdır.


6

Google'da ortaçağ / eski şehir planları arıyorsanız pek çok farklı varyasyonlar bulacaksınız çoğunlukla (örneğin rastgele yerleşim vs askeri konumunu düzenlenen) şehir kökenleri dayalı.

Daha doğal olarak yetişen / kaotik bir yerleşim yeri arıyorsanız sanırım.

Bunlar için şöyle bir yaklaşım denerdim:

  • Bir uçtan diğer uca giden bir ana yol ile başlayın (ve ideal olarak diğer yerleşimleri birbirine bağlayın. İsterseniz üçüncü bir yol oluşturun, böylece yerleşiminize başlamak için bir kavşak elde edin.
  • Bazı evleri yol boyunca yerleştirin (sadece bir tarafa).
  • Şimdi bu yolu evler boyunca genişletin ve diğer tarafa büyük bir dönüm noktası ekleyin (tipik olarak bir kilise, ancak bu aynı zamanda bir değirmen veya benzeri olabilir). Burası sizin merkeziniz / pazarınız olacak.
  • Şimdi evlerle birlikte alanın dışında iki pozisyon seçin ve evleri çevreleyen yeni bir yol oluşturun.
  • İsteğe bağlı olarak eski ve yeni yolu bağlayan evler arasında daha küçük müttefikler oluşturun.
  • Şimdi "çekirdeğinizden" memnun olana kadar tekrarlayın:
    • Birkaç ev daha ekleyin.
    • Onları çevreleyen başka bir yol ekleyin.
    • Yolları birbirine bağlayan sokakları ekleyin.
  • Bundan memnun olduğunuzda, işiniz bitti. Bir kasaba olması gerekiyorsa, duvarlarla çevreleyin ve duvarların dışına ek evler ekleyerek son adımları birkaç kez tekrarlayın.

3

Her şeyden önce, prosedürel üretim yapmanın yolları vardır ve bunların hiçbiri hiç de kolay değildir, nasıl çalıştırabileceğinize, nasıl yapacağınıza, değiştirdiğinize veya attığınıza nasıl bir yaklaşım yapacağım.

Anlaması daha kolay olduğu için JS'de sözde kod yazacaktır.

1º bir giriş noktası tanımlayın, bir ortaçağ şehri inşa etmek istediğiniz gibi bir kare ile başlayacağız, bu yüzden kasabanızın 300 kare birimi olacak ve kare bunun ortasında olacak (X ile temsil edilecek).

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

const square = [ 150, 150 ];

2º Şimdi caddeler olacağız, rastgele bir sayı olacak, düz olacaklar ve orta meydandan veya diğer caddelerden başlayacaklar

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

Bu size bir kare ve çift ana cadde vermeli

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

Şimdi ana meydanda başlamayan caddeleri ayarlamamız gerekiyor, diğer caddelerle kesişecekler

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] ];

}

Dik vektörler elde etmek için x, y kablolarını değiştirmeniz ve yeni y'yi reddetmeniz gerekir:

kaydırıldı == x: noswiped.y, y: -1 * (noswiped.x)

Şu an buna benzer bir şeye sahip olmalısın, kasaba gibi görünmüyor mu? : P

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

Şimdi, sadece caddeleri kısa sokaklarla birbirine bağlamak zorundasınız, ayrıca, tüm kasaba boyunca rastgele kareler oluşturabilir ve hepsi için yukarıdakiyle aynı şeyi yapabilir veya sadece bazı meydanlardan küçük sokaklar çıkarabilirsiniz, bu size kalmış.

Unutmayın, sokaklarınız ne kadar kısaysa, kasaba kaotik gibi görünüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.