2009-03-19 32 views
5

En un editor de niveles que he creado para mi juego XNA (el editor también está en XNA), estoy permitiendo escalar objetos Texture2D.¿Cómo cambiar el tamaño y guardar un Texture2D en XNA?

Cuando el usuario intenta guardar el nivel, me gustaría cambiar el tamaño del archivo de imagen en el disco para que no requiera escalado en el juego.

¿Existe alguna manera fácil de crear un archivo de imagen (PNG preferido) desde un objeto Texture2D escalado?

Respuesta

11

Puede escalar sus texturas renderizando en un destino de renderizado al tamaño que desee y luego guardando la textura del objetivo de renderizado.

Este sencillo ejemplo muestra cómo podría hacerlo. Ignore la configuración del GraphicsDevice, solo para hacer un pequeño ejemplo autónomo. Lo interesante es crear el objetivo de renderizado y dibujar la textura escalada. Deberías reutilizar los objetivos de renderizado donde puedas (todas las imágenes del mismo tamaño pueden reutilizar un objetivo de renderizado).

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

Esto es lo más cercano a lo que terminé implementando. Aunque no utilicé la importación de kernel32 ni GetConsoloWindow, simplemente usé mi GraphicsDevice desde mi objeto Game. –

0

¿Has probado Texture2D.Save()?

+0

Esto funcionaría si el Texture2D fuera del tamaño correcto, pero la escala se hace con las llamadas al Draw, ¿cómo puedo crear un objeto Texture2D que se escala? –

0

Escalar imágenes generalmente no implica demasiada sobrecarga, además, no querría cargar diferentes tamaños de la misma textura en la memoria ya que sería un desperdicio.

Por supuesto, podría estar escribiendo un juego de Zune, lo que significa que probablemente estoy fuera de la escala, pero, de todos modos.

No creo que pueda guardar la imagen escalada directamente desde XNA, pero podría usar la clase de imagen de WinForms para cargar la imagen y luego escalarla a las dimensiones en su editor de niveles y guardarla nuevamente en el disco.

Si su textura no es BMP o PNG, puede que tenga que usar el comando Texture2D.Save() para convertirlo a un formato que pueda usar en la clase Image.

Este hilo puede ayudarle con el uso de la clase de imagen. http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/6fe3d353-0b09-440b-95c9-701efdc9e20a/

+0

Realmente me gustaría evitar escalar en el juego para mantener mi código de colisión simple. –

0

Tengo un código como este que hace una copia más grande/más pequeña de una textura pero consigo errores después de un tiempo. Después de 30 cambios de tamaño, recibo la excepción, no la primera vez.

Parece ser un problema de rendertarget, pero no estoy seguro. ¿Se pregunta si obtendrá estas excepciones también si también ejecuta este código demasiado?

Cuestiones relacionadas