Ejercicio 2: Generación infinita en videojuegos #
1. Introducción
El Ruido Perlin es una función matemática que utiliza la interpolación entre un gran número de gradientes de vectores precalculados para crear un valor que varía de forma pseudoaleatoria en el espacio o en el tiempo. Se asemeja al ruido blanco y se utiliza con frecuencia en imágenes generadas por ordenador para simular la variabilidad de muchos tipos de fenómenos, dándoles un aspecto más realista.
Perlin Noise es un método matemático para generar fluctuaciones aleatorias pero muy contiguas, por lo que, a diferencia de cualquier tipo de función aleatoria, es una manera muy apta para generar terrenos aleatorios que, aunque aleatorios, requieren una forma coherente.
Lee más sobre el Ruido Perlin y otros métodos de generación de terreno aleatorio en: https://medium.com/nerd-for-tech/generating-digital-worlds-using-perlin-noise-5d11237c29e9
2. Solución
En los videojuegos y ambientes virtuales se suele procurar optimizar los recursos de la maquina para dar una mejor experiencia al usuario. Una forma de realizar esto es haciendo uso de la renderización parcial: Esto evita que la máquina se cargue con trabajo que de todos modos no será visible para el usuario.
En esta solución se propone la generacion aleatoria de terreno para un simulador de vuelo simple.
Código
var cols, rows; // variables para almacenar el número de columnas y filas en el mapa de ruido
var scl = 20; // escala para el tamaño de los bloques de ruido
var w = 1400; // ancho del mapa de ruido
var h = 1000; // altura del mapa de ruido
var flying = 0; // variable para almacenar el valor del desplazamiento vertical del mapa de ruido
var terrain = []; // arreglo vacío que almacenará el valor del mapa de ruido en cada posición
function preload(){
airplane = loadModel('/showcase/sketches/terrain/airplane.obj'); // precargar el modelo del avión
}
function setup() {
createCanvas(800, 800, WEBGL); // crear un canvas en modo WEBGL
cols = w / scl; // calcular el número de columnas del mapa de ruido
rows = h / scl; // calcular el número de filas del mapa de ruido
slider = createSlider(-300,300,0,1); // crear un slider para desplazar la cámara
slider.position(10,10); // colocar el slider en la esquina superior izquierda
camera = createCamera(); // crear una cámara para la escena
for (var x = 0; x < cols; x++) {
terrain[x] = [];
for (var y = 0; y < rows; y++) {
terrain[x][y] = 0; // inicializar el valor del mapa de ruido en cada posición con cero
}
}
}
function draw() {
flying -= 0.1; // decrementar el valor del desplazamiento vertical del mapa de ruido
var yoff = flying; // almacenar el valor actual del desplazamiento vertical del mapa de ruido
for (var y = 0; y < rows; y++) {
var xoff = 10;
for (var x = 0; x < cols; x++) {
terrain[x][y] = map(noise(xoff, yoff), 0, 1, -200, 55); // mapear el valor del ruido a un valor entre -200 y 55
xoff += 0.2;
}
yoff += 0.2;
}
background(0); // definir un fondo negro para la escena
translate(0, 50); // trasladar el sistema de coordenadas hacia abajo para mostrar la escena completa
rotateX(PI / 3); // rotar la escena alrededor del eje X para mostrar la vista desde arriba
let sld=slider.value(); // almacenar el valor actual del slider
camera.camera(230,400,600,200,100,200,0,1,0); // definir la posición inicial de la cámara
camera.setPosition(sld,400,600); // actualizar la posición de la cámara con el valor del slider
push();
scale(0.03); // escalar el modelo del avión
fill(0,0,0,150); // definir un color negro semitransparente para el modelo del avión
rotateZ(55); // rotar el modelo del avión alrededor del eje Z
model(airplane, true);
pop();
fill(200, 200, 200, 150);
translate(-w / 2, -h / 2);
for (var y = 0; y < rows - 1; y++) {
noStroke();
beginShape(TRIANGLE_STRIP);
for (var x = 0; x < cols; x++) {
fill(100,0,255,150)
vertex(x * scl, y * scl, terrain[x][y]);
vertex(x * scl, (y + 1) * scl, terrain[x][y + 1]);
}
endShape();
}
}
El avión se incuye como un archivo .OBJ, que es un estándar para representar diseños en 3D a partir de sus coordenadas.
El usuario jwdunn1 propone la generación de un mundo inspirado en el popular videojuego Minecraft haciendo uso del ruido Perlin:
3. Conclusión
El ruido Perlin brinda un patron tan impredecible como la naturaleza misma, lo cual puede ser aprovechado para hacer creer a nuestras mentes que estamos viendo paisajes naturales en los que incluso podemos crear una falsa sensación de movimiento.