Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 44 di 53
  • livello principiante
Indice lezioni

Vista in prima persona, in terza persona e proiezioni ortogonali

Gestire la visualizzazione delle telecamere e ottenere effetti di isometria
Gestire la visualizzazione delle telecamere e ottenere effetti di isometria
Link copiato negli appunti

Imparare a gestire la matrice View è fondamentale per realizzare telecamere in prima o terza persona in grado di reagire correttamente agli input degli utenti (approfondiamo questo argomento più avanti, quando parliamo di telecamera).

A questo proposito, tenete presente che una telecamera è in realtà costruita come una trasformazione dei vertici del "mondo". A differenza di una telecamera reale, che può essere fisicamente spostata o ruotata (modificando di conseguenza l'inquadratura), nel nostro caso ciò che viene effettivamente spostato a destra o sinistra, in alto o in basso, ecc., è l'insieme degli oggetti che compongono la scena (cioé il mondo).

In altri termini, se l'osservatore si sposta di un passo a sinistra, ciò che realmente avviene è uno spostamento analogo, ma in direzione opposta, del mondo. In questo modo si crea l'effetto di movimento della telecamera (cioè di ciò che vedete a schermo).

In modo analogo, se ruotiamo la nostra telecamera di 90 gradi verso destra, è in realtá l'intero mondo 3D a ruotare di 90 in senso opposto. Provate a modificare la matrice View come segue, disegnando il resto della scena nello stesso identico modo sopra visto; adesso osserviamo la scena da "due passi a destra":

bfx.View = Matrix.CreateTranslation(-Vector3.Right * 2.0f) * Matrix.CreateRotationY(-1.5f);

Proiezione ortogonale

Un altro caso interessante è rappresentato dalla cosiddetta proiezione isometrica, ossia un tipo di proiezione in cui non si applica la normale prospettiva e in cui gli oggetti mantengono le loro dimensioni invariate a prescindere da quanto siano vicino o lontani dalla telecamera (per approfondimenti sui diversi tipi di proiezioni si può vedere http://www.compuphase.com/axometr.htm#CARTESIO).

Per creare una proiezione ortogonale, XNA mette a disposizione l'apposito metodo Matrix.CreateOrthographicOffCenter:

public static Matrix CreateOrthographicOffCenter (
         float left,
         float right,
         float bottom,
         float top,
         float zNearPlane,
         float zFarPlane
)

Creiamo dunque la nostra matrice di proiezione ortogonale, sostituendola a quella originaria (in grassetto la parte modificata):

bfx.Projection = Matrix.CreateOrthographicOffCenter(-2, 4, -2, 4, 0.1f, 10000.0f);

Se ora provate a lanciare l'applicazione, noterete che la nostra texture continuerà a ruotare intorno all'origine, ma dal momento che non c'è prospettiva, non cambia le sue dimensioni a seconda della distanza dalla telecamera, con il risultato che la nuvola di plasma sembra muoversi solo lateralmente.

Usare un altro effect

Per concludere, proviamo adesso a passare al nostro metodo Spritebatch.Begin un diverso effetto per vedere cosa succede, dal momento che ogni effetto ha un comportamento diverso. Sostituiamo la relativa chiamata con la seguente (in grassetto è evidenziata la differenza):

sprite_batch.Begin(SpriteSortMode.Immediate, BlendState.Additive, SamplerState.LinearWrap, DepthStencilState.None, RasterizerState.CullNone, afx);

Il resto del codice rimane sostanzialmente identico, salvo doversi ricordare di impostare le matrici di trasformazione sull'effetto corrente, altrimenti sarà come non averle impostate affatto. Nel metodo Update aggiungete le seguenti righe:

afx.World = Matrix.CreateBillboard(p, Vector3.Right * 2.0f, Vector3.Up, null);
afx.View = Matrix.CreateTranslation(-Vector3.Right * 2.0f) * Matrix.CreateRotationY(-1.5f);
afx.Projection = Matrix.CreatePerspectiveFieldOfView(1.5f, 4.0f / 3.0f, 0.1f, 10000.0f);

Nel metodo Draw, sostituite l'attuale chiamata con la seguente:

sprite_batch.Draw(ship, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero, new Vector2(1.0f / plasma.Width, 1.0f / plasma.Height), SpriteEffects.None, 0.0f);
sprite_batch.End();

Ti consigliamo anche