0

Generación de mapas aleatorios con Blender Game Engine y OpenSimplex

Hola, homo fabers. Hace unos meses publiqué este tutorial, dónde os enseñé cómo generar mapas aleatorios utilizando Python y la librería OpenSimplex. Sobreponiendo varios mapas de ruido simplex conseguíamos generar mapas de terreno con océanos, montañas, islas y distintos tipos de biomas:

Algunos de vosotros me habéis pedido que haga también este mismo tutorial, pero explicando cómo hacer un mapa aleatorio con Blender Game Engine. Así que hoy hablaré precisamente de esto, y os enseñaré a programar un script que nos genere mapas aleatorios un poco parecidos a los de juegos de estrategia 4X como Civilization o Age of Wonders:

A ver, esto es Robologs, no los estudios de Electronic Arts ni Ubisoft. No me pidáis gráficos 3D full HD hiperrealistas…

¡Poned un poco de música y empezamos! Hoy trabajaremos con música ambiental de fondo…

Nota: Para poder seguir bien este tutorial, primero deberiáis leer el tutorial Generación de Mapas con Python y OpenSimplex que he mencionado al principio, porque hoy sólo explicaré como adaptar el script que hicimos para que funcione con Blender.


1. Instalar librerías en Blender

Necesitamos dos librerías para este proyecto: Numpy y OpenSimplex. Por suerte, Numpy ya viene por defecto en Blender y sólo tenemos que preocuparnos por la segunda librería.

OpenSimplex puede descargarse desde aquí. Id dónde pone “download”, descargad el paquete y descomprimidlo.

Una vez descomprimido encontraréis una carpeta llamada “OpenSimplex” dentro. Copiadla dentro del directorio dónde tengaís instalado Blender → 2.79 → python → lib → python3.5. Este es el directorio dónde están todas las librerías que utiliza el programa.

Ahora abrid Blender y os vaís a la pantalla de Scripting.

 

Escribid “import opensimplex” en la consola y pulsad enter:


Si la librería se ha instalado bien, no debería aparecer ningún mensaje de error:


2. Escena básica

[Descargad este archivo blend]

Para ahorrar tiempo os he preparado una escena básica sobre la que vamos a trabajar. Veréis que consta de dos capas: la capa principal (la primera) sólo contiene luces y la cámara, con los Logic Bricks para desplazarla con el teclado (teclas W-A-S-D). La segunda capa contiene todos los bloques de terreno. Nuestro script los irá copiando y colocando en la capa principal para formar el mapa.

Como veréis, tenemos bloques para construir 11 biomas diferentes: nieve, desierto frío, desierto templado, desierto tropical, taiga, bosque templado, bosque tropical, matorrales, pradería templada, pradería/sabana y mar.


 

En el tutorial original de Python y OpenSimplex teníamos algunos biomas más (p. ej. un segundo tipo de bosque templado, aguas costeras, yermo), pero creo que por hoy bastará con estos. ¡No obstante, siempre podéis añadir más biomas!

Mapa con todos los biomas que hay en la Tierra. Tenéis para ir modelando y texturizando hasta que os canséis…


3. Script en Python

Nuestro script en Python para generar el mapa será una variación del que hicimos la última vez. Las bases son idénticas: generaremos dos mapas de ruido simplex para la humedad y la elevación y colocaremos los biomas en función de éstos.

Abrid la escena básica que habéis descargado:

 

Vamos a empezar con el script. Id al ‘Text Editor‘ (la vista de arriba a la derecha) y pulsad el botón “New” (si queréis, podéis ampliar esta vista con Ctrl+Flecha arriba).

Pulsad aquí para crear un nuevo script

Bautizad el script con el nombre “terrain.py

El contenido del script es el que hay aquí debajo. Es casi idéntico al de la última vez, pero la diferencia está en el bucle que dibuja el mapa: comprobamos cuál es el valor de elevación y humedad de cada espacio de la matriz, y creamos una copia de alguno de los bloques de terreno (dependiendo de cuál sea el bioma que necesitemos). También se establece un valor para la variable ‘altura‘.

Al final del bucle colocamos este nuevo bloque una posición X,Y que viene dada por un múltiplo de los índices ‘i‘ ‘j‘ del bucle. La posición Z del espacio viene dada por la variable ‘altura’.

También hay otro cambio (menor), y es que usamos la librería ‘random’ para generar la semilla de los mapas de ruido, en vez de introducirla a mano. De esta forma aparecerá un mapa diferente cada vez que se inicie el juego.

"""
    SCRIPT PARA GENERAR MAPAS ALEATOROS CON BLENDER GAME ENGINE
    
    Escrito por Glare
    www.robologs.net
"""


#Importar librerias
from opensimplex import OpenSimplex
import numpy as np
import bge
from random import randint

#Guardar la escena actual
scene = bge.logic.getCurrentScene()
 
#Crear el objeto opensimplex con una semilla
seed_altura = randint(0, 1000)
seed_humedad = randint(0, 1000)
gen_altura = OpenSimplex(seed = seed_altura)
gen_humedad = OpenSimplex(seed = seed_humedad)
 
#Dimensiones del mapa
alto = 30
ancho = 30
 
#Array para guardar la elevacion
mapa_altura = np.empty([alto, ancho])
mapa_humedad = np.empty([alto, ancho])
 
#Valor de la frecuencia
#Aumentar este valor hace el mismo efecto que un zoom hacia afuera
freq = 1

#Inicializar la variable de la altura
altura = 0
 
 
#Llenar el array de elevacion
for y in range(alto):
    for x in range(ancho):
        #Dividir la posicion por la altura
        nx = 2*x/ancho
        ny = 2*y/alto
 
        #Generar el valor de la posicion actual
        mapa_altura[y][x] = gen_altura.noise2d(freq*nx, freq*ny) + 0.5 * gen_altura.noise2d(4*freq*nx, 4*freq*ny)+0.25 * gen_altura.noise2d(8*freq*nx, 8*freq*ny)
 
        #La humedad la escalaremos para que el rango vaya de 0 a 1 en vez de -1 a 1
        mapa_humedad[y][x] = (gen_humedad.noise2d(freq*nx, freq*ny) + 0.5 * gen_humedad.noise2d(4*freq*nx, 4*freq*ny)+0.25 * gen_humedad.noise2d(8*freq*nx, 8*freq*ny))/2.0+0.5
 
 
#Dibujar el mapa
for j in range(len(mapa_altura)):
    for i in range(len(mapa_altura[j])):
         
        #Mar - Azul oscuro
        if mapa_altura[j][i] < 0:
            newobject = scene.addObject('Mar', 'Mar')
            altura = 0
 
        #Elevacion baja
        elif mapa_altura[j][i] < 0.25: 
            if mapa_humedad[j][i] > 0.5:
                newobject = scene.addObject('Bosque_tropical', 'Bosque_tropical')
            elif mapa_humedad[j][i] > 0.25:
                newobject = scene.addObject('Praderia', 'Praderia')
            else:
                newobject = scene.addObject('Desierto_tropical', 'Desierto_tropical')
            altura = 0
 
        #Elevacion media
        elif mapa_altura[j][i] < 0.5: 
            if mapa_humedad[j][i] > 0.55:
                newobject = scene.addObject('Bosque_templado', 'Bosque_templado')
            elif mapa_humedad[j][i] > 0.25:
                newobject = scene.addObject('Praderia_templada', 'Praderia_templada')
            else:
                newobject = scene.addObject('Desierto_templado', 'Desierto_templado')
            altura = 0.4
 
        #Elevacion alta
        elif mapa_altura[j][i] < 0.75: 
            if mapa_humedad[j][i] > 0.66:
                newobject = scene.addObject('Taiga', 'Taiga')
            elif mapa_humedad[j][i] > 0.33:
                newobject = scene.addObject('Matorrales', 'Matorrales')
            else:
                newobject = scene.addObject('Desierto_frio', 'Desierto_frio')
            altura = 0.8
 
        #Elevacion muy alta - a partir de aquí solo creamos nieve
        else:
            newobject = scene.addObject('Nieve')
            altura = 1.2

        #Se coloca el bloque de terreno en la escena 3D
        newobject.worldPosition = [i*2,j*2,altura]

Para que el script pueda funcionar, habrá que asociarlo a algún objeto de la escena 3D. Lo asociaremos a un empty que vamos a crear en la capa princpial. Con el ratón sobre la vista 3D, pulsad Ctrl+A → Empty → Plain Axes. Esto creará un objeto vacío encima del puntero 3D.

Ahora, seleccionad este Empty que habéis creado y en el Logic Editor añadid un sensor de tipo Always y un controlador de tipo Python, y conectadlos. En el controlador, elegid “terrain.py” de la lista de scripts.

 

Por último, no os olvidéis de cambiar el motor de “Blender Render” a “Blender Game”.

 

Con el ratón encima de la Vista 3D pulsad ‘P‘. Si habéis seguido bien todos los pasos debería generarse el mapa aleatorio con los bloques de terreno. Con las teclas WASD podéis desplazaros por el escenario (siempre que el juego se haya iniciado desde la vista de la cámara).

¡Y esto es todo por hoy! Como siempre, si tenéis alguna duda sobre el proceso o hay algo que no funciona, podéis dejarme un comentario y contestaré en cuánto tenga un momento.

¡Hasta pronto! 😉

Gl4r3

Brillante, luminosa y cegadora a veces, Glare es tan artista como técnica. Le encanta dar rienda suelta a sus módulos de imaginación y desdibujar los ya de por si delgados límites que separan el mundo de la electrónica y el arte. Su mayor creación hasta la fecha es un instrumento capaz de convertir los colores y la luz en música. Cuándo sus circuitos no están trabajando en una nueva obra electrónica, le gusta dedicar sus ciclos a la lectura o a documentar sus invenciones para beneficio de los humanos. Sus artilugios favoritos son aquellos que combinan una funcionalidad práctica con un diseño elegante y artístico.

Deja un comentario

avatar