Posso ottenere un effetto fiaccolata (area più chiara attorno a una sorgente luminosa) in un gioco 2D?


16

Sto pensando di scrivere un semplice gioco 2D. All'inizio non brillerà con una grafica o un gameplay perfetti, ma lo considererei il mio primo passo nello sviluppo di giochi per PC. Quindi, immagina un gioco 2D basato su sprite (come Heroes IV o Startcraft BroodWar).

Voglio che il gameplay supporti giorno / notte con i relativi cambiamenti di illuminazione e allo stesso tempo sarà una follia dover creare sprite per ogni sfumatura di illuminazione. Quindi, ho deciso di aggiungere uno strato semitrasparente sopra altri oggetti.

Il problema con questa soluzione è se ho un oggetto sorgente di luce nel gioco (come l'eroe che indossa una torcia o un edificio in fiamme), deve esserci un'area più chiara intorno, giusto? Dal momento che sto mettendo il mio strato semitrasparente su tutto, come suggeriresti di ottenere l'effetto visivo torcia che desidero? Forse ridisegnare quel livello aggiungendo 'spazi vuoti' o aree di colore diverso in base all'effetto di illuminazione?


2
La maschera potrebbe essere la strada da percorrere
Gustavo Maciel,

5
"Torchlight" nel titolo può essere fonte di confusione a causa del gioco chiamato Torchlight.
Tetrad

4
@Tetrad Dovrebbe essere ok fintanto che non è in maiuscolo. Quanto a me, Torchlight non mi è venuto in mente fino a quando non hai letto il tuo commento.
famosogarkin

Tuttavia, ho suggerito una modifica per rendere il titolo più specifico.
famosogarkin

Risposte:


12

Non so in cosa stai programmando, ma è così che l'ho gestito in XNA:

  1. Alla chiamata di disegno, un List<Light>oggetto viene creato / cancellato.
  2. Durante il loop di disegno delle tessere, ogni tessera viene controllata per vedere se ha delle Luci associate. In tal caso, gli Lightoggetti vengono aggiunti a List<Light>.
  3. Le tessere sono disegnate da sole RenderTarget2D.
  4. Dopo il loop di tile, l'elenco di Lights viene ripetuto e disegnato da solo RenderTarget2Dutilizzando una trama creata in questo modo:
    Texture leggera(Nota: ho usato i valori R, G e B qui ma probabilmente dovresti usare il canale alfa nel tuo trama reale.)
  5. Usando uno shader personalizzato, eseguo il rendering della superficie della piastrella sullo schermo e passo la superficie dell'illuminazione come parametro che viene campionato per il valore di "oscurità" in ciascun pixel.


Ora, ci sono alcune cose da notare:

Per quanto riguarda il punto 4:

In realtà ho due shader personalizzati, uno per disegnare le luci sul target del rendering dell'illuminazione (passaggio 4) e un altro per disegnare il target del rendering delle piastrelle sullo schermo utilizzando il target del rendering dell'illuminazione (passaggio 5).
Lo shader utilizzato al punto 4 mi consente di aggiungere (quello che chiamo) un valore di "luminosità". Questo valore è un valore floatche viene moltiplicato per ogni pixel della trama prima che venga aggiunto al target di rendering in modo che io possa essenzialmente rendere le luci più chiare o più scure.
A questo punto, prendo in considerazione anche il valore di "scala" della luce, il che significa che posso avere luci grandi o piccole usando solo una trama.

Per quanto riguarda il punto 5:

Pensa al target del rendering dell'illuminazione essenzialmente come se avesse un valore per ogni pixel da 0 (nero) a 1 (bianco). Lo shader essenzialmente moltiplica quel valore rispetto ai valori RGB per un pixel nella destinazione di rendering delle tessere per creare l'immagine finale disegnata.

Ho anche un altro codice qui dove passo (allo shader) un valore da usare come colore di sovrapposizione giorno / notte. Questo viene anche moltiplicato nei valori RGB e incluso nei calcoli del target di rendering dell'illuminazione.


Ora, questo non ti consentirà di fare cose come bloccare la luce attorno agli oggetti e quant'altro, ma, almeno per i miei scopi, è semplice e funziona bene.

Ho scritto post di blog più dettagliati qui e qui che potrebbero aiutarti. Non ho tempo in questo momento, ma se vuoi posso approfondire qui su gamedev.

Oh, ed ecco uno sguardo nel mio editor di mappe:inserisci qui la descrizione dell'immagine


Generare e cancellare un elenco ogni frame potrebbe non essere troppo costoso?
Gustavo Maciel,

@Gtoknu Non fa alcuna differenza evidente nel mio gioco. L'elenco contiene solo riferimenti a oggetti già esistenti nella memoria, quindi non è come se ogni luce venisse ricreata o altro, solo un elenco.
Richard Marskell - Drackir,

potresti avere ragione, non del tutto, ma lo sei. Naturalmente, non stai creando oggetti completi, ma stai aggiungendo puntatori ai riferimenti, ancora a basso utilizzo, ma comunque consumando. Stai andando bene, ma penso che potrebbe essere meglio se metti la lista fuori dal metodo draw, dato che fare la logica in aggiornamento è molto più veloce che in draw
Gustavo Maciel

@Gtoknu Certo, puoi dichiarare la lista dove vuoi ma il punto è che le luci sono associate alle tessere. Il Drawmetodo delle tessere è dove scopri se una tessera ha luci o no. Non cerco tutte le tessere disegnate nel Updatemetodo, quindi aggiungerei un sovraccarico per quello. Inoltre, XNA cerca di garantire che Updateverrà chiamato 60 volte al secondo, quindi potrebbe sacrificare le Drawchiamate per questo, il che significa che questo codice verrebbe effettivamente chiamato meno spesso.
Richard Marskell - Drackir,

Detto questo, è un punto controverso perché alla fine ho spostato le luci nelle loro liste basate sul partizionamento spaziale e ho appena disegnato tutte le luci in sezioni che si intersecano con lo schermo. Non ne ho parlato nel mio post per mancanza di tempo, ma è menzionato nel secondo post sul blog che ho collegato.
Richard Marskell - Drackir,

9

Normalmente, l'illuminazione nei giochi 2D viene eseguita con una mappa normale per tutti i tuoi sprite, quindi calcola gli effetti di illuminazione 3D sui tuoi sprite 2D. Questo è noto come "2.5D". Vorrei però non consiglierei di fare questo nel vostro primo gioco in quanto è complesso.

Ecco un fantastico video di qualcuno che lo ha fatto in XNA: http://www.youtube.com/watch?v=-Q6ISVaM5Ww

Detto questo, ci sono probabilmente modi per imbrogliare e ottenere un sistema di pseudo-illuminazione che potrebbe funzionare con varie ipotesi.


Ho già visto questo video prima, +1 per aver menzionato una tecnica così incredibile.
Gustavo Maciel,

Grazie per il consiglio e il collegamento video. In effetti una mappa sembra essere una soluzione. Io stesso tenterei di usare la mappa sul mio livello superiore per creare un "gap" o per cambiare l'effetto che ha sugli oggetti sottostanti.
Ivaylo Slavov il

5

È difficile suggerire un approccio se non sei completamente specifico sull'effetto che stai cercando di ottenere. Dettagli come se le luci dovessero essere ostruite dall'ambiente o meno, qual è il punto di vista del gioco, in che misura la luce dovrebbe interagire con l'ambiente, ecc.

Lascerò i miei due centesimi però. Scopri se questo tutorial di Catalin Zima intitolato Dynamic 2D Shadows si adatta al tuo conto. Come puoi vedere, la luce ha un raggio e non attraversa ostacoli. Potresti animare un po 'il raggio e il colore per farlo sembrare più vicino a una vera torcia.

inserisci qui la descrizione dell'immagine

In questo caso, la luce agisce come una sorta di sovrapposizione sulla parte superiore della scena, ma non interagisce con essa nella stessa misura dell'esempio di John, sebbene tenga conto degli ostacoli.

modificare

Catalin si collega a un altro articolo che ha usato come riferimento, ma il collegamento è interrotto. Ecco un link aggiornato .


Grazie, penso che questo non sia l'effetto che sto cercando, ma ancora grazie per averlo condiviso :)
Ivaylo Slavov
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.