Come generare una rete stradale cittadina?


16

Vorrei creare un generatore di città per un gioco, ma sto affrontando un problema all'inizio della generazione: il sistema stradale.

Dato che è un mondo medievale, non voglio un piano a griglia come molte città moderne. Preferirei idealmente una generazione pseudo-casuale di grandi viali e strade più piccole, dove potrebbe essere possibile perdersi, ma con ancora un po 'di logica - non un labirinto completo.
Qualcosa che sembrerebbe una città cresciuta naturalmente.

Per semplicità, supponiamo che le mie città si troverebbero su terreni pianeggianti e stabili, senza alcun problema di attraversamento o rilievo. Potrei provare a integrarlo in una soluzione dopo.

Non ho deciso una dimensione o una disposizione precise per le mie città, quindi se hai una soluzione che funzionerebbe solo con città di una forma precisa (quadrata, circolare, rettangolo ecc.), La prenderei.


2
Potresti voler esaminare il generatore di città procedurale da Introversion Software che hanno realizzato per Subversion. Mentre il gioco stesso è stato cancellato, c'è un sacco di filmati in giro dal loro generatore.
Philipp,

Hai un esempio di ciò che desideri (esempio di vita reale del tuo periodo di tempo target, esempio di un altro gioco, schizzo, ecc.)? Ci sono molte opzioni tra "non una griglia" e "non un labirinto completo".
Pikalek,

@Pikalek Non do più precisione perché non ce l'ho. Non sto cercando qualcosa di molto specifico, nessun esempio di generazione che non generi né un labirinto né un piano a griglia potrebbe soddisfarmi.
Aracthor,

Risposte:


21

Un buon punto di partenza con la generazione procedurale di città è Parish and Müller Modeling procedurale di città . Il loro documento presenta un sistema a L in cui le regole relative alla densità di popolazione e ai modelli di strade (griglia rettangolare, radiale e minima variazione di elevazione) vengono combinate e quindi fissate per adattarsi a vincoli locali come fronti d'acqua ed estetica stradale. Mentre i risultati di questo sistema sono impressionanti, è stato criticato come inutilmente complicato . La soluzione alternativa di Barrett è ribadita nel blog degli sviluppatori di parti di ricambio di Rudzicz come segue:

  • mantenere un elenco di strade "proposte"
  • valutali in un certo ordine
  • se sono accettabili (con o senza alcune modifiche minori)
  • memorizzare ogni strada accettata mentre "propone" una manciata di più ramificazioni da essa

Questo approccio rimuove la maggior parte del simbolo che riscrive l'eredità delle pulizie in Parish e Müller L-System. Puoi vedere una demo di questo approccio qui .

Un vantaggio di questo approccio è che è agnostico a forma di città: è possibile aggiungere vincoli di contorno in base alle esigenze, quindi la forma della città può essere determinata dalle esigenze di progettazione del gioco piuttosto che dall'algoritmo. A seconda delle dimensioni della tua città, questo potrebbe essere abbastanza buono come lo è. Ecco un risultato della demo sopra con un limite di segmento di 100: inserisci qui la descrizione dell'immagine Ma se hai bisogno di qualcosa di grande, potresti avere problemi; ecco un risultato con un limite di segmento di 500: inserisci qui la descrizione dell'immagine

In parte, puoi modificarlo modificando le regole di diramazione della strada, evitando angoli di 90 gradi, ecc. Se il layout è ancora troppo regolare, ecco la mia correzione:

Trasforma la griglia della tua città in un grafico in cui ogni strada è un bordo e ogni incrocio è un nodo. Quindi, utilizza qualsiasi algoritmo che preferisci per convertire il grafico in un labirinto . Ecco l'ultimo esempio trasformato in un labirinto: inserisci qui la descrizione dell'immagine

Ora l'output ha il problema opposto, è troppo labirinto. Ma ora possiamo applicare un paio di tecniche tratte dal Secret Workings di Dungeon Generator di Jamis Buck . Innanzitutto, aumenta la scarsità rimuovendo alcuni corridoi senza uscita. Successivamente, aumenta la connettività aggiungendo in strade che creano loop (ovvero introducono cicli nel grafico). Ecco un risultato di esempio: inserisci qui la descrizione dell'immagine

Nota: è possibile ottenere lo stesso risultato finale direttamente dalla fase di layout orientata alla griglia precedente (prima di generare il labirinto), applicando solo la rimozione dei bordi alla griglia della città. Il problema con questo approccio è che è necessario assicurarsi che la rimozione di un bordo non divida la città rendendo le parti irraggiungibili.


6

Se cerchi piani di città medioevali su Google troverai molte varianti, principalmente basate sulle origini della città (ad esempio insediamento casuale vs. posizione militare organizzata).

Presumo che tu stia cercando un insediamento più naturale / caotico.

Per questi proverei un approccio come questo:

  • Inizia con una strada principale che va da un'estremità all'altra (e idealmente collega alcuni altri insediamenti. Se vuoi, crea una terza strada in modo da ottenere un incrocio sul quale iniziare il tuo insediamento.
  • Posizionare alcune case lungo la strada (solo su un lato).
  • Ora allarga quella strada lungo le case e aggiungi un importante punto di riferimento sull'altro lato (in genere una chiesa, ma potrebbe anche essere un mulino o simile). Questo sarà il tuo centro / mercato.
  • Ora scegli due posizioni all'esterno dell'area con le case e crea una nuova strada che racchiuda le case.
  • Facoltativamente, crea alcuni alleati più piccoli tra le case che collegano la vecchia e la nuova strada.
  • Ora ripeti finché non sei soddisfatto del tuo "core":
    • Aggiungi qualche altra casa.
    • Aggiungi un'altra strada racchiudendoli.
    • Aggiungi vicoli che collegano le strade.
  • Una volta che sei soddisfatto, hai finito. Se dovrebbe essere una città, circondala di mura e ripeti gli ultimi passaggi ancora una volta, aggiungendo altre case fuori dalle mura.

3

Prima di tutto, ci sono molti modi per fare generazione procedurale e nessuno di loro è affatto facile, farò il tipo di approccio a come potresti farlo funzionare, dipende da te prenderlo, modificarlo o scartarlo.

Pseudo-codice in JS poiché è più facile da capire.

1º definisci un punto di ingresso, poiché vuoi costruire una città medievale inizieremo con una piazza, quindi supponiamo che la tua città avrà 300 unità quadrate e la piazza sarà al centro di essa (rappresentata da una X).

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

const square = [ 150, 150 ];

2º ora saremo sui viali, ce ne sarà un numero casuale, saranno dritti e inizieranno dalla piazza centrale o da altri viali

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

Questo dovrebbe darti una piazza e un paio di strade principali

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

Ora dobbiamo impostare i viali che non iniziano nella piazza principale, si intersecano con gli altri viali

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

}

Per ottenere vettori perpendicolari devi scambiare i cavi x, y e annullare il nuovo y:

swiped == x: noswiped.y, y: -1 * (noswiped.x)

In questo momento dovresti avere qualcosa di simile a questo, non sembra una città? : P

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

3º ora devi solo collegare i viali con strade brevi, inoltre, potresti generare casuali casuali in tutta la città e fare lo stesso come sopra per tutti loro, o semplicemente generare piccole strade da alcune piazze secondarie, dipende da te.

Ricorda, più brevi sono le tue strade, più caotica sembra la città.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.