Come farei per generare una mappa stellare?


8

Sto cercando di generare una mappa stellare.

Il mio tentativo sarebbe:

  1. Avere una larghezza e un'altezza per la mappa.
  2. Posizionare i punti (stelle) in modo casuale attraverso l'area di larghezza e altezza.

Un approccio semplice, ma ha il problema di posizionare casualmente le stelle estremamente vicine tra loro.

Per risolvere questo problema, un approccio sarebbe quello di avere una distanza minima e quando si genera una stella, si confronta la distanza dalla nuova stella a ogni stella generata e se la sua distanza minima inferiore, ne genera una nuova, ma non so se è efficiente. Qualche consiglio?


3
Potrebbero esserci modi più efficienti per farlo, ma perché non funziona per te? Hai problemi con questa implementazione? Stai ottimizzando prematuramente?
Vaillancourt

Qual è lo scopo della mappa stellare? È uno sfondo, o più come un campo da gioco?
Erik,

@AlexandreVaillancourt sì, non so quante stelle voglio ancora generare e sembra che sia un modo molto inefficiente.
zebleckDAMM,

@Erik non è uno sfondo, stelle con cui puoi interagire
zebleckDAMM,

E ... lo farai in fase di esecuzione o offline?
Vaillancourt

Risposte:


13

Una distribuzione di campionamento di Poisson-Disk ti permetterà di selezionare punti casuali a una distanza minima e l'algoritmo di Bridson può risolvere efficacemente il problema in O (n) - abbastanza veloce per il tempo reale a condizione che il conteggio delle stelle non diventi troppo grande.

L'algoritmo di Bridson divide la regione di output in una griglia di celle dimensionata rispetto alla distanza minima consentita, in modo tale che in ciascuna cella possa apparire solo un punto. Quindi, quando si considera l'aggiunta di un nuovo punto, è necessario solo controllare una raccolta di celle vicine a forma di disco anziché l'intero elenco di punti. Ad esempio, considera la seguente immagine:

inserisci qui la descrizione dell'immagine

Quando si verifica se il punto blu candidato è troppo vicino ai punti esistenti, non è necessario verificarlo con tutti i punti esistenti. Invece puoi limitare la ricerca ai punti nelle celle vicine (che puoi trovare rapidamente usando una tabella di ricerca). Mike Bostock ha una bella animazione che mostra l'algoritmo in corso.

L'implementazione standard riguarda solo una distanza minima fissa tra i punti. L' articolo di campionamento del disco di Poisson di Herman Tulleken (include il codice sorgente) copre un adattamento per variare la distanza minima in diverse parti dell'immagine; fondamentalmente come un algoritmo di dithering . L'uso del rumore perlin / del rumore simplex come mostrato nelle nuvole dell'articolo potrebbe dare una mappa stellare dall'aspetto più naturale. Ad esempio, ho usato l'immagine a sinistra per generare la destra:

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Per fare ciò, quando si considera un punto candidato, per prima cosa controllo il valore dell'immagine di input, che produce un valore da 0 a 1. Quindi lo ridimensiono alla distanza minima e massima desiderata tra i punti; in questo caso ho selezionato 5 e 20 pixel. Quindi quando posiziono un punto nelle regioni scure, le mie stelle possono essere vicine quanto 5 pixel l'una all'altra e quando posizionano le stelle nelle regioni chiare, possono essere distanti fino a 20 pixel.

Vale la pena notare che l'accelerazione di Bridson non funziona esattamente con il campionamento a distanza variabile perché i punti di uscita non utilizzano una distanza minima uniforme. Tuttavia, è ancora possibile utilizzare una griglia di output per ridurre la ricerca. Più piccola è la griglia, più rapida sarà la ricerca dei vicini più vicini a scapito di una maggiore memoria per una tabella di ricerca più ampia.


2
I collegamenti sono molto belli. Tuttavia, potrebbero perdersi nel tempo. Potrebbe essere ancora meglio includere maggiori dettagli qui.
Trilarion,

Aggiunti un po 'più di spiegazione e illustrazione per proteggerlo.
Pikalek,

1

Una soluzione molto ingenua ma semplice sarebbe quella di saltare semplicemente sempre la distanza "minima", e quindi aggiungere una quantità casuale in più. Questo significa che le stelle non avranno mai un amico troppo amico, e almeno avrai un po 'di deviazione.

per esempio

for (int x = 0; x < MAX_WIDTH; x+= MIN_SEPERATION_X)
{
  x += generateRandom();

  for (int y = 0; y < MAX_HEIGHT; y+= MIN_SEPERATION_Y)
  {
    y += generateRandom();

    if (x < MAX_WIDTH && y < MAX_HEIGHT)
    {
      image[x + y * width] = STAR;
    }
  }
}

(Inserimento della funzione di generazione di numeri casuali preferita)


E se colpissi un'altra stella lì? (Anche le tue stelle dovrebbero essere in una fascia inclinata se fai così.)
Trilarion

1
È possibile colpire un'altra stella? Presumo solo una iterazione sull'intera immagine. Entrambi i numeri che cambiano sempre di una separazione minima non lo fermano? Sento che le fusioni stellari sono piuttosto disordinate, quindi concordo che è bene assicurarsi che non si verifichino. Causare una supernova sarebbe un bug molto sconsiderato.
Huxellberger,

Volevo dire che min_separation non è garantito (non può essere con questo algoritmo) perché aggiungi sempre numeri casuali. Almeno assicurati, i numeri casuali non possono essere maggiori di min_separation. La distanza minima garantita è quindi min_separation - max (generate_Random). Ma non è un approccio davvero negativo. +1
Trilarion

Questo approccio tenderà a produrre colonne di stelle in linee verticali ordinate, poiché non si varia la coordinata x quando cambia y. È improbabile che ciò appaia casuale o naturale per raccolte dense.
DMGregory

0

Se conosci la dimensione XYZ del tuo spazio di gioco, puoi scegliere un punto casuale in quello spazio

e poi fai uno SphereCast per verificare se c'è già qualcosa di troppo vicino.

//pseudo code

SpawnStar(){
 Vector3 spot = new vector3(random(0,world size),random(0,world size,random(0,world size)

  while(true){
  SphereCast(spot, radius)
   if(hit something){
      spot = get new random spot
    }else{
     SpawnStar();
     brake;
    }
  } 
}

Il problema è che probabilmente non sarà molto buono in tempo reale, tuttavia per i pre-generati va bene e abbastanza veloce.


1
Qualunque sia uno SphereCast, non è esattamente questa la soluzione menzionata nella domanda e considerata inefficiente?
Trilarion,


1
Penso che intendi OverlapSphere. SphereCast spara una sfera lungo una linea, quindi ha un'impronta di rilevamento a forma di capsula.
DMGregory
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.