Come posso generare laghi e fiumi casuali nel mio gioco?


19

Ho un gioco di costruzione di blocchi 2D e sto cercando di creare laghi e fiumi generati casualmente. Ho esaminato l'algoritmo del rumore Perlin, ma non sono riuscito a ottenere risultati casuali e piacevoli.

Ho cercato di utilizzare la libreria del rumore Python , ma non ha creato mappe in modo casuale.

C'è qualche funzione seed che mi manca in quella libreria per renderla più casuale? Quale variabile cambio se voglio che diventi più casuale? Se possibile, dammi una risposta meno tecnica, con meno matematica e più termini di pitone.

La mappa è una mappa piastrellata 2D. Ecco alcuni esempi della non casualità dell'altro algoritmo. Il seguente codice è stato emesso 3 volte di seguito. Stavo randomizzando le ottave e la frequenza con qualcosa del genere:freq = 16.0 * random.randint(1, 500000) * 0.000001 + 0.5

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

Questo è il codice che ha prodotto l'output sopra:

"""Writes a 256x256 grayscale simplex noise texture file in pgm format
(see http://netpbm.sourceforge.net/doc/pgm.html)
"""
# $Id: 2dtexture.py 21 2008-05-21 07:52:29Z casey.duncan $

import sys
from noise import pnoise2
import random
octaves = random.randint(1, 500000) * 0.000001 + 0.5
freq = 16.0 * octaves
for y in range(30):
    for x in range(40):
        n = int(pnoise2(x/freq, y / freq, 1)*10+3)
        if n>=1:
            n=1
        else:
            n=0
        print n,
    print

Maggiori informazioni, per favore. Non è possibile rispondere a questa domanda nel suo stato attuale.
Gustavo Maciel,

Ho aggiunto un po 'di più, ma cosa devi sapere.
Giuliano

Hai aggiunto buone informazioni, ma abbiamo bisogno di un po 'di più. Cosa è "non molto casuale"? Qualche schermata per noi vede qual è il risultato dato e qual è il risultato desiderato? Come l'hai provato? Qualche codice per mostrarci? Qual è il tuo contesto? 2D o 3D? Piastrellato o poligonale? Scusa se tutto questo è troppo, ma sto solo cercando di aiutare. Il -1 non era mio, se non fornisci informazioni, la domanda diventerà inadatta al sito e loro la chiuderanno. Quindi, sto ancora cercando di aiutare.
Gustavo Maciel,

2
+1, ora è una buona domanda :) Non sono bravo con il rumore del perlin e tutta la generazione procedurale, ma stai seminando l'oggetto casuale? Se non sbaglio, è random.seed()così che il tempo di sistema verrà utilizzato come seme. E invece di octaves = random.randint(1,500000)*.000001+.5te puoi provare: octaves = random.random() (ha lo stesso risultato, otterrai un numero compreso tra 0 e 1, ma ha molte più possibilità rispetto a soli 500000 numeri.)
Gustavo Maciel

Grazie +1 :) :) Ho cercato di aggiungere 1 commento ma non posso
Julian

Risposte:


7

Beh, a quanto pare, non stai seminando il generatore di numeri casuali. In Python, può essere fatto facilmente con solo random.seed () .

E vedo anche che stai generando un numero compreso tra 1 e 500000 e rendendolo compreso tra 0 e 1. È un metodo funzionale, ma è limitato a sole 500000 possibilità. Stai meglio con solo usarlo random.random()genera già un numero compreso tra 0 e 1, ma con molte più possibilità! Se hai ancora bisogno di un numero compreso tra 0,5 e 1,0, come suggerisce il codice, potresti semplicemente fare:(random.random() * 0.5) + 0.5

Il tuo codice finale dovrebbe apparire come segue:

import sys
from noise import pnoise2
import random
random.seed()
octaves = random.random()
# octaves = (random.random() * 0.5) + 0.5
freq = 16.0 * octaves
for y in range(30):
    for x in range(40):
        n = int(pnoise2(x/freq, y / freq, 1)*10+3)
        if n>=1:
            n=1
        else:
            n=0
        print n,
    print

È tutto!


Non sono chiaro come il seeding abbia qualcosa a che fare con esso. I numeri casuali saranno comunque casuali se non esegui il seeding, ma si ripeteranno. L'unico sintomo di non seeding dovrebbe essere la stessa sequenza casuale ogni volta che si esegue il programma (supponendo che lo stesso seed venga utilizzato ogni volta).
Tim Holt,

1
Se stai ottenendo lo stesso output tre volte di seguito come indicato nella tua domanda, è molto probabile perché non hai seminato il generatore casuale. Seminalo e vedi se risolve il problema.
cenere 1999,

Ah, non avevo visto il bit "3 volte di seguito" - stava leggendo "C'è qualche funzione seed che mi manca in quella libreria per renderla più casuale". Sì, semina per casualità non ripetuta :)
Tim Holt,

8

Questo non risponde alla tua specifica domanda di programmazione, ma considera che la creazione di laghi e fiumi non consiste nel posizionare casualmente macchie d'acqua e strisce d'acqua tra di loro. Riguarda l'altezza del terreno - le depressioni (bacini) che si trasformano in laghi e l'acqua che scorre dai punti più alti a quelli più bassi.

Se vuoi un ottimo esempio di creazione di laghi e fiumi che abbiano un senso, potresti dare un'occhiata a questo post del blog -> http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html È un buon riferimento per questo genere di cose se il tuo obiettivo è un'idrografia ragionevolmente realistica.


2

È molto semplice: se ottieni la stessa mappa tre volte di seguito (o più), è perché non hai randomizzato il seme.

Cosa significa questo?

I computer sono intrinsecamente deterministici (non casuali), quindi simulano la casualità. In realtà è ripetibilmente casuale (ecco perché lo chiamiamo "generatore di numeri pseudo casuali").

Come funziona?

Quando crei un numero casuale, hai la possibilità di dargli un "seme". L'importante è che se usi sempre lo stesso seme, otterrai sempre la stessa sequenza di numeri casuali, nello stesso ordine. Sempre. Questo può essere buono o cattivo.

Nel tuo caso, sembra che non stai eseguendo il seeding del generatore casuale e, per impostazione predefinita, stai ottenendo lo stesso seed - probabilmente utilizza alcuni componenti della tua data / ora. Quindi, ti consiglio di randomizzarlo.

Come menzionato da Gusatavo nella sua risposta, devi chiamare random.seed () . I documenti affermano che "se X [il parametro predefinito] viene omesso o Noneviene utilizzata l'ora di sistema corrente". Questo dovrebbe essere sufficiente.

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.