Generazione di mappe casuali: strategie per la diffusione / raggruppamento di nodi casuali


10

Sto realizzando un semplice gioco di strategia 4X nello spazio in cui ogni nodo è un punto di interesse (un pianeta, un asteroide e così via).

Per generare casualmente una mappa, seguirei i passaggi seguenti

  1. Decidi quanti tipi di ciascun nodo avrà la mappa (forse, diciamo, 5 pianeti simili alla Terra, 10 pianeti sterili ecc.)

  2. Posiziona ogni tipo di nodo sulla mappa.

Per il passaggio 2 vorrei avere una diffusione uniforme di ciascun tipo di nodo. Quindi, per esempio, inizierei posizionando tutti i pianeti simili alla terra. Se faccio semplicemente un rand (map.width, map.height) per determinare la posizione, potrei finire per raggruppare tutti i pianeti simili alla terra, il che darà vantaggio al giocatore che inizia in quella zona.

Esistono metodi, come l'utilizzo di diverse funzioni grafiche o di rumore, che potrebbero generare una sequenza di coordinate (x, y) che si estendono l'una dall'altra. Allo stesso modo, ci sono modi per generare coordinate vicine tra loro?


1
Contrassegna una risposta come accettata, sia mia che di qualcun altro. Grazie.
Ingegnere

Risposte:


8

Il problema che stai affrontando è che la selezione casuale non discrimina, e ciò può significare che si tratta di una soluzione tutt'altro che ideale per ciò che devi fare. Ma esiste almeno un modo semplice per aggirare questo:

  1. Dividi il tuo spazio in settori (ad esempio, se hai un'area di 100 per 100 e devi generare 100 di questi sistemi solari, quindi dividi la tua area in una griglia di settori 10 per 10)

  2. Passa attraverso ciascun settore e ripeti il ​​passaggio 3 (che, a sua volta, ripeterà il passaggio 4 più volte)

  3. Determinare casualmente il numero di pianeti per l'attuale sistema solare (ad esempio, per un intervallo da 3 a 7 pianeti, basta acquisire un numero casuale compreso tra 0 e 4 e aggiungere 3) nel settore corrente (se si dispone di più di un solare sistema in un settore, è qui che avresti impostato un altro loop)

  4. Assegna casualmente i tuoi pianeti all'interno dell'attuale Sistema Solare identificato dal tuo loop (puoi anche usare numeri casuali per aumentare le distanze minime tra i pianeti); è qui che decideresti i tipi di pianeti, che potrebbero anche essere determinati casualmente con una varietà di pesi o qualunque metodo tu preferisca usare

Puoi anche definire un'area "fuori limite" attorno al bordo di ciascun settore per impedire ai pianeti dei settori vicini di entrare in contatto diretto tra loro (nel caso in cui fossero effettivamente posizionati fianco a fianco), oppure. ..

Un'altra soluzione potrebbe essere quella di decidere la posizione di ciascun sistema solare e / o di ogni pianeta, per eseguire un rapido controllo di prossimità contro i settori vicini e adattarsi di conseguenza (ad esempio, allontanarsi dal bordo di una distanza minima più una distanza casuale ).


Prego! E +1 per la pubblicazione di alcuni follow-up su ciò che ha risolto il tuo problema. =)
Randolf Richardson,

8

Il modo migliore per garantire una distribuzione uniforme è trattare ogni nodo come una sorta di particella fisica. Prima fai una distribuzione casuale su un piano xy continuo (a virgola mobile). Applicando forze di repulsione tra ciascuna coppia distinta di singole particelle sul piano, scoprirai che si diffondono lentamente. In un certo senso è come la risoluzione delle collisioni, solo che non esiste alcun contatto reale di cui parlare. È quindi semplice convertire quel piano ("rasterizzarlo") in una griglia con indice intero. Puoi semplicemente farlo da una griglia con indice intero per cominciare, ma potrebbe essere un po 'più difficile rendere le cose "belle" - questo dipende da quanto è alta la risoluzione della tua griglia ... più alta è, meglio è , in questo caso.

Ovviamente potresti voler applicare una sorta di forza anche dai bordi del piano quadrato, oppure potresti trovare molte particelle "che si lavano sulle rive". In alternativa, puoi creare un campo molto più grande del necessario, quindi scattare un'istantanea di una piccola area di ciò - questo evita il problema di cui sopra.

Quando si desidera garantire il contrario, ovvero che si verifichi il clustering , esaminare la distribuzione "standard" o "gaussiana". Questo è il motivo per cui i campi stellari generati casualmente sembrano spesso falsi; usano la pura distribuzione casuale piuttosto che un modello di distribuzione più naturalistico.


1
Puoi anche ottenere un comportamento di raggruppamento dal modello "fisica", dovrai solo usare un diverso insieme di regole, possibilmente usando un mix di attrazione e repulsione. Le opzioni sono infinite, tutto quello che bisogna fare è trovare il modello giusto.
aaaaaaaaaaaa,

6

È possibile utilizzare un semplice algoritmo di distribuzione del disco di Poisson per ottenere una distribuzione "rumore blu". Ciò si traduce in punti nel piano che sono approssimativamente distanziati equamente l'uno dall'altro. Questo funziona non solo nel tuo esempio 2D ma anche in 3D, e anche in spazi non euclidei, ma i calcoli possono diventare rapidamente ingombranti.

L'idea di base di quegli algoritmi è che si inizia con un primo punto "seed", quindi si lavora verso l'esterno aggiungendo punti casuali o pseudo-casuali nell'annulus tra le distanze massima e minima che si desidera avere dal punto in poi ed eliminare quelli che si trovano troppo vicini l'uno all'altro. Il tuo algoritmo funziona quindi verso l'esterno in questo modo, fino a quando non viene aggiunta la quantità di punti necessari (che ti dà una nuvola di punti approssimativamente circolare) o lo spazio disponibile viene riempito.

Un algoritmo alternativo rapido ed elegante per la generazione di tali disturbi 2D, nonché una breve discussione delle loro proprietà, è disponibile in " Una struttura di dati spaziali per la generazione veloce di campioni su disco Poisson " di Daniel Dunbar e Greg Humphreys dell'Università della Virginia.


2
Non avevo mai sentito parlare delle distribuzioni del disco di Poisson - buon collegamento!
ten
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.