Як я можу генерувати випадкові озера та річки у своїй грі?


19

У мене є 2D-блокова гра, яка намагається створити випадкові озера та річки. Я переглянув алгоритм шуму Перліна, але не зміг його отримати для отримання випадкових і приємних результатів.

Я намагався використовувати бібліотеку шумових пітонів , але це не створювало карти дуже випадково.

Чи є якась функція насіння, яку я не вистачає в цій бібліотеці, щоб зробити її більш випадковою? Яку змінну я можу змінити, якщо хочу, щоб вона стала більш випадковою? Якщо можливо, дайте мені менш технічну відповідь, з меншою кількістю математики та більшою кількістю пітонних термінів.

Карта є двовимірною плитковою картою. Ось кілька прикладів невипадковості іншого алгоритму. Наступний код виводився 3 рази поспіль. Я рандомізував октави та частоту приблизно так: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

Це код, який дав вихід вище:

"""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

Більше інформації, будь ласка. На це питання не можна відповісти в поточному стані.
Густав

Я додав ще трохи, але що вам потрібно знати.
Джуліан

Ви додали гарну інформацію, але нам потрібно трохи більше. Що таке «не дуже випадково»? Будь-який знімок екрана до нас бачить, що це за результат і який бажаний результат? Як ти спробував це? Будь-який код, який ви нам покажете? Який ваш контекст? 2D або 3D? Плитка чи багатокутник? Вибачте, якщо все це занадто багато, але я лише намагаюся допомогти. -1 не було моїм, якщо ви не дасте інформацію, питання стане непридатним для сайту, і вони закриють його. Тож знову намагаюся допомогти.
Густаво Масель

2
+1, зараз це гарне питання :) Мені непогано з шумом перлин і всіма процедурними поколіннями, але ви сієте випадковий об'єкт? Якщо я не помиляюсь, його random.seed()системний час буде використовуватися як насіння. І замість цього octaves = random.randint(1,500000)*.000001+.5ви можете спробувати: octaves = random.random() (він має такий самий результат, ви отримаєте число від 0 до 1, але його набагато більше можливостей, ніж просто 500000 чисел.)
Густаво Масьєль,

Дякую +1 :) :) Пробував плюс 1 коментар, але я не можу
Джуліан

Відповіді:


7

Ну, як здається, вас немає висіваєте генератор випадкових чисел. У python це легко зробити за допомогою просто random.seed () .

І я також бачу, що ви генеруєте число від 1 до 500000 і присвоюєте це значення між 0 і 1. Це функціональний метод, але він обмежений лише 500000 можливостями. Вам краще просто використовувати random.random()його вже створює число від 0 до 1, але набагато більше можливостей! Якщо вам все-таки потрібне число від 0,5 до 1,0, як підказує ваш код, ви можете просто зробити:(random.random() * 0.5) + 0.5

Ваш остаточний код повинен виглядати так:

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

Це все!


Мені не зрозуміло, наскільки посів має щось спільне з цим. Випадкові числа все одно будуть випадковими, якщо ви не посіяєте, але повторитеся. Єдиним симптомом несідіння має бути однакова випадкова послідовність кожного разу, коли ви запускаєте програму (припускаючи, що одне і те ж насіння використовується кожен раз).
Тім Холт

1
Якщо ви отримуєте той самий вихід три рази поспіль, як зазначено у вашому запитанні, це дуже ймовірно, тому що ви не посадили випадковий генератор. Посійте його і подивіться, чи вирішує проблему.
попіл999

Ах, я не бачив біт "3 рази поспіль" - читав: "Чи є якась функція насіння, яку я відсутня в цій бібліотеці, щоб зробити її більш випадковою". Так, висівання для неповторних випадковостей :)
Тім Холт

8

Це не відповідає вашому конкретному програмному питанню, але врахуйте, що створювати озера та річки - це не випадкове розміщення крапель води та смужок води між ними. Йдеться про висоту місцевості - про поглиблення (басейни), що перетворюються на озера, і воду, яка тече з вищих на нижні місця.

Якщо ви хочете чудовий приклад створення озер і річок, які мають сенс, ви можете ознайомитися з цим дописом у блозі -> http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html Це хороший орієнтир для подібних речей, якщо ваша мета - досить реалістична гідрографія.


2

Це дуже просто: якщо ви отримуєте одну і ту ж карту тричі поспіль (або більше), це тому, що ви не рандомізували насіння.

Що це означає?

Комп'ютери за своєю суттю детерміновані (не випадкові), тому вони імітують випадковість. Це насправді повторно випадково (саме тому ми називаємо це "генератором псевдовипадкових чисел").

Як це працює?

Коли ви створюєте випадкове число, у вас є можливість дати йому "насіння". Важливим є те, що якщо ви завжди використовуєте одне і те ж насіння, ви завжди отримаєте однакову послідовність випадкових чисел, в одному порядку. Завжди. Це може бути добре чи погано.

У вашому випадку, схоже, ви не сієте випадковий генератор, і за замовчуванням ви отримуєте те саме насіння - воно, ймовірно, використовує якийсь компонент вашої дати / часу. Отже, я рекомендую вам їх рандомізувати.

Як згадував Гусатаво у своїй відповіді, вам потрібно зателефонувати random.seed () . Документи зазначають, що "якщо X [параметр за замовчуванням] пропущено, або використовується Noneпоточний системний час." Цього має бути достатньо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.