viernes, 13 de febrero de 2009

XNA Y METODOS DE EXTENSION - PARTE 2

El artículo original fue escrito el 03-Nov-08.

Continuando con el tema de cómo usar la muy útil funcionalidad provista por los "Extension Methods" en nuestras creaciones basadas en XNA, para este artículo necesitaremos el juego de ejemplo "FuelCell" (recuerda que encontrarás este tutorial -junto con el "TopDownShooter"- en los archivos de ayuda en la sección "What's New In This Release").

Ok. En el capítulo llamado "Finishing Touches" del ejemplo "FuelCell", verás el siguiente método al final del archivo "FuelCellGame.cs":

private Rectangle GetTitleSafeArea(Viewport viewport)
{
Rectangle retval = new Rectangle(viewport.X, viewport.Y,
         viewport.Width, viewport.Height);

#if XBOX
retval = viewport.TitleSafeArea;
#endif

 return retval;
}


Si recuerdas mi último artículo sobre este tema, debes estar anticipando a esta altura que el estructurado "Viewport" puede ser "extendido" tal que se obtenga el área "insegura" en una sola llamada a un método.

Si esto es así, adivinaste! Podemos usar los métodos de extensión para declarar una operación llamada, digamos "GetFullArea", y brindarle la implementación adecuada.

No sólo pasaremos otr vez un parámetro por referencia (usando la palabra reservada "out") -como hicimos en la Parte 1 de esta serie- sino también para este caso particular, puesto que estamos manejándonos con un estructurado, podemos darnos el lujo de implementar una método sobrecargado que localmente declare, cree y retorne una instancia de un "Rectangle" (sé lo que estás pensando, no hay propiedades de extensión en C#, así que necesitaremos obtener el rectángulo llamando a un método).

Usando métodos de extensión, nuestra solución debería lucir como sigue:

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

namespace MyNamespace.Math
{
public static class MathExtensions
{
public static void GetFullArea(this Viewport viewport,
              out Rectangle area)
{
area = new Rectangle(viewport.X, viewport.Y,
                   viewport.Width, viewport.Height);
}

public static Rectangle GetFullArea(this Viewport
              viewport)
{
return new Rectangle(viewport.X, viewport.Y,
                   viewport.Width, viewport.Height);
}
}
}

Ahora bie, el método "GetTitleSafeArea(...)" podría ser reimplementado de esta forma:

private Rectangle GetTitleSafeArea(Viewport viewport)
{
Rectangle retval;

 #if XBOX
retval = viewport.TitleSafeArea;
#else
viewport.GetFullArea(out retval);
#endif

 return retval;
}

O también así:

private Rectangle GetTitleSafeArea(Viewport viewport)
{
#if XBOX
return viewport.TitleSafeArea;
#else
return viewport.GetFullArea();
#endif
}

Recuerda dos cosas importantes:

  • Tendrás que agregar la sentencia "Using" correspondiente en el archivo que usará el método de extensión (que en este ejemplo es "MyNamespace.Math"), y
  • Tendrás que agregar manualmente una referencia al ensamblado "System.Core" en tu proyecto.

Esta técnica puede usarse para obtener, digamos -entre otras cosas, un "Vector2" que contenga el ancho y la altura de un "Viewport" (idem para las áreas de visualización y cliente). Dejo ésto como un ejercicio para que lo intentes (verás que es muy fácil de implementar).

Espero que encuentres este artículo útil.

Hasta la próxima,
~Pete