2009-03-19 15 views
5

In un editor di livelli che ho creato per il mio gioco XNA (l'editor è anche in XNA), sto permettendo di ridimensionare gli oggetti Texture2D.Come ridimensionare e salvare Texture2D in XNA?

Quando l'utente tenta di salvare il livello, mi piacerebbe effettivamente ridimensionare il file immagine su disco in modo che non richieda ridimensionamento nel gioco.

C'è un modo semplice per creare un file immagine (preferito PNG) da un oggetto Texture2D in scala?

risposta

11

È possibile ridimensionare le trame eseguendo il rendering su un oggetto di rendering con le dimensioni desiderate e salvando la trama di destinazione del rendering.

Questo semplice esempio mostra come è possibile farlo. Ignora la configurazione di GraphicsDevice, che è solo per fare un piccolo esempio autonomo. Il bit interessante è la creazione del target di rendering e il disegno della texture in scala. Dovresti riutilizzare i target di rendering dove puoi (tutte le immagini della stessa dimensione possono riutilizzare un target di rendering).

using System; 
using System.Runtime.InteropServices; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 

class Program 
{ 
    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr GetConsoleWindow(); 

    static void Main(string[] args) 
    { 
     string sourceImagePath = args[0]; 
     string destinationImagePath = args[1]; 
     int desiredWidth = int.Parse(args[2]); 
     int desiredHeight = int.Parse(args[3]); 

     GraphicsDevice graphicsDevice = new GraphicsDevice(
      GraphicsAdapter.DefaultAdapter, 
      DeviceType.Hardware, 
      GetConsoleWindow(), 
      new PresentationParameters()); 
     SpriteBatch batch = new SpriteBatch(graphicsDevice); 

     Texture2D sourceImage = Texture2D.FromFile(
      graphicsDevice, sourceImagePath); 

     RenderTarget2D renderTarget = new RenderTarget2D(
      graphicsDevice, 
      desiredWidth, desiredHeight, 1, 
      SurfaceFormat.Color); 

     Rectangle destinationRectangle = new Rectangle(
      0, 0, desiredWidth, desiredHeight); 

     graphicsDevice.SetRenderTarget(0, renderTarget); 

     batch.Begin(); 
     batch.Draw(sourceImage, destinationRectangle, Color.White); 
     batch.End(); 

     graphicsDevice.SetRenderTarget(0, null); 

     Texture2D scaledImage = renderTarget.GetTexture(); 
     scaledImage.Save(destinationImagePath, ImageFileFormat.Png); 
    } 
} 
+2

Questo è il più vicino a quello che ho finito per implementare. Sebbene non abbia usato l'importazione kernel32 o GetConsoloWindow, ho semplicemente usato il mio GraphicsDevice dal mio oggetto Game. –

0

Hai provato Texture2D.Save()?

+0

Ciò funzionerebbe se Texture2D fosse la dimensione corretta, ma il ridimensionamento viene eseguito con i richiami Draw, come posso creare un oggetto Texture2D che viene ridimensionato? –

0

Il ridimensionamento delle immagini in genere non comporta molto di sovraccarico, inoltre, non si vorrebbe caricare nella stessa memoria diverse dimensioni della stessa texture in quanto sarebbe uno spreco.

Ovviamente, potresti scrivere un gioco Zune, il che significa che probabilmente non mi occupo del ridimensionamento, ma comunque.

Non penso che sia possibile salvare l'immagine in scala direttamente da XNA, ma è possibile utilizzare la classe Image di WinForms per caricare l'immagine e ridimensionarla in base alle dimensioni nell'editor di livelli e salvarla sul disco.

Se la trama non è un BMP o un PNG, potrebbe essere necessario utilizzare il comando Texture2D.Save() per convertirlo in un formato che è possibile utilizzare nella classe Image.

Questa discussione potrebbe aiutarti a utilizzare la classe Immagine. http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/6fe3d353-0b09-440b-95c9-701efdc9e20a/

+0

Mi piacerebbe davvero evitare il ridimensionamento in-game per mantenere il mio codice di collisione semplice. –

0

Ho codice come questo che fa una grande/copia più piccola di una trama, ma ottengo gli errori dopo un po '. Dopo 30 ridimensionamenti, ottengo l'eccezione, non la prima volta.

Sembra essere un problema di rendering ma non sono sicuro. Mi chiedo se otterrai anche queste eccezioni se usi molto questo codice?