Come posso implementare l'illuminazione occlusa in un gioco 2D basato su blocchi?


11

Voglio avere un'illuminazione 2D che può essere bloccata da oggetti di gioco. Il mio gioco ha una vista dall'alto e tutti gli oggetti del gioco sono descritti da rettangoli.

Diciamo che ho un mondo 10x10 e posiziono una luce su 1x1 e le pareti attorno a quella luce. Voglio poter vedere la sorgente luminosa su 1x1, ma non altrove, perché è bloccata dalle pareti.

Ho sentito parlare della fusione dei raggi luminosi, ma come funziona davvero?


1
Vorrei vedere alcune risposte agnostiche al linguaggio a questa domanda.
Dashto,

2
@Dashto: hai bisogno di un pezzo di codice funzionante nella lingua che usi? È un posto sbagliato per chiedere ..
Kromster,

Che cosa hai provato? Quando dici "altrove per non avere una fonte di luce", cosa intendi? Ti ho appena illuminato 1,1 blocchi e basta. Forse non capisco la tua domanda, potresti pubblicare un'illustrazione?
Laurent Couvidou,

1
@Krom Stern: in realtà sto chiedendo l'esatto contrario: una risposta concettuale che non dipende dal linguaggio. I due thread collegati come duplicati non parlano molto dei concetti. In effetti la maggior parte delle domande simili su questo sito hanno semplicemente risposte che dicono "Usa questa libreria!" che è meno utile per qualcuno che vuole capire come funziona.
Dashto,

@Dashto: Questa è un'informazione importante, dovresti aggiungerla alla domanda;)
Kromster,

Risposte:


13

Amit Patel ha scritto un bellissimo articolo sul ray casting 2D.

Ciò comporta il lancio di raggi su ciascuno dei vertici all'interno della gamma della sorgente luminosa per creare una maglia leggera.

inserisci qui la descrizione dell'immagine

Tutti gli esempi visivi sono interattivi nel post e molto facili da capire.

Non devi limitarti a una scatola, il perimetro che traccia può avere qualsiasi forma ti piaccia.


1

Dovresti usare l'algoritmo di raycasting , il che significa che dovresti essere in grado di calcolare l'intersezione del raggio (mezza linea) con qualsiasi oggetto nella tua scena (linee, quadrati, cerchi, triangoli ....) e scegliere l'intersezione più vicina. Lanci il raggio in tutte le direzioni e poi "attiri la luce" solo sull'oggetto più vicino.

Ecco come potrebbe apparire .


Ho appena chiesto come avrei usato il ray casting. Lo so.
LiquidFeline

0

Se sai cos'è il ray casting, tutto ciò che devi fare è codificarlo. Non è eccessivamente complesso fintanto che hai le coordinate per ciascun vertice.

Innanzitutto, crea un oggetto che emana luce. Posiziona la tua luce sulle coordinate 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

Questo non è garantito per funzionare con un poligono concavo, ma dovrebbe funzionare perfettamente con qualsiasi poligono convesso.

Funzionerà se i tuoi oggetti occludenti (muri, personaggi, persone che volano viola) vengono dipinti sullo schermo dopo aver applicato l'illuminazione. Altrimenti, metà di un muro apparirà significativamente più luminosa dell'altra metà. Se la tua luce di punto è equidistante da due coppie di vertici della stessa parete (esattamente la metà dell'altezza della tua parete), applica il triangolo ai due vertici più vicini, anziché ai due più lontani.

Dovrei anche menzionare che questo metodo richiede un punto di vertice creato dinamicamente in cui il bordo del raggio della luce incontra la superficie dell'oggetto occludente. Questo crea un minimo di 3 vertici per ogni oggetto occludente e consentirà alle pareti che si estendono oltre il raggio della luce (o fuori dallo schermo) di bloccare anche qualsiasi luce.

Ulteriori informazioni sui poligoni concavi e convessi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.