¿Cómo implemento la iluminación ocluida en un juego 2D basado en bloques?

11

Quiero tener iluminación 2D que pueda ser bloqueada por objetos en el juego. Mi juego tiene una vista de arriba hacia abajo y todos los objetos del juego se describen mediante rectángulos.

Digamos que tengo un mundo de 10x10 y pongo una luz en 1x1 y paredes alrededor de esa luz. Quiero poder ver la fuente de luz en 1x1, pero no en ningún otro lugar, porque está bloqueada por las paredes.

He oído hablar de cómo funcionan los rayos de luz, pero ¿cómo funciona realmente?

LiquidFeline
fuente
1
Me gustaría ver algunas respuestas agnósticas del lenguaje a esta pregunta.
Dashto
2
@Dashto: ¿Necesita un código funcional en el idioma que usa? Ese es un lugar equivocado para pedir ..
Kromster
Que has intentado Cuando dices "en cualquier otro lugar para no tener una fuente de luz", ¿qué quieres decir? Solo iluminé tu bloque 1,1 y eso es todo. Tal vez no entiendo tu pregunta, ¿podrías publicar una ilustración?
Laurent Couvidou
1
@Krom Stern: en realidad estoy pidiendo exactamente lo contrario: una respuesta conceptual que no depende del lenguaje. Los dos hilos vinculados como duplicados no hablan mucho de los conceptos. De hecho, la mayoría de las preguntas similares en este sitio simplemente tienen respuestas que dicen "¡Usa esta biblioteca!" lo cual es menos útil para alguien que quiere entender cómo funciona.
Dashto
@Dashto: Esa es información importante, debe agregarla a la pregunta;)
Kromster

Respuestas:

13

Amit Patel ha escrito un artículo muy bueno sobre el casting de rayos 2D.

Esto implica lanzar rayos a cada uno de los vértices dentro del rango de la fuente de luz para construir una malla de luz.

ingrese la descripción de la imagen aquí

Todos los ejemplos visuales son interactivos en la publicación y muy fáciles de entender.

Tampoco tiene que limitarse a una caja, el perímetro que traza puede tener la forma que desee.

MichaelHouse
fuente
1

Debe usar el algoritmo de emisión de rayos, lo que significa que debe poder calcular la intersección del rayo (media línea) con cualquier objeto en su escena (líneas, cuadrados, círculos, triángulos ...) y elegir la intersección más cercana. Lanzas el rayo en todas las direcciones y luego "dibujas la luz" solo al objeto más cercano.

Así es como puede verse .

Ivan Kuckir
fuente
Solo pregunté cómo usaría el casting de rayos. Sé al respecto.
LiquidFeline
0

Si sabes lo que es la emisión de rayos, entonces todo lo que necesitas hacer es codificarlo. No es demasiado complejo siempre que tenga coordenadas para cada vértice.

Primero, crea un objeto que emana luz. Coloque su luz en las coordenadas x, y.

#include <math.h>
int i = 0;
if ( sqrt( abs( light.x - vertex.x )^2 + abs( light.y - vertex.y )^2 ) <= light.radius)
{
    lightOccludingVertices[i] = vertex;
    i++;
}

//If two or more vertices are both a member of an individual wall,
//illuminate the triangular area between the light, the furthest 
//vertex on the x-axis, and the furthest vertex on the y-axis

No se garantiza que funcione para un polígono cóncavo, pero debería funcionar bien para cualquier polígono convexo.

Esto funcionará si sus objetos ocultos (paredes, personajes, comedores de personas que vuelan de color púrpura) se pintan en la pantalla después de aplicar la iluminación. De lo contrario, la mitad de una pared aparecerá significativamente más brillante que la otra mitad. Si su punto de luz es equidistante de dos pares de vértices de la misma pared (exactamente la mitad de la altura de su pared), aplique el triángulo a los dos vértices más cercanos, en lugar de los dos más alejados.

También debo mencionar que este método requiere un punto de vértice creado dinámicamente donde el borde del radio de la luz se encuentra con la superficie del objeto oclusivo. Esto crea un mínimo de 3 vértices para cualquier objeto oclusivo y permitirá que las paredes que se extiendan más allá del radio de la luz (o fuera de la pantalla) también bloqueen cualquier luz.

Más información sobre polígonos cóncavos y convexos.

igrad
fuente