¿Puedo lograr un efecto de antorcha (área más clara alrededor de una fuente de luz) en un juego 2D?

16

Estoy pensando en escribirme un simple juego 2D. Al principio no brillará con gráficos o jugabilidad perfectos, pero lo consideraría mi primer paso en el desarrollo de juegos de PC. Entonces, imagina un juego 2D tan simple basado en sprites (como Heroes IV o Startcraft BroodWar).

Quiero que el juego sea compatible día / noche con los cambios de iluminación correspondientes y, al mismo tiempo, será una locura tener que crear sprites para cada matiz de iluminación. Entonces, decidí que agregar una capa semitransparente encima de otros objetos será suficiente.

El problema con esta solución es que si tengo un objeto fuente de luz en el juego (como el héroe que lleva una antorcha o un edificio en llamas), debe haber un área más clara a su alrededor, ¿verdad? Como estoy poniendo mi capa semitransparente sobre todo, ¿cómo sugeriría lograr el efecto visual de antorcha que quiero? ¿Quizás vuelva a dibujar esa capa agregando 'huecos' o áreas de diferentes colores según el efecto de iluminación?

Ivaylo Slavov
fuente
2
La máscara puede ser el camino a seguir
Gustavo Maciel el
55
"Torchlight" en el título puede ser confuso debido al juego llamado Torchlight.
Tetrad
44
@Tetrad Debería estar bien siempre que no esté en mayúscula. En cuanto a mí, Torchlight no vino a mi mente hasta que leí tu comentario.
famousgarkin
No obstante, sugerí una edición para que el título sea más específico.
famousgarkin
2
posible duplicado de ¿Cómo se implementa la iluminación 2D?
bummzack

Respuestas:

12

No sé en qué estás programando, pero así es como lo manejé en XNA:

  1. En la llamada de sorteo, List<Light>se crea / borra un objeto.
  2. Durante el ciclo de extracción de fichas, cada ficha se verifica para ver si tiene luces asociadas. Si lo hace, los Lightobjetos se agregan a la List<Light>.
  3. Los azulejos se dibujan por su cuenta RenderTarget2D.
  4. Después del bucle de mosaico, la lista de Lights se repite y se dibuja por sí misma RenderTarget2Dusando una textura que hice que se ve así:
    Textura ligera(Nota: Usé los valores R, G y B aquí, pero probablemente debería usar el canal alfa en su textura real.)
  5. Utilizando un sombreador personalizado, renderizo la superficie de mosaico en la pantalla y paso la superficie de iluminación como un parámetro que se muestrea para el valor de "oscuridad" en cada píxel.


Ahora, hay algunas cosas a tener en cuenta:

Con respecto al punto 4:

De hecho, tengo dos sombreadores personalizados, uno para dibujar las luces hacia el objetivo de representación de iluminación (paso 4) y otro para dibujar el objetivo de representación de mosaico en la pantalla utilizando el objetivo de representación de iluminación (paso 5).
El sombreador utilizado en el punto 4 me permite agregar (lo que llamo) un valor de "luminosidad". Este valor se floatmultiplica por cada píxel en la textura antes de agregarlo al objetivo de renderizado, de modo que esencialmente puedo hacer que las luces sean más brillantes o más oscuras.
En este punto, también tengo en cuenta el valor de "escala" de la luz, lo que significa que puedo tener luces grandes o pequeñas usando solo una textura.

Con respecto al punto 5:

Piense en el objetivo de renderizado de iluminación como esencialmente un valor para cada píxel de 0 (negro) a 1 (blanco). El sombreador esencialmente multiplica ese valor contra los valores RGB para un píxel en el objetivo de representación de mosaico para hacer la imagen dibujada final.

También tengo más código aquí donde paso (al sombreador) un valor para usar como color de superposición de día / noche. Esto también se multiplica en los valores RGB y se incluye en los cálculos del objetivo de renderizado de iluminación.


Ahora, esto no le permitirá hacer cosas como impedir que la luz pase alrededor de objetos y otras cosas, pero, al menos para mis propósitos, es simple y funciona bien.

He escrito publicaciones de blog más detalladas aquí y aquí que pueden ayudarte. No tengo tiempo en este momento, pero si quieres puedo entrar en más detalles aquí en gamedev.

Ah, y he aquí un vistazo en mi editor de mapas:ingrese la descripción de la imagen aquí

Richard Marskell - Drackir
fuente
¿Generar y borrar una lista cada cuadro puede no ser demasiado costoso?
Gustavo Maciel
@Gtoknu no hace ninguna diferencia notable en mi juego. La lista solo contiene referencias a objetos que ya existen en la memoria, por lo que no es como si se recrearan todas las luces ni nada, solo una lista.
Richard Marskell - Drackir el
Puede que tengas razón, no totalmente, pero lo estás. Por supuesto, no está creando objetos completos, sino que está agregando punteros a las referencias, todavía es de bajo uso, pero sigue consumiendo. Lo estás haciendo bien, pero creo que podría ser mejor si colocas la lista fuera del método de sorteo, ya que hacer la lógica en la actualización es mucho más rápido que en el sorteo
Gustavo Maciel
@Gtoknu Claro, puedes declarar la lista donde quieras, pero el punto es que las luces están asociadas con los mosaicos. El Drawmétodo de mosaico es donde averigua si un mosaico tiene luces o no. No recorro todos los mosaicos dibujados en el Updatemétodo, por lo que agregaría una sobrecarga adicional para eso. Además, XNA intenta garantizar que Updatese llamará 60 veces por segundo, por lo que puede sacrificar Drawllamadas por esto, lo que significa que este código en realidad se llamaría con menos frecuencia.
Richard Marskell - Drackir
Dicho todo esto, es un punto discutible porque eventualmente moví las luces a sus propias listas basadas en particiones espaciales y simplemente dibujé todas las luces en secciones que se cruzan con la pantalla. No hablé de eso en mi publicación por falta de tiempo, pero se menciona en la segunda publicación del blog que vinculé.
Richard Marskell - Drackir
9

Normalmente, la iluminación en los juegos 2D se realiza al tener un Mapa Normal para todos tus sprites, luego calcula los efectos de iluminación 3D en tus sprites 2D. Esto se conoce libremente como "2.5D". Sin embargo, no recomendaría hacer esto en tu primer juego, ya que es complejo.

Aquí hay un video increíble de alguien que ha hecho esto en XNA: http://www.youtube.com/watch?v=-Q6ISVaM5Ww

Dicho esto, probablemente hay formas de hacer trampa y obtener un sistema de pseudo-iluminación que podría funcionar con varios supuestos.

John McDonald
fuente
Ya vi este video antes, +1 por mencionar una técnica tan increíble.
Gustavo Maciel
Gracias por el consejo y el enlace del video. De hecho, un mapa parece ser una solución. Yo mismo trataría de usar el mapa en mi capa superior para crear una 'brecha' o para cambiar el efecto que tiene sobre los objetos subyacentes.
Ivaylo Slavov
5

Es difícil sugerir un enfoque si no eres completamente específico sobre el efecto que estás tratando de lograr. Detalles como si las luces deben estar obstruidas por el entorno o no, cuál es el punto de vista de su juego, en qué medida la luz debe interactuar con el entorno, etc.

Aunque dejaré caer mis dos centavos. Vea si este tutorial de Catalin Zima titulado Dynamic 2D Shadows se ajusta a su factura. Como puede ver, la luz tiene un radio y no atraviesa obstáculos. Puedes animar un poco el radio y el color para que se vea más cerca de una luz de antorcha real.

ingrese la descripción de la imagen aquí

En este caso, la luz actúa como una especie de superposición en la parte superior de la escena, pero no interactúa con ella en la misma medida que en el ejemplo de John, aunque tiene en cuenta los obstáculos.

Editar

Catalin enlaza con otro artículo que utilizó como referencia, pero el enlace está roto. Aquí hay un enlace actualizado .

David Gouveia
fuente
Gracias, creo que este no es el efecto que busco, pero aún así gracias por compartir :)
Ivaylo Slavov