¿Has leído Las crónicas de Amber de Roger Zelazny?
Imagínese jugando en un juego MMO en tercera persona. Engendras en el mundo y comienzas a deambular. Después de un tiempo, cuando piensas, que has aprendido el mapa, te das cuenta de que estás en un lugar, que nunca has visto antes. Regresas al último lugar que estabas seguro de conocer y todavía está allí. Pero el resto del mundo ha cambiado y ni siquiera te diste cuenta de cómo sucedió.
He leído sobre la generación procesal mundial. He leído sobre el ruido y las octavas de Perlin, el ruido Simplex, el algoritmo Diamond-square, sobre la simulación de placas tectónicas y la erosión hídrica. Creo que tengo una vaga comprensión del enfoque general en la generación procesal mundial.
Y con este conocimiento, no tengo idea de cómo puedes hacer algo como lo escrito anteriormente. Cada idea que se me ocurre encuentra algunos problemas teóricos. Aquí hay algunas ideas que se me ocurren:
1) Generación mundial "reversible" con un número de semilla como entrada y algún número que describe completamente un fragmento
Dudo que sea posible, pero imagino una función que recibirá una semilla y producirá una matriz de números, sobre la cual se construyen los fragmentos. Y para cada número único hay un fragmento único. Y una segunda función, que obtiene este número de fragmento único y produce una semilla, que contiene este número. Intenté hacer un esquema en la imagen a continuación:
2) Hacer trozos completamente al azar y hacer una transición entre ellos.
Como sugirió Aracthor . Los beneficios de este enfoque es que es posible y no requiere una función mágica :)
Los inconvenientes que tiene este enfoque en mi opinión, es que probablemente no sea posible tener un mundo diverso. Si tiene, digamos, tanto el archipiélago como un continente representado por un solo número y son fragmentos adyacentes, entonces el tamaño de un fragmento no sería igual al continente. Y dudo que sea posible hacer una transición atractiva entre fragmentos. ¿Me estoy perdiendo de algo?
En otras palabras, estás desarrollando un MMO con un mundo generado por procedimientos. Pero en lugar de tener un mundo, tienes muchos . ¿Qué enfoque tomaría para generar mundos y cómo implementaría la transición del jugador de un mundo a otro sin que el jugador se dé cuenta de la transición?
De todos modos, creo que tienes la idea general. ¿Cómo lo habrías hecho?
fuente
Respuestas:
Use una porción de ruido de orden superior. Si utilizó ruido 2D para un mapa de altura antes, utilice ruido 3D con la última coordenada fija en su lugar. Ahora puede cambiar lentamente la posición en la última dimensión para modificar el terreno. Dado que el ruido Perlin es continuo en todas las dimensiones, obtendrá transiciones suaves siempre que cambie suavemente la posición donde muestrea la función de ruido.
Si solo desea cambiar el terreno lejos de la distancia al jugador como compensación, por ejemplo. También puede almacenar el desplazamiento para cada coordenada en el mapa y solo aumentarlo pero nunca disminuirlo. De esta manera, el mapa solo se vuelve más nuevo pero nunca más antiguo.
Esta idea también funciona si ya está usando ruido 3D, solo muestree a partir de 4D. Además, eche un vistazo al ruido Simplex. Es la versión mejorada del ruido Perlin y funciona mejor para más dimensiones.
fuente
Tu idea de dividir el mundo en varios trozos no es mala. Es solo incompleto.
El único problema son las uniones entre trozos. Por ejemplo, si usa ruido de perlin para generar alivio y una semilla diferente para cada fragmento, y corre el riesgo de que esto suceda:
Una solución sería generar un alivio del fragmento no solo de su semilla de ruido Perlin, sino también de otros fragmentos a su alrededor.
El algoritmo de Perlin utiliza valores de mapas aleatorios a su alrededor para "suavizarse". Si usan un mapa común, se suavizarían juntos.
El único problema es que si cambias una semilla de trozos para que sea diferente cuando el jugador retrocede, también tendrás que volver a cargar trozos, porque sus bordes también deberían cambiar.
Esto no cambiaría el tamaño de los fragmentos, pero aumentaría la distancia mínima desde el jugador hasta la carga / descarga, ya que un fragmento debe cargarse cuando el jugador lo ve y, con este método, los fragmentos adyacentes también deben estar cargados. .
ACTUALIZAR:
Si cada parte de tu mundo es de un tipo diferente, el problema crece. No se trata solo de alivio. Una solución costosa sería la siguiente:
Supongamos que los trozos verdes son mundos forestales, los azules archipiélagos y los amarillos desiertos planos.
La solución aquí es crear zonas de "transición", donde su relieve y la naturaleza terrestre (así como los objetos conectados a tierra o cualquier otra cosa que desee) cambien progresivamente de un tipo a otro.
Y como puede ver en esta imagen, la parte infernal del código serían pequeños cuadrados en las esquinas de los fragmentos: tienen que hacer un enlace entre 4 fragmentos, naturalezas potencialmente diferentes.
Entonces, para este nivel de complejidad, creo que las generaciones clásicas del mundo 2D como Perlin2D simplemente no se pueden usar. Me remito a la respuesta de @danijar para eso.
fuente
Si bien la idea de danijar es bastante sólida, podría terminar almacenando una gran cantidad de datos, si quisiera tener el área local igual y el cambio de distancia. Y solicitando más y más rebanadas de ruido cada vez más complejo. Puede obtener todo esto de una manera 2D más estándar.
Desarrollé un algoritmo para generar ruido fractal aleatorio de procedimiento, en parte basado en el algoritmo de diamante cuadrado que fijé para ser tanto infinito como determinista. Entonces, el diamante cuadrado puede crear un paisaje infinito, así como mi propio algoritmo bastante bloqueado.
La idea es básicamente la misma. Pero, en lugar de muestrear ruido dimensional superior, puede iterar valores en diferentes niveles iterativos.
Por lo tanto, aún almacena los valores que solicitó anteriormente y los almacena en caché (este esquema de forma independiente podría usarse para acelerar un algoritmo ya súper rápido). Y cuando se solicita una nueva área, se crea con un nuevo valor y. y cualquier área no solicitada en esa solicitud se elimina.
Entonces, en lugar de explorar diferentes espacios en dimensiones adicionales. Almacenamos un bit extra de datos monótonos para mezclar en diferentes (en cantidades progresivamente más grandes en diferentes niveles).
Si el usuario viaja en una dirección, los valores se mueven en consecuencia (y en cada nivel) y se generan nuevos valores en los nuevos bordes. Si se cambia la semilla iterativa superior, el mundo entero cambiará drásticamente. Si a la iteración final se le da un resultado diferente, entonces la cantidad de cambio será muy menor + -1 bloque más o menos. Pero, la colina todavía estará allí y el valle, etc., pero los rincones y grietas habrán cambiado. A menos que vayas lo suficientemente lejos, entonces la colina se habrá ido.
Entonces, si almacenamos una porción de valores de 100x100 en cada iteración. Entonces nada podría cambiar a 100x100 del jugador. Pero, a 200x200, las cosas podrían cambiar en 1 bloque. A 400x400 las cosas podrían cambiar en 2 bloques. A 800x800 de distancia, las cosas podrán cambiar en 4 bloques. Entonces las cosas cambiarán y cambiarán cada vez más a medida que avance. Si regresas, serán diferentes, si vas demasiado lejos, se cambiarán por completo y se perderán por completo, ya que se abandonarían todas las semillas.
Agregar una dimensión diferente para proporcionar este efecto estabilizador, sin duda funcionaría, cambiando la y a la distancia, pero estaría almacenando una gran cantidad de datos para una gran cantidad de bloques cuando no debería tener que hacerlo. En los algoritmos deterministas de ruido fractal, puede obtener este mismo efecto agregando un valor cambiante (en una cantidad diferente) a medida que la posición se mueve más allá de cierto punto.
https://jsfiddle.net/rkdzau7o/
fuente