Prefiero lanzar rayos de sombra en lugar de rayos de línea de visión.
Digamos que esta es su área de visualización (el área potencialmente visible)
######################
#####.............####
###................###
##..................##
#....................#
#....................#
#..........@.........#
#....................#
#....................#
##..................##
###................###
#####.............####
######################
Los # bloques no son visibles mientras que. son visibles
Pongamos un obstáculo X:
######################
#####.............####
###................###
##.....X.....XXX....##
#......X.......X.....#
#...X.XX.............#
#...X......@.........#
#...X..........X.....#
#...XXXXXX...........#
##..................##
###....X...........###
#####.............####
######################
Tiene una lista de las X que se encuentran dentro del área de visualización y luego marca como ocultas cada mosaico que está detrás de cada uno de estos obstáculos: cuando un obstáculo se marca como oculto, lo elimina de la lista.
######################
#####.............####
###................###
##.....X.....XXX....##
#......X.......X.....#
#...X.XX.............#
#...X......@.........#
#...X..........X.....#
#...XXXXX*...........#
##......##..........##
###....*#..........###
#####.###.........####
######################
En el ejemplo anterior, puede ver la sombra proyectada en el extremo derecho de la pared inferior y cómo esta sombra elimina el obstáculo oculto de la lista del obstáculo que debe verificar (X debe verificar; * marcado).
Si ordena la lista usando alguna partición binaria para que primero se verifiquen el costo X, puede acelerar ligeramente su verificación.
Puede usar una especie de algoritmo de "Batallas Navales" para verificar el bloque de X a la vez (básicamente buscando una X adyacente que esté en una dirección que pueda ensanchar el cono de sombra)
[EDITAR]
Se necesitan dos rayos para proyectar correctamente una sombra y, dado que un mosaico es rectangular, se pueden hacer muchas suposiciones utilizando las simetrías disponibles.
Las coordenadas del rayo se pueden calcular utilizando un espacio simple que se divide alrededor del mosaico de obstáculos:
Cada área rectangular constituye una elección sobre qué esquina del mosaico debe tomarse como borde de cono de sombra.
Este razonamiento se puede impulsar aún más para conectar múltiples mosaicos adyacentes y permitirles lanzar un solo cono más ancho de la siguiente manera.
El primer paso es asegurarse de que no haya obstáculos hacia la dirección del observador, en ese caso se considera el obstáculo más cercano:
Si el mosaico amarillo es un obstáculo, ese mosaico se convierte en el nuevo mosaico rojo.
Ahora consideremos el borde del cono superior:
Las fichas azules son todas posibles candidatas para permitir que el cono de sombra se ensanche: si al menos una de ellas es un obstáculo, el rayo se puede mover usando el espacio que se divide alrededor de esa ficha como se vio anteriormente.
El mosaico verde es un candidato solo si el observador está por encima de la línea naranja que sigue:
Lo mismo significa el otro rayo y las otras posiciones del observador sobre el obstáculo rojo.
La idea subyacente es cubrir la mayor cantidad de área posible para cada lanzamiento de cono y acortar lo más rápido posible la lista de obstáculos para verificar.