[XNA] Sistemas de partículas en 2D

Otro “must-do” de la programación gráfica es implementar nuestro propio sistema de partículas. Un sistema de partículas, a pesar de lo sofisticado de su nombre, no es más que un montón de “objetos”, a los que llamaremos partículas, cada uno de ellos con un comportamiento autónomo, pero con cierta relación con el de las demás partículas del mismo sistema. Esto se acostumbra a utilizar para generar efectos parecidos a los que se producen en la naturaleza, como humo, fuego, explosiones… la idea básica aplica tanto para 2D como 3D, sólo cambiarían los tipos de vectores y la forma de pintar, pero la lógica sería la misma o muy parecida.

Como no se si os habré aclarado o liado más con mi particular definición de lo que es un sistema de partículas… os pongo un enlace a la definición técnica de la wikipedia

Así pues, sin más dilación, en este ejemplo os explicaré como implementar un sencillo sistema de partículas para generar un efecto parecido al humo, básicamente el código hace lo que podéis ver en este vídeo:

[View:http://www.youtube.com/watch?v=W4_SX4DNf5c:550:0]

Cómo podéis ver el efecto es muy sencillo, pero trabajándolo se pueden conseguir cosas muy interesantes. Veamos el código de una vez…

Toda la lógica se almacena en una clase que he llamado ManagerParticulas. Con esto conseguimos tener un objeto reutilizable para aplicar las partículas de ese tipo en el momento que queramos. Contiene un montón de constantes, la textura (que es la misma para todas las partículas) y la posición inicial de la que parten todas las partículas “en principio”. Y lo pongo entre comillas porqué al inicializar cada partícula es muy importante que apliquemos un factor de aleatoriedad a cada propiedad de la misma… Todas esas constantes definen valores máximos y mínimos relativos a las partículas.

managerParticulas

La clase Particula es la que nos permite almacenar la información de los cientos de partículas que podemos manejar a la vez.

particula

Vamos a ver algunos de los métodos más interesantes… El constructor cargará la textura y inicializa el array de partículas, y establece la posición inicial.

   1: public ManagerParticulas(ContentManager contentManager, int numeroParticulas, Vector2 posicionInicial) 

   2: {

   3:     this.posicionInicial = posicionInicial;

   4:  

   5:     // Inicializar textura (es la misma para todas las partículas)

   6:     this.textura = contentManager.Load<Texture2D>("humo");

   7:  

   8:     // Inicializar array de partículas, aplicando aleatoriedad en los parámetros para que parezca más "natural"

   9:     particulas = new Particula[numeroParticulas];

  10:     

  11: }

El método Update, que se llamará desde fuera del Manager de Partículas, llama a los métodos encargados de mover a las partículas y de parametrizar a las no inicializadas.

   1: public void Update(GameTime gameTime) 

   2: {

   3:     // Animar partículas "vivas"

   4:     this.AnimarParticulas(gameTime);

   5:  

   6:     // Reparametrizar partículas "muertas"

   7:     this.ParametrizarParticulas(this.posicionInicial, gameTime);

   8: }

La animación como he comentado mueve las partículas y además establece un fade-in fade-out para que las partículas no aparezcan y desaparezcan de golpe, creando un efecto más natural. Esto lo hacemos estableciendo la propiedad alfa de cada instancia de la clase Particula.

   1: private void AnimarParticulas(GameTime gameTime) 

   2: {

   3:     for (int i = 0; i < particulas.Length; i++) 

   4:     {

   5:         if (particulas[i] != null) 

   6:         {

   7:             // Movemos las partículas

   8:             particulas[i].edad += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

   9:             particulas[i].Mover();

  10:  

  11:             // Aplicamos fadeout

  12:             if (particulas[i].edad >= particulas[i].edadMuerte * TIEMPO_INICIO_DECREMENTO_FADEOUT)

  13:             {

  14:                 if (particulas[i].tiempoDesdeUltimoFadeout >= INTERVALO_FADEOUT)

  15:                 {

  16:                     particulas[i].tiempoDesdeUltimoFadeout = 0.0f;

  17:                     particulas[i].alfa -= DECREMENTO_FADEOUT;

  18:                 }

  19:             }

  20:             else

  21:             {

  22:                 if(particulas[i].alfa<MAX_ALFA)

  23:                     particulas[i].alfa += INCREMENTO_FADEOUT;

  24:             }

  25:  

  26:             particulas[i].tiempoDesdeUltimoFadeout += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

  27:         }                

  28:     }

  29: }

Este método es el que tiene más “chicha”, es el que parametriza las partículas, las crea en el intervalo establecido y les aplica un factor de “aleatoriedad” a sus propiedades, para que todas las partículas sean “parecidas pero no iguales” (sinó menudo humo más raro no?).

Comentar que hay varios bucles for que se podrían poner en una sola función, y ahorraríamos tiempo de procesamiento (lo cual se traduce en que podríamos meter más parículas en el sistema sin afectar al rendimiento), pero aquí lo he separado para que el código sea más limpio y fácil de entender.

   1: private void ParametrizarParticulas(Vector2 posicionInicial, GameTime gameTime)

   2: {

   3:     for (int i = 0; i < particulas.Length; i++)

   4:     {

   5:         if (tiempoCreacionUltimaParticula >= INTERVALO_CREACION_PARTICULAS)

   6:         {

   7:             // Instanciamos una nueva partícula si todavía no lo está

   8:             if (particulas[i] == null)

   9:             {

  10:                 particulas[i] = new Particula();

  11:             }

  12:  

  13:             // Sólo reparametrizamos las partículas "muertas"

  14:             if (particulas[i].edad >= particulas[i].edadMuerte)

  15:             {

  16:                 // Reinicializamos la edad

  17:                 particulas[i].edad = 0.0f;

  18:  

  19:                 // Reinicializamos alfa

  20:                 particulas[i].alfa = 0.0f;

  21:                 particulas[i].tiempoDesdeUltimoFadeout = 0.0f;

  22:  

  23:                 // Situamos la posición inicial

  24:                 particulas[i].posicion = posicionInicial + new Vector2((float)Aleatorio.ObtenerAleatorio(MAX_DESVIACION_POSICIONINICIAL), (float)Aleatorio.ObtenerAleatorio(MAX_DESVIACION_POSICIONINICIAL));

  25:  

  26:                 // Establecemos la aceleración

  27:                 particulas[i].aceleracion.X = (float)Aleatorio.ObtenerAleatorio(MAX_ACELERACION_X) ;

  28:                 particulas[i].aceleracion.Y = -Aleatorio.ObtenerAleatorio(MAX_ACELERACION_Y) - MIN_ACELERACIONY;

  29:                 particulas[i].aceleracion.Normalize();

  30:  

  31:                 if (Aleatorio.ObtenerAleatorio(10) <= 5)

  32:                     particulas[i].aceleracion.X *= -1;

  33:  

  34:                 // Establecemos la edad de la "muerte"

  35:                 particulas[i].edadMuerte = EDAD_MUERTE_INICIAL;

  36:                 particulas[i].edadMuerte += Aleatorio.ObtenerAleatorio(MAX_DESVIACION_MUERTE);

  37:  

  38:                 // Establecemos la desviación en la escala (queremos unas partículas más pequeñas que otras)

  39:                 particulas[i].escala = (float)1.0f / (float)Aleatorio.ObtenerAleatorio(MAX_DESVIACION_ESCALA);

  40:  

  41:                 tiempoCreacionUltimaParticula = 0.0f;

  42:             }

  43:         }

  44:         else 

  45:         {

  46:             tiempoCreacionUltimaParticula += (float)gameTime.ElapsedGameTime.TotalMilliseconds;

  47:         }

  48:     }

  49: }

El Draw ya no tiene ningún secreto… excepto el detalle de que estamos aplicando un alpha a la textura, que eso sí es interesante:

   1: public void Draw(GameTime gameTime, SpriteBatch spriteBatch)

   2: {

   3:     for (int i = 0; i < particulas.Length; i++)

   4:     {

   5:         if(particulas[i]!=null)

   6:             spriteBatch.Draw(textura,

   7:                 particulas[i].posicion, null,

   8:                 new Color(255, 255, 255, (byte)MathHelper.Clamp(particulas[i].alfa, 0, 255)), 0.0f, Vector2.Zero, particulas[i].escala,

   9:                 SpriteEffects.None, 0);

  10:     }

  11: }

El resultado del código es el del vídeo que os he mostrado antes, podéis además descargaros el código para probarlo. Algo que os recomiendo es jugar un poco con los valores de las constantes, ampliar el número de partículas hasta 10.000 (lo aguanta perfectamente jejeje) y aumentad el tiempo de vida de las partículas, y observaréis efectos curiosos.

Hasta la próxima!

[XNA] Animaciones básicas en 3D

Las animaciones en 3D implican muchas operaciones de matrices… pero por suerte XNA nos facilita el trabajo hasta tal punto que prácticamente el más negado en matemáticas puede trabajar con ellas… pero aunque sea fácil cualquier programador de XNA que se precie debe hacer un esfuerzo por comprenderlas si quiere saber lo que hace xD. En fin, el de las animaciones es un tema muy ámplio, e iré explicando algunas partes en pequeños episodios. En esta introducción veremos las operaciones más básicas.

Animar objetos en su forma más básica consistirá en multiplicar matrices, y algo muy importante es el orden en el que realicemos estas multiplicaciones. Si no realicamos las multiplicaciones en el orden correcto, nuestro modelo 3D sin duda se moverá de forma cuanto menos «rara» o inesperada. Este problema se soluciona recordando el orden que hay que aplicar, que siempre va a ser el mismo, partiendo de la matriz identidad:

  1. Escalar el modelo
  2. Rotar el modelo sobre su propio eje
  3. Rotar el modelo sobre un punto externo
  4. Trasladar el modelo

Y como he comentado, XNA nos ayuda enormemente en estas posibles operaciones básicas de matrices.

Esto se podría traducir en los siguientes ejemplos:

   1: // Matriz identidad

   2: Matrix.Identity;

   3:  

   4: // Crear escalas

   5: Matrix.CreateScale(1.0f);

   6: Matrix.CreateScale(Vector3.Zero);

   7:  

   8: // Rotar ejes

   9: Matrix.CreateRotationX(0.5f);

  10: Matrix.CreateRotationY(0.5f);

  11: Matrix.CreateRotationZ(0.5f);

  12:  

  13: // Trasladar

  14: Matrix.CreateTranslation(Vector3.Zero);

Ahora vamos a ver un par de ejemplos prácticos muuuy sencillos.

Ejemplo 1: Animando un ventilador

Para animar este ventilador, lo primero que he hecho es descargar el modelo 3D de Internet. En la web hay cientos de páginas que permiten descargar modelos 3D libres de derecho… con una simple búsqueda en Bing encontraremos 41 millones de resultados 🙂 Eso sí, a continuación he tenido que realizar algunas pequeñas modificaciones en 3DSMAX.

Si ampliáis la imágen veréis que he “fusionado” las aspas, con el eje central y los soportes que unen las aspas con los ejes, para animarlos todos juntos, y les he puesto un nombre: “aspas”, al que después accederé desde XNA para animar sólo esa parte del modelo 3D.

captura_3dmax

Ese acostumbra a ser un problema para más de un programador… que no acostumbramos a conocer 3D Max, por suerte siempre hay buenos amigos en los foros que nos ayudaran en estos detalles… en el caso de 3D MAX hay que convertir cada pala a malla editable (con el botón derecho sobre el aspa: Convert To->Editable Mesh), y posteriormente, en las propiedades de la malla, usaremos la función “Attach” para ir fusionando las palas. Finalmente ponemos un nombre que usaremos desde XNA al conjunto de aspas y el eje.

El código no es que tenga mucha dificultad… tampoco entraré mucho en detalle porque os dejo el link para descargarlo.

   1: public void Draw(GameTime gameTime, Matrix vista, Matrix proyeccion) 

   2: {

   3:     modelo.CopyAbsoluteBoneTransformsTo(transformaciones);

   4:  

   5:     foreach(ModelMesh mesh in modelo.Meshes)

   6:     {

   7:         Vector3 rotacionTmp = Vector3.Zero;

   8:  

   9:         if (mesh.Name == "aspas")

  10:         {

  11:             rotacion.Y += 0.01f;

  12:  

  13:             if (rotacion.Y > 360)

  14:                 rotacion.Y = 0;

  15:  

  16:             rotacionTmp = rotacion;

  17:         }

  18:  

  19:         Matrix.CreateTranslation(Vector3.Zero);

  20:         Matrix.CreateRotationX(0.5f);

  21:         Matrix.CreateRotationY(0.5f);

  22:         Matrix.CreateRotationZ(0.5f);

  23:  

  24:         foreach (BasicEffect efecto in mesh.Effects) 

  25:         {

  26:             efecto.EnableDefaultLighting();

  27:  

  28:             efecto.World = transformaciones[mesh.ParentBone.Index] * 

  29:                 Matrix.CreateFromYawPitchRoll(

  30:                 rotacionTmp.Y,

  31:                 rotacionTmp.X,

  32:                 rotacionTmp.Z) *

  33:                 Matrix.CreateScale(escala) *

  34:                 Matrix.CreateTranslation(posicion);

  35:  

  36:             efecto.View = vista;

  37:             efecto.Projection = proyeccion;

  38:         }

  39:         mesh.Draw();

  40:     }

  41: }

 La parte interesante es la que compobamos si el nombre de la malla es “aspas”, en cuyo caso lo rotamos en su eje Y.

Ejemplo 2: Animando la tierra y la luna

Este vamos a complicarlo un poco, pero tampoco mucho eh 🙂  Lo que haremos va a ser poner en evidencia el orden de la multiplicación de las matrices.

En este caso he creado una simple esfera con el 3D Max, y le he asignado primero la textura de la Tierra, y he exportado a FBX, y después lo mismo con la Luna. Estas texturas también pueden encontrarse rápidamente en Internet.

A la clase que he llamado “ModeloExtendido”, que es la que se encarga de almacenar la información del modelo y pintarlo, le he añadido las siguientes matrices (la matriz World pasa a ser privada):

   1: public Matrix rotacion;

   2: public Matrix traslacion;

   3: public Matrix orbitacion;

   4: public Matrix escala;

 

Ahora, desde fuera de la clase podemos modificar cualquiera de estas matrices en el orden que queramos, sólo en el Draw tendremos que tener en cuenta el orden de multiplicación de las mismas:

   1: public void Draw(GameTime gameTime, Matrix vista, Matrix proyeccion) 

   2: {

   3:     modelo.CopyAbsoluteBoneTransformsTo(transformaciones);

   4:  

   5:     foreach(ModelMesh mesh in modelo.Meshes)

   6:     {

   7:         foreach (BasicEffect efecto in mesh.Effects) 

   8:         {

   9:             efecto.EnableDefaultLighting();

  10:  

  11:             efecto.World = transformaciones[mesh.ParentBone.Index] * ObtenerWorld();

  12:             efecto.View = vista;

  13:             efecto.Projection = proyeccion;

  14:         }

  15:  

  16:         mesh.Draw();

  17:     }

  18: }

  19:  

  20: private Matrix ObtenerWorld() 

  21: {

  22:     return world * escala * rotacion * orbitacion * traslacion;

  23: }

 

Con su salsa y demás, el resultado es el vídeo que habéis visto. El código está disponible para descargar.

[OT] Emulador de Windows Phone 7 Series desbloqueado

El hecho es que ya hace varios días que está disponible… pero os lo pongo por si os habéis quedado despistados 🙂 Si queréis disponer de un emulador de WP7Series ahora podéis descargarlo en este enlace. El autor del desbloqueo se ha asustado un poco y ha retirado el enlace directo a la descarga en su blog… pero podéis descargarlo en los enlaces que aparecen en los últimos comentarios que existen del artículo. Siguiendo esos sencillos pasos vuestro emulador será completo!

Información obtenida del grupo Estudiantes.Net en Facebook

[MIX] Herramientas de desarrollo para windows phone 7 ya disponibles!

Lo acaba de anunciar Scott Guthrie en el MIX2010… ya podemos descargar las herramientas de desarrollo para Phone 7!! Estas herramientas se basan en desarrollo Silverlight y XNA. Podéis descargarlas en http://developer.windowsphone.com/windows-phone-7-series/ La descarga de Visual Studio 2010 Express for Windows Phone (uf) es gratuita.

Todo esto en riguroso directo desde Las Vegas.. 🙂 enjoy!

[OT] XNA Game Studio 4.0: Nos vemos en Las Vegas!

Desde hace unos días ya es oficial… XNA Game Studio 4.0 será un poco más portable… esta vez sobre Windows Phone 7! Y además con todo su esplendor… portabilidad «total», juegos 3D, XBOX Live, etc. El caso es que se ha estado hablando de ello en el GDC, y puede encontrarse información de ello en los blogs oficiales, como el de Michael Klucher. Otro tema interesante es que soporta la integración con Visual Studio 2010.

El caso es que en el MIX 2010 se van a mostrar más detalles al respecto, en sesiones específicas de desarrollo de XNA 4 sobre la plataforma windows Phone. Allí voy a estar, y os lo iré narrando a diario! 🙂

[XNA] Introducción al trazado de rayos con XNA

Los rayos son usados en desarrollo de videojuegos para trazar líneas imaginarias entre un punto y otro en el espacio tridimensional, y valorar si hay intersecciones entre el vector que une ambos. Puede servir para detectar si un disparo intersecciona con su objetivo o no, y para calcular la distancia entre este y quien ha disparado… o también puede ser útil para pintar un texto encima de un modelo en el espacio 3D… o para hacer un Drag & Drop de modelos en un espacio tridimensional. De hecho, el trazado de rayos puede ser utilizado incluso para renderizar escenas… pero no se usa en videojuegos a tiempo real porque consume muchos recursos.

Con un poco de álgebra se puede calcular la intersección entre un rayo y una esfera, entre un rayo y un plano, un cubo, o incluso un triángulo… las matemáticas para hacer estos cálculos pueden llegar a ser más o menos complicadas… pero si programas en XNA, se te va a caer la lagrimita de lo fácil que es utilizar técnicas de trazado de rayos. A pesar de esta ventaja, hay que decir que la documentación en MSDN acerca de la estructura Ray es escueta… por decirlo de forma amable. Así que voy a compartir con vosotros algunos experimentos que he hecho con ella y os puede interesar conocer.

En este ejemplo lo que hacemos es crear un rayo a partir de la posición del puntero del ratón sobre la pantalla, y calcular el destino del rayo a partir de la vista y proyección de la camara -pero creas que es gran cosa, porqué aquí XNA vuelve a socorrernos-.

Así pues, en el método update, «refrescaremos» el rayo llamando al método siguiente:

   1: private Ray posicionarRayo() 

   2:         {

   3:             Vector2 posicionMouse = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

   4:  

   5:             // Calculamos a qué posiciones del World corresponden las del mouse con Unproject

   6:             Vector3 puntoCercano = GraphicsDevice.Viewport.Unproject(new Vector3(posicionMouse, 0f),

   7:                 camara.projection, camara.view, Matrix.Identity);

   8:  

   9:             Vector3 puntoLejano = GraphicsDevice.Viewport.Unproject(new Vector3(posicionMouse, 1f),

  10:                 camara.projection, camara.view, Matrix.Identity);

  11:  

  12:  

  13:             Vector3 direccion = puntoLejano - puntoCercano;

  14:  

  15:             direccion.Normalize();

  16:  

  17:             return new Ray(puntoCercano, direccion);

  18:         }

El método realmente interesante de este código es Unproject. Lo que hace es proyectar el un vector a partir de la posición del mouse, en una posición de la escena en 3D.

Después, para saber si hay intersección entre el rayo y el BoundingSphere, sería algo tan sencillo como utilizar un método de la propia estructura Ray:

   1: rayo.Intersects(ref esfera, out distancia);

Donde esfera es un boundingSphere y la distancia es la longitud a la que existe la intersección entre el rayo y el boundingsphere.

Finalmente, para pintar el texto encima del modelo 3D (en este caso las primitivas de un BoundingSphere), tenemos que traducir la posición en el world del modelo (en este caso hemos puesto Matrix.Identity) a lo que es la pantalla:

   1: string mensaje = "Rayo intersecciona con la esfera!";

   2:                 

   3: // Calculamos la posición en pantalla del boundingSphere gracias al método Project del Viewport

   4: Vector3 posicionenPantalla = graphics.GraphicsDevice.Viewport.Project(

   5: Vector3.Zero, camara.projection, camara.view, Matrix.Identity);

   6:  

   7: // Obtenemos el centro del texto

   8: Vector2 centroTexto = this.fuente.MeasureString(mensaje) / 2;

   9:  

  10: Vector2 posicionTexto = new Vector2(posicionenPantalla.X, posicionenPantalla.Y - (esfera.Radius + 50));

  11:  

  12: spriteBatch.DrawString(fuente, mensaje, posicionTexto - centroTexto, Color.White);

El resultado de este ejemplo sencillo sería el siguiente, donde estamos pintando un boundingsphere (aparece rojo si ponemos el mouse “sobre él”, y blanco si el mouse queda “fuera” de él, además aparece el texto en blanco por encima):

Además, en XNA Creators Club Online hay un par de ejemplos interesantes relacionados con el trazado de rayos donde podrás ampliar conocimientos:

Rayos con modelos
http://creators.xna.com/en-US/sample/picking

Rayos a nivel de triangulos
http://creators.xna.com/en-US/sample/pickingtriangle

[XNA] Aprende a programar C# con XNA

XNA Game Studio se está convirtiendo cada vez más en una plataforma para introducir el mundo de la programación en C# a los estudiantes. Este libro gratuito no da por supuesto ningún conocimiento previo de programación. No solo se aprende C# sinó que es una perfecta introducción, muy básica, al desarrollo de videojuegos. Sin duda una lectura muy interesante para jóvenes programadores.

Podéis descargar el libro en PDF aquí:

http://www.lulu.com/product/download/a-simple-introduction-to-game-programming-with-c%23-and-xna-31/5438606

También existe una versión online en esta URL:

http://xnagamemaking.com/

[XNA] Game Engines para XNA

Hoy os presento una recopilación de Game Engines para XNA. Como sabéis, la plataforma XNA ofrece facilidades para el renderizado de gráficos, carga de contenidos y demás, pero en videojuegos completos es necesaria la utilización de un engine que extienda y facilite estas funcionalidades, y añada otras, como pueden ser los motores de física o animación de modelos 3D. Cualquier engine importante que detectéis que falta en la lista me lo decís y lo añado ipso facto 🙂

Tomahawk XNA Game Engine


Completo framework open source compatible con XNA 3.1 para XBOX 360 y Windows. Internamente se basa en otros engines para la física y animaciones, lo que lo hacen muy potente y desacoplado. Uno de los problemas que le veo es la documentación del proyecto.

http://www.assembla.com/wiki/show/tomahawkengine/

 CAROT Engine


Todavía en versión Alpha, y orientado a 2D, parece tener como punto fuerte un foro bastante activo, lo cual es una garantía para la continuidad del proyecto. Para proyectos basados en Windows usa un wrapper de las librerías de sonido Audiere, en C++. La descarga es gratuita.

http://carotengine.com/

Ox Game Engine for XNA


Open Source. Se autodefine como un engine ya maduro para proyectos 3D, incluye un editor de escenas 3D visual, facilidad en renderizado de GUI en 2D, también con un editor visual, física basada en JigLibX, animaciones, y un sistema de scripting basado en C#.  

http://oxgameengine.codeplex.com/

QuickStart Engine
Engine 3D, open source. Se autodefine como potente y fácil de usar. Además puedo deciros que lo he probado, y es realmente sencillo de utilizar, además de tener una comunidad que atiende a las peticiones de mejoras, si van en beneficio de todos. Permite gestionar física, animaciones, renderizado, etc.

http://www.codeplex.com/QuickStartEngine

JigLibX Physics Engine

Excelente motor de física Open Source. Es un port a XNA del proyecto JigLib.

http://www.codeplex.com/JigLibX

Klib Engine (2D)
Engine open source para juegos 2D basados en XBOX 360 y Windows. Este framework quiere facilitar operaciones comunes como físicas, escenas, partículas, efectos de post-procesado, gestión del input y más.

http://klibenginexna.codeplex.com/

DEngine – C# XNA 2D Game Engine
Engine 2D gratuito que se basa en la lectura de XML para la gestión de niveles, facilita la animación de sprites, física basada en FarseerPhysics, editor de niveles, controles GUI, algoritmo A*, y un ejemplo de videojuego RTS basado en este engine.

http://dengine.codeplex.com/

Phoenix XNA Engine
Un engine gratuito todavía en desarrollo pero bastante prometedor, ya que su desarrollo se basa en una comunidad bastante activa. Tiene funcionalidades como generación de terrenos a partir de texturas, gestión de Input, texturas, cámaras, Networking, etc. 

http://phoenixxna.codeplex.com/


XEN Graphics API for XNA
xen
Engine 3D que se esfuerza en ser fácil de utilizar y a su vez ofrecer un alto rendimiento. Muy interesante es el hecho de su completa documentación y tutoriales que demuestran la facilidad de uso.

http://xen.codeplex.com/


SilverSprite
No se podría definir exactamente como un engine XNA… pero es interesante mencionarlo. Permite ejecutar juegos 2D basados en XNA en Silverlight, en sus versiones 2 y 3. 

http://silversprite.codeplex.com/


Garage Games Torque X

Engine comercial para el desarrollo de  videojuegos para varias plataformas. Tiene muchos años de historia y es bastante famoso. Tienen un framework tan trabajado que programar bajo esta plataforma se parece poco a desarrollar en XNA (para lo bueno y para lo malo que ello conlleva). Tiene editores de niveles 2D y 3D y un montón de utilidades más.

http://www.torquepowered.com/

Mercury particle engine
Open source. Motor de partículas para Windows PC y XBOX 360.

http://www.codeplex.com/mpe

SubBurn
Comercial. Engine gráfico para 3D focalizado en iluminación y el renderizado.

http://www.synapsegaming.com/products/sunburn/

bEpUphysics
Otra librería gratuíta (siempre que no se use para obtener beneficios económicos) de físicas para XNA. Contiene documentación y algunos tutoriales.

http://www.bepu-games.com/BEPUphysics/downloads.htm

[XNA] Implementando un clon de Tetris con XNA

El Tetris es un must-do para cualquier programador que se precie… pues con esto he podido poner un check en la lista de «cosas que hacer para ser un buen programador». Un juego, por sencillo que sea -como es el caso del tetris- contiene mucha lógica, y si no se estructura bien la complejidad puede crecer de forma exponencial… llegando a complicar de tal forma la codificación que resulte imposible continuar con el desarrollo del juego. El caso es que si te animas a implementar este pequeño juego, te darás cuenta de la importancia de diseñar antes de picar código -algo a lo que estamos relativamente acostumbrado cuando programamos aplicaciones de gestión-. En este caso he usado una herramienta de diseño increiblemente avanzada… EL EXCEL. Pues sí… el excel ¿qué pasa…? Lo cierto es que me ha ido perfecto para «debugar mentalmente» algunas situaciones, así como tener controlada la forma y tamaño de cada uno de los tipos de piezas disponibles en un tetris que se precie. Como demuestra la captura de pantalla:

El resultado de unas horillas de codificación es el siguiente:

[View:http://www.youtube.com/watch?v=m_JezzoomWw:550:0]

Dicho esto… vamos a ver un poco el algoritmo de implementación (a grandes rasgos):

 1 Crear pieza aleatoria               
 2 Leer nueva posición               
 3 Comprobar si la nueva posición está libre               
     3.1 Si NO está libre copiar a Matriz              
     3.2 Si está libre, lo movemos a la posición solicitada              
4 Comprobar si hay línea en la matriz               
    4.1 Si hay línea, desplazar todo una línea hacia abajo a partir de esta, sobreescribiendo              

¿Fácil verdad?  Toda la lógica se encuentra en las clases Tablero y Ficha, que muestro en este diagrama de Visual Studio:

Los objetos importantes son MatrizGlobal, que es una matriz de dos dimensiones donde se van almacenando todas las piezas que no están bajo el control del jugador, y sobre la cual detectaremos colisiones con la ficha que sí mueve el usuario, si ha llegado al tope (game over), si hay línea, etc.

public Color?[,] MatrizGlobal;

Por defecto todos los valores de la matriz serán null, y a medida que el usuario vaya soltando piezas sobre el «suelo» de la matriz, estas piezas pasarán a formar parte de la matriz en forma de Color (para posteriormente ser capaces de pintar cada pieza con la textura que toca).

La clase update de Tablero ejecuta el algoritmo que he mostrado antes:

public void Update(GameTime gameTime)
{
  
if (tipoMovimiento != Ficha.TipoMovimiento.gameOver)
   {

      // Lógica de la ficha
     
tipoMovimiento = this.Ficha.Update(gameTime, ref MatrizGlobal);

      // Comprobar si hay lnea
     
if (tipoMovimiento == Ficha.TipoMovimiento.colisionVertical)
      {
        
this.ComprobarLineas();
        
this.Ficha = new Ficha();
      }
   }
  
else
  
{
     
// Si pulsa espacio, limpiamos tablero y reiniciamos
     
if (Keyboard.GetState().IsKeyDown(Keys.Space))
      {
        
this.ResetGame();
      }
   }
}

En la clase Ficha tenemos como método más «complicado» el que calcula si se puede mover la pieza a la nueva posición solicitada (la pieza siempre cae hacia abajo, más si el jugador la está haciendo rotar o mover hacia derecha o izquierda). Sería esta la implementación del método:

int anchoBloque = this.ancho[this.rotacionActual];
int altoBloque = this.alto[this.rotacionActual];

int anchoTablero = MatrizGlobal.GetLength(0);
int altoTablero = MatrizGlobal.GetLength(1);

// Comprobamos posicin de la pieza con el tablero
for (int y = 0; y < altoBloque; y++)
{
  
for (int x = 0; x < anchoBloque; x++)
   {
     
if (this.Espacio[rotaciontmp, x, y] == true)
      {
        
if(nuevaPosicionY + y == altoTablero)
           
return TipoMovimiento.colisionVertical;
        
if(nuevaPosicionX + x >= anchoTablero)
           
return TipoMovimiento.fueraLimites;
        
if (MatrizGlobal[nuevaPosicionX + x, nuevaPosicionY + y] != null)
           
return TipoMovimiento.colisionLateral;

         if (this.PosicionY + y + 1 < altoTablero && MatrizGlobal[nuevaPosicionX + x, this.PosicionY + y + 1] != null)
           
return TipoMovimiento.colisionVertical;
      }
   }
}

return TipoMovimiento.correcto;

¿Lo próximo? Creo que va a ser divertido implementar una IA que juegue sola al tetris… (y digo sola porqué ningún humano es capaz de vencer una máquina jugando al tetris…)

[webcast] XNA Avanzado: "Cómo se hizo: Kaotik Puzzle"

En este webcast conoceremos de la mano del autor del videojuego «Kaotik Puzzle«, Silvino Esquiva, el caso de éxito de la producción de un videojuego Indie, y su comercialización en XBOX Live. Silvino nos enseñará la arquitectura utilizada, las líneas generales del desarrollo, y sobretodo el motor de IA, punto donde destaca especialmente este entretenido videojuego.

Silvino Esquiva es un experimentado Modelador 3D, que además demuestra en esta producción tener ámplios conocimientos de desarrollo en XNA. Ha trabajado durante años como profesor en escuelas de 3D y en distintos tipos de proyectos de modelado.

Registro:
http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032443443&EventCategory=4&culture=es-ES&CountryCode=ES

[View:http://www.youtube.com/watch?v=oQyVf1NjAtE:550:0]