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

Il Disegno 'manuale' con XNA

Realizzare oggetti bidimensionali e applicare colori e texture
Realizzare oggetti bidimensionali e applicare colori e texture
Link copiato negli appunti

In questo capitolo vedremo come disegnare oggetti 2D a schermo. Inizieremo dal modo di farlo manuale, per capire quali sono gli attori coinvolti (anche se il processo manuale è decisamente più complicato) e poi vedremo come grazie a XNA e all'oggetto SpriteBatch possiamo realizzare le stesse operazioni con pochissime righe di codice e (quasi) la stessa flessibilitá.

Ora che siamo in grado di creare una applicazione che non fa nulla, chiaramente ci interessa iniziare a disegnare qualcosa sullo schermo. Per fare questo dobbiamo creare una serie di quadrati colorati, componendo tra loro coppie di triangoli.

La geometria in XNA, come in DirectX, è basata sulla creazione di due buffer che contengono i vertici della geometria (Vertex Buffer) e gli indici dei vertici che presi "a tre a tre" ci permettono di ricostruire i triangoli (Index Buffer); un quadrato potrebbe essere costituito come:

Figura 18. Vertex Buffer e Index Buffer
Vertex Buffer e Index Buffer

Usando solo il Vertex Buffer avremmo una ripetizione dei vertici lungo la diagonale. I vertici sono pesanti da memorizzare e, se duplicati, devono essere processati due volte in quanto hanno entries diverse nella cache dei vertici trasformati, anche se sono identici come valori interni, per questo usiamo gli indici. Gli indici possono essere duplicati (sono solo interi) e avremo meno vertici. Man mano che la geometria usata diventa più complessa, il numero di vertici da duplicare aumenta e usare gli indici diventa cruciale.

Proviamo a realizzare una prima operazione di disegno in 2D. Per prima cosa dobbiamo dichiarare un Effect, che si occuperá di disegnare per noi la geometria applicandovi una serie di effetti grafici:

BasicEffect fx;

Impostare le matrici World, View e Projection

Nella LoadContent dobbiamo inizializzare il nostro BasicEffect e impostare le sue matrici World, View e Projection in modo che le coordinate dei vertici siano interpretate come coordinate di pixel (torneremo su World, View e Projection nel capitolo sul 3D):

fx = new BasicEffect(GraphicsDevice);
var viewport = GraphicsDevice.Viewport;
Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);
fx.World = Matrix.Identity;
fx.View = Matrix.Identity;
fx.Projection = halfPixelOffset * projection;

A questo punto attiviamo i colori dei vertici, ossia istruiamo il nostro BasicEffect affinché applichi ai pixel dei nostri triangoli i colori dei vertici:

fx.VertexColorEnabled = true;

Nel metodo Draw, iniziamo attivando il nostro BasicEffect:

fx.CurrentTechnique.Passes[0].Apply();

quindi creiamo vertici e indici:

var vertices = new [] {
    new VertexPositionColor(new Vector3(0, 0, 0.0f),     Color.White),
    new VertexPositionColor(new Vector3(200, 0, 0.0f),   Color.White),
    new VertexPositionColor(new Vector3(0, 200, 0.0f),   Color.White),
    new VertexPositionColor(new Vector3(200, 200, 0.0f), Color.White),
  };
var indices = new short[] {
  0, 1, 2,
  2, 1, 3
};

ed infine li disegniamo con il metodo GraphicsDevice.DrawUserIndexedPrimitives che prende i due array, i range da disegnare e li disegna a schermo:

GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, 4, indices, 0, 2);

Il risultato è molto semplice: un quadrato nell'angolo in alto a destra dello schermo:

Figura 19. Un quadrato
Un quadrato

Possiamo modificare i nostri vertici in modo da avere dei colori dei vertici differenti:

var vertices = new [] {
    new VertexPositionColor(new Vector3(0, 0, 0.0f),     Color.OrangeRed),
    new VertexPositionColor(new Vector3(200, 0, 0.0f),   Color.White),
    new VertexPositionColor(new Vector3(0, 200, 0.0f),   Color.White),
    new VertexPositionColor(new Vector3(200, 200, 0.0f), Color.Green),
  };

e i nostri triangoli assumeranno un colore diverso:

Figura 20. Applicare colori ai vertici
Applicare colori ai vertici

Applicare una texture

Vogliamo peró ottenere qualcosa di un po' più elaborato dei triangoli colorati, possiamo ad esempio applicare un'immagine (Texture) sopra i nostri triangoli, per dare l'apparenza di qualcosa di più ricco di dettagli: una icona, una particella di fumo o un'astronave.

Per applicare una texture su dei vertici, dobbiamo stabilire una corrispondenza tra i vertici e i punti dell'immagine, perciò dovremo indicare, per ciascun vertice, quale pixel dell'immagine andrá disegnato sopra quel vertice, in un range normalizzato [0..1].

Nei punti dei triangoli che non corrispondono ad un vertice (la maggior parte) useremo i pixel intermedi della texture. Specifichiamo il pixel della texture da disegnare su un vertice nel parametro Texture Coordinate del vertice. Per avere a disposizione questo parametro non basta più il semplicissimo tipo di vertice VertexPositionColor che abbiamo usato prima, ma dobbiamo usare VertexPositionColorTexture, un tipo di vertice che contiene più informazioni, comprese le coordinate di texture.

Vediamo come cambia il codice dell'esempio precedente: per prima cosa carichiamo anche una texture nel metodo LoadContent:

asteroid = Content.Load("asteroid1");

poi attiviamo l'uso delle textures nel nostro BasicEffect e impostiamo la texture attiva alla texture dell'asteroide:

fx.TextureEnabled = true;
fx.Texture = asteroid;

infine usiamo il nuovo tipo di vertice e colleghiamo gli angoli della texture ai nostri vertici:

var vertices = new [] {
    new VertexPositionColorTexture(new Vector3(0, 0, 0.0f),     Color.White, new Vector2(0,0)),
    new VertexPositionColorTexture(new Vector3(200, 0, 0.0f),   Color.White, new Vector2(1,0)),
    new VertexPositionColorTexture(new Vector3(0, 200, 0.0f),   Color.White, new Vector2(0,1)),
    new VertexPositionColorTexture(new Vector3(200, 200, 0.0f), Color.White, new Vector2(1,1)),
  };

il risultato è:

Figura 21. La texture applicata ai vertici
La texture applicata ai vertici

Proviamo ora ad aggiungere dei colori ai nostri vertici:

var vertices = new [] {
    new VertexPositionColorTexture(new Vector3(0, 0, 0.0f),     Color.Red, new Vector2(0,0)),
    new VertexPositionColorTexture(new Vector3(200, 0, 0.0f),   Color.Green, new Vector2(1,0)),
    new VertexPositionColorTexture(new Vector3(0, 200, 0.0f),   Color.Blue, new Vector2(0,1)),
    new VertexPositionColorTexture(new Vector3(200, 200, 0.0f), Color.White, new Vector2(1,1)),
  };

e il risultato (orribile ?) diventa:

Figura 22. Texture e colori
La texture applicata ai vertici

Naturalmente possiamo anche modificare le posizioni dei vertici; non siamo limitati a quadrati, anche se ai fini del disegno 2D questo è raramente usato:

Figura 23. Modificare le posizioni dei vertici
La Modificare le posizioni dei vertici

Per concludere vediamo cosa succede se usiamo delle coordinate di texture differenti: proviamo con delle coordinate più piccole, in modo da applicare al nostro quadrato solo una porzione della texture:

var vertices = new [] {
    new VertexPositionColorTexture(new Vector3(0, 0, 0.0f),     Color.White, new Vector2(0,0) * 0.5f),
    new VertexPositionColorTexture(new Vector3(200, 0, 0.0f),   Color.White, new Vector2(1,0) * 0.5f),
    new VertexPositionColorTexture(new Vector3(0, 200, 0.0f),   Color.White, new Vector2(0,1) * 0.5f),
    new VertexPositionColorTexture(new Vector3(200, 200, 0.0f), Color.White, new Vector2(1,1) * 0.5f),
  };

Figura 24. Texture più grande del quadrato
La texttici

e delle coordinate più grandi in modo da ripetere la texture:

var vertices = new [] {
    new VertexPositionColorTexture(new Vector3(0, 0, 0.0f),     Color.White, new Vector2(0,0) * 4),
    new VertexPositionColorTexture(new Vector3(200, 0, 0.0f),   Color.White, new Vector2(1,0) * 4),
    new VertexPositionColorTexture(new Vector3(0, 200, 0.0f),   Color.White, new Vector2(0,1) * 4),
    new VertexPositionColorTexture(new Vector3(200, 200, 0.0f), Color.White, new Vector2(1,1) * 4),
  };

Figura 25. Texture più piccola del quadrato
La texturtici

Ti consigliamo anche