Bagaimana saya bisa menghasilkan danau dan sungai acak di game saya?

19

Saya memiliki permainan pembangun blok 2D dan saya mencoba membuat danau dan sungai yang dihasilkan secara acak. Saya telah melihat ke dalam algoritma noise Perlin, tetapi, saya tidak bisa mendapatkannya untuk menghasilkan hasil yang acak dan menyenangkan.

Saya telah mencoba menggunakan pustaka kebisingan python , tetapi, itu tidak membuat peta dengan sangat acak.

Apakah ada beberapa fungsi seed yang saya lewatkan di perpustakaan itu untuk membuatnya lebih acak? Variabel apa yang saya ubah jika saya menginginkannya menjadi lebih acak? Jika memungkinkan, beri saya jawaban yang kurang teknis, dengan lebih sedikit matematika dan lebih banyak istilah python.

Peta tersebut adalah peta ubin 2D. Berikut adalah beberapa contoh dari keacakan dari algoritma lainnya. Kode berikut dikeluarkan 3 kali berturut-turut. Saya mengacak oktaf dan frekuensi dengan sesuatu seperti ini: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

Ini adalah kode yang menghasilkan output di atas:

"""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
Julian
sumber
Tolong info lebih lanjut. Pertanyaan ini tidak dapat dijawab dalam kondisi saat ini.
Gustavo Maciel
Saya menambahkan sedikit lagi, tapi, apa yang perlu Anda ketahui.
Julian
Anda menambahkan info yang bagus, tetapi kami perlu lebih banyak. Apa itu "tidak terlalu acak"? Adakah tangkapan layar untuk kita melihat apa hasil yang diberikan, dan apa hasil yang diinginkan? Bagaimana Anda mencobanya? Ada kode untuk Anda tunjukkan kepada kami? Apa konteks Anda? 2D atau 3D? Ubin atau poligonal? Maaf jika semua ini terlalu banyak, Tapi aku hanya berusaha membantu. -1 bukan milik saya, jika Anda tidak memberikan info, pertanyaannya akan menjadi tidak layak untuk situs dan mereka akan menutupnya. Jadi sekali lagi, saya mencoba membantu.
Gustavo Maciel
2
+1, sekarang ini pertanyaan yang bagus :) Saya tidak bagus dengan perlin noise dan semua generasi prosedural, tetapi, apakah Anda menyemai objek acak? Jika saya tidak salah, random.seed()maka waktu sistem akan digunakan sebagai seed. Dan alih-alih octaves = random.randint(1,500000)*.000001+.5Anda dapat mencoba: octaves = random.random() (ini memiliki hasil yang sama, Anda akan mendapatkan angka antara 0 dan 1, tetapi kemungkinannya jauh lebih banyak daripada hanya 500.000 angka.)
Gustavo Maciel
Terima kasih +1 :) :) Sudah mencoba untuk menambahkan 1 komentar tetapi saya tidak bisa
Julian

Jawaban:

7

Nah, seperti yang terlihat, Anda tidak menyemai generator angka acak. Dalam python, ini dapat dengan mudah dilakukan hanya dengan random.seed () .

Dan saya dapat melihat Anda juga menghasilkan angka antara 1 dan 500000 dan membuatnya antara 0 dan 1. Ini adalah metode fungsional, tetapi dibatasi hingga hanya 500.000 kemungkinan. Anda lebih baik dengan hanya menggunakannya random.random()sudah menghasilkan angka antara 0 dan 1, tetapi dengan lebih banyak kemungkinan! Jika Anda masih membutuhkan angka antara 0,5 dan 1,0, seperti yang disarankan oleh kode Anda, Anda bisa melakukannya:(random.random() * 0.5) + 0.5

Kode akhir Anda akan terlihat sebagai berikut:

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

Itu saja!

Gustavo Maciel
sumber
Saya tidak jelas bagaimana seeding ada hubungannya dengan itu. Angka acak masih akan acak jika Anda tidak seed, tetapi akan diulang. Satu-satunya gejala tidak menabur harus urutan acak yang sama setiap kali Anda menjalankan program (dengan asumsi benih yang sama digunakan setiap kali).
Tim Holt
1
Jika Anda mendapatkan output yang sama tiga kali berturut-turut seperti yang disebutkan dalam pertanyaan Anda, sangat mungkin karena Anda belum menabur generator acak. Benih dan lihat apakah itu memperbaiki masalah.
ashes999
Ah saya belum melihat bit "3 kali berturut-turut" - sedang membaca, "Apakah ada fungsi seed yang saya lewatkan di perpustakaan itu untuk membuatnya lebih acak". Ya penyemaian untuk keacakan yang tidak berulang :)
Tim Holt
8

Ini bukan menjawab pertanyaan pemrograman spesifik Anda, tetapi pertimbangkan untuk membuat danau dan sungai bukanlah tentang menempatkan gumpalan air secara acak dan strip air di antara mereka. Ini tentang ketinggian medan - tentang depresi (cekungan) yang berubah menjadi danau, dan air yang mengalir dari tempat yang lebih tinggi ke tempat yang lebih rendah.

Jika Anda ingin contoh yang bagus untuk membuat danau dan sungai yang masuk akal, Anda dapat memeriksa posting blog ini -> http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html Ini referensi yang bagus untuk hal semacam ini jika tujuan Anda adalah hidrografi yang cukup realistis.

Tim Holt
sumber
2

Ini sangat sederhana: jika Anda mendapatkan peta yang sama tiga kali berturut-turut (atau lebih), itu karena Anda tidak mengacak benih.

Apa artinya ini?

Komputer secara inheren deterministik (non-acak), sehingga mereka mensimulasikan keacakan. Ini sebenarnya berulang berulang (itu sebabnya kami menyebutnya "pseudo random number generator").

Bagaimana cara kerjanya?

Saat Anda membuat angka acak, Anda memiliki opsi untuk memberinya "seed." Yang penting adalah jika Anda selalu menggunakan seed yang sama, Anda akan selalu mendapatkan urutan angka acak yang sama, dalam urutan yang sama. Selalu. Ini bisa baik atau buruk.

Dalam kasus Anda, sepertinya Anda tidak menabur generator acak, dan secara default, Anda mendapatkan benih yang sama - mungkin menggunakan beberapa komponen tanggal / waktu Anda. Karena itu, saya sarankan Anda mengacaknya.

Seperti yang disebutkan Gusatavo dalam jawabannya, Anda perlu menelepon random.seed () . Dokumen menyatakan bahwa "jika X [parameter default] dihilangkan atau None, waktu sistem saat ini digunakan." Ini harus cukup.

ashes999
sumber