XNA Sprite Flash Effect


8

Sto cercando un modo per rendere ogni pixel non trasparente in uno sprite bianco solido (per "far lampeggiare" lo sprite bianco quando il giocatore subisce danni, ecc.). Questo è su Windows Phone 7.

Stavo usando uno shader personalizzato molto semplice per farlo in XNA 3.1, ma WP7 non li supporta e trovando difficile provare un'alternativa.

Gradirei qualsiasi aiuto o suggerimento. Preferirei non dover creare manualmente una solida copia bianca di ogni sprite nel mio gioco.


1
Okay, ho trovato un modo, ma non è carino. Lasciami ripulire un po 'e aggiornerò la mia risposta.
David Gouveia,

Risposte:


9

Metodo 1

Non è necessario creare manualmente una versione bianca completa di ogni sprite nel gioco : è possibile anche automatizzare il processo al momento del caricamento. In altre parole, è possibile utilizzare Texture2D.GetData()per accedere ai pixel della trama (e recuperarli come semplici Color[]), scorrere su di essi sostituendo qualsiasi pixel non trasparente con bianco solido, quindi salvarlo su una nuova trama utilizzando e Texture2D.SetData().

Metodo 2

Ho provato a giocare con BlendStatema non sono riuscito a trovare un modo per renderlo tutto bianco, almeno non entro i limiti del profilo Reach. Ma se qualcuno conosce un modo fammelo sapere. Quello che ho trovato, tuttavia, è stato un modo per farlo usando lo stencil buffer e la AlphaTestEffectclasse integrata . L'idea è la seguente:

  1. Creare un backbuffer che ha un buffer di stencil.
  2. Cancella lo stencil buffer a zero.
  3. Disegna gli sprite che desideri tingere di bianco e ogni volta che superano il test alfa, imposta il buffer dello stencil in quella posizione su 1.
  4. Disegna un quadratino bianco che copre l'intero schermo, ma solo dove il valore del buffer di stencil è 1.

Ecco il codice che ho usato:

(Passaggio 1) Assicurarsi innanzitutto che il backbuffer venga creato con spazio per un buffer di stencil:

graphics = new GraphicsDeviceManager(this) { PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8 };

(Passaggio 2) Crea una texture bianca 1x1 che verrà ridimensionata per riempire l'intero schermo:

private Texture2D pixel;
pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new[] { Color.White });

(Passaggio 3) E ora la parte difficile: renderizzarla. Bene, non proprio difficile, ma richiede due DepthStencilStateoggetti e un AlphaTestEffectoggetto. Dovresti crearli solo una volta.

// Clear stencil buffer
GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0f, 0);

// Prepare the alpha test effect object (create it only once on initilization)
AlphaTestEffect alphaTestEffect = new AlphaTestEffect(GraphicsDevice)
{
    DiffuseColor = Color.White.ToVector3(), 
    AlphaFunction = CompareFunction.Greater, 
    ReferenceAlpha = 0, World = Matrix.Identity, 
    View = Matrix.Identity, 
    Projection = Matrix.CreateTranslation(-0.5f, -0.5f, 0) * 
    Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1)
};

// Prepare the first DepthStencilState (create only once, or put it in a static class)
DepthStencilState beforeDepthStencilState = new DepthStencilState
{
    StencilEnable = true, 
    StencilFunction = CompareFunction.Always,
    StencilPass = StencilOperation.Replace, 
    ReferenceStencil = 1
};

// Draw your sprites using the structures above
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, beforeDepthStencilState, null, alphaTestEffect);
spriteBatch.Draw(sprite, new Vector2(300, 150), Color.White);
spriteBatch.End();

// Prepare the second DepthStencilState (create only once, or put it in a static class)
DepthStencilState afterDepthStencilState = new DepthStencilState
{
    StencilEnable = true, 
    StencilFunction = CompareFunction.Equal, 
    ReferenceStencil = 1
};

// Draw a full screen white quad with the structure above
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, afterDepthStencilState, null);
spriteBatch.Draw(pixel, GraphicsDevice.Viewport.Bounds, Color.White);
spriteBatch.End();

E il risultato:

inserisci qui la descrizione dell'immagine


Sorprendente! Grazie mille per aver dedicato così tanto impegno a questo, David. Peccato che non ci sia una soluzione più semplice, ma questo dovrebbe fare bene il trucco.
Ryan McD
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.