.NET Tutorial 53. XNA4 en un Windows Forms

Han pasado ya varios meses desde que no me ponía en "serio" con un nuevo tutorial (más que nada debido a la falta de tiempo)

Hoy os mostraré una cosa que quizás pueda ser interesante a más de uno: La posibilidad de usar XNA en una aplicación "típica de Windows", es decir, con sus controles "label", "butons", "checkbox", etc.

Lo que se explica a continuación está explicado para una aplicación "Windows Form" de VB.NET pero es totalmente extrapolable si la aplicación es "Windows Form" de C# (y además, los cambios son realmente mínimos, básicamente a nivel de sintáxis y poco más)

Si vistéis los tutoriales anteriores en este blog sobre el uso de XNA (versión XNA 3.1)  notaríais que para poder usar XNA desde VB.NET había que hacer un "apaño" con un proyecto de C#.

Pues bien, esto ya no es necesario tanto con la versión XNA4 y con el Visual Studio 2010, puesto que ya hay un soporte nativo para usar XNA en un proyecto completamente escrito en VB.NET

¿Para que puede servir meter XNA dentro de una aplicación "Windows Form"? 

Pues a bote pronto se me ocurre que quieras programar un "editor de niveles"  y necesites "renderizar" en dicho formulario tu mapeado.

Hay que tener en cuenta que XNA le dá como 10.000.000 de patadas a GDI / GDI+ y realmente puedes conseguir, además de un rendimiento espectacular, unos resultados la mar de majos.

Por último decir que lo que os mostraré aquí no requiere ningún control "especial" diseñado para poder renderizar los gráficos mediante XNA, simplemente se hace un un control Picturebox totalmente estándar.

Cómo veréis es tremendamente simple a la par que potente y sencillo.

Bien, dicho lo cual, al lio que me lio.

Una vez instalada la SDK del Windows Phone 7 tendremos disponibles en VB.NET las plantillas para desarrollar aplicaciones con XNA4.

Seleccionamos Juego de Windows (4.0) tal y como se muestra en la pantalla siguiente: 


(Haz click para agrandar)

Esto nos crea una solución "básica" de XNA:


(Haz click para agrandar)

Y cuando la ejecutamos nos sale la "típica" ventana con el fondo azul:

Hasta aquí todo normal. Si has seguido las entradas anteriores sobre programación usando XNA o conoces un poquito esta SDK verás que no hay nada "nuevo" al respecto.

Sin embargo a partir de aquí es donde empieza lo bueno.

Nosotros queremos "pintar" usando XNA, pero no en ese "formulario" (de hecho, esa pantalla "azul" no es un formulario) para poder poner nuestros botones, labels, etc.

Lo que tendremos que hacer es eliminar (si, has leído bien) los siguientes archivos de la solución:

Game1.vb  (Game1.cs en C#)
GameThumbnail.png
Program.vb (program.cs en C#)

 


(Haz click para agrandar)

Una vez eliminados esos 3 archivos nuestro explorador de soluciones quedará tal que así:


(Haz click para agrandar)

Ahora agregaremos un nuevo elemento, en este caso un Windows Form:


(Haz click para agrandar)

Lo llamaremos por ejemplo FrmMain.vb


(Haz click para agrandar)

Una vez añadido el formulario nuestra solución tendrá el siguiente aspecto:


(Haz click para agrandar)

A continuación iremos a las propiedades del proyecto:


(Haz click para agrandar)

La pestaña Aplicacióndebería ser algo como esto:


(Haz click para agrandar)

Lo que deberemos hacer es marcar la casilla Habilitar marco de trabajo de la aplicación

Al hacerlo se mostrará el siguiente mensaje de error (es posible que salga dos veces)

Una vez aceptado el mensaje anterior, la pestaña Aplicación debería ser algo como esto:


(Haz click para agrandar)

Guardamos los cambios y proseguimos.

Ahora vamos a cargar una serie de recursos en el "Game Content" para poder usarlos desde XNA. No me extenderé en ello puesto que ya lo hemos visto en las entradas anteriores.

Botón derecho sobre XNAWinFormsTutorialContent >> Agregar >> Elemento existente…


(Haz click para agrandar)

En este caso he cargado unos cuantos *.png y *.jpg que estaban en la carpeta "Gráficos":


(Haz click para agrandar)

Por último añadiremos una "fuente" para escribir mediante XNA.

Al igual que antes, botón derecho sobre XNAWinFormsTutorial1Content >> Agregar >> Nuevo elemento…


(Haz click para agrandar)

En este caso elegimos una Fuente de Sprite a la que llamamos debug.spritefont:


(Haz click para agrandar)

Al crear la fuente se muestra un "XML" con información de la fuente:


(Haz click para agrandar)

En este caso he cambiado el tipo de fuente por defecto por la fuente "Arial", el tamaño lo he puesto un poco más pequeño (8) y en CharacterRegion he cambiado el valor de End (de ~) al valor ñ para de esta forma poder escribir la ñ y carácteres con acentos:


(Haz click para agrandar)

A continuación necesitamos una pequeña clase para poder usar todos estos elementos que hemos añadido al "Game Content". Para ello añadimos un nuevo elemento >> Clase y la llamamos por ejemplo clsContent.vb:


(Haz click para agrandar)

El código completo está aquí (pastebin)

Bien, volvamos a nuestro formulario FrmMain. Hacemos el formulario un poco más grande y añadimos un PictureBox al que llamaremos por ejemplo pbScreen:


(Haz click para agrandar)

Si ahora vamos a la parte del código de ese formulario deberemos declarar una serie de objetos:


(Haz click para agrandar)

En el Form_Load deberemos inicializar esos objetos, de eso se encarga la función InitGFX a la cual se le pasa el Picturebox donde se va a dibujar mediante XNA

Si la función se ejecuta correctamente se llama a GLoop, que por decirlo de alguna forma es el "bucle principal de nuestra aplicación"

La función InitGFX ( PicturebBox ) es la siguiente:


(Haz click para agrandar)

Dentro de esta función verás que se llama a LoadGFX() que es donde se cargan los gráficos y fuentes que hemos añadido anteriormente al "Game Content"

La función LoadGFX() es la siguiente:


(Haz click para agrandar)

Cómo puedes ver, el los recursos que se cargan del "Game Content" se hacen prácticamente igual (por no decir igual) que en una aplicación "no Windows Form de XNA"

Nuestro "bucle principal" báscicamente se encarga de dibujar (aquí iría la "lógica" de nuestro programa, control de teclado, "updates", etc)


(Haz click para agrandar)

Y esta sería la rutina de dibujado:


(Haz click para agrandar)

…lo típico, se borra la pantalla (en negro en este caso), se inicia un spriteBatch, se pinta, se cierra el spriteBatch y se hace un Present del dispositivo gráfico

Por último y para que el programa "no se quede colgao" se establece esto en el FormClosing


(Haz click para agrandar)

El código completo del formulario lo podéis encontar aquí (pastebin)

Si ahora ejecutamos nuestro programa veremos lo siguiente:


(Haz click para agrandar)

Dentro del picturebox se muestra el "background" que y el texto "Hola Mundo!!!" tal  y como se muestra en el procedimiento Draw()

SB.Draw(bg, Vector2.Zero, Color.White)
SB.DrawString(debugfont, "Hola Mnudo!!!", New Vector2(10, 4), Color.White)

Cómo véis, más simple que el mecanismo de un chupete 😀

 

Bonus Track

Bien, ahora que ya sabemos dibujar cosillas en nuestro PictureBox, vamos a liarla parda 😀

Vamos a hacer un "sistema de partículas" que se dibuje en nuestro PictureBox y que en función de una serie de controles que hay en nuestro formulario, dicho sistema de partículas se comporte de una forma u otra.

En nuestro formulario añadimos los controles pertientes. Quedaría algo como esto:


(Haz click para agrandar)

Nuestras partículas tienen varias propiedades:

"Textura"
"Vida"
"Velocidad"
"Ángulo de rotación"
"Tamaño"
"Color"
etc.

Básicamente lo que se hace es generar una serie de partículas (la clase Particle.vb se encarga de eso) con unos valores iniciales de forma aleatoria.
De forma periódica se van incrementando o decrementando alguna de esas propiedades.
Cuando se cumple cierta condición (por ejemplo la "vida de la partícula" es 0 se elimina dicha partícula de la Lista (Of particulas). De esta forma se mantiene un nivel "constante" de partículas y no crecen infinitamente en nuetra lista de partículas.

Parece complicado pero si examinas el código verás que es realmente una "tontería"

Pues bien, al mover el ratón sobre el PictureBox observarás como se comportan las partículas. A continuación tres ejemplos con disitintos parámetros activados. 

Ejemplo 1/3:


(Haz click para agrandar)

Ejemplo 2/3:


(Haz click para agrandar)

Ejemplo 3/3


(Haz click para agrandar)

Lo "bueno" del asunto es que el sistema de partículas se mueve increiblemente suave a 60 FPS (si bueno, 59.9999 en mi caso 😀 )

Aquí podéis ver un vídeo del sistema en movimiento. Ya advierto que la captura con el CamStudio hace que los frames bajen mucho y se notan "saltos", pero esto es porque está el CamStudio grabando el video. 

Si te bajas el código fuente de ejemplo que encontrarás al final de esta entrega y lo ejecutas, verás que realmente el ejemplo se ejecuta muy pero que muy suave

 

 

Bueno, pues cómo habrás visto, no es tan "complicado" usar XNA desde VB.NET y tampoco desde una aplicación "Windows Form"

Desde aquí os animo a que "trasteéis" con el código y preguntéis cualquier duda o cuestión

 

PD: ¿Quien era el que decía que con VB.NET no se pueden hacer cosas "chulas"? 😀

 

Saludos.
mov eax,ollydbg; Int 13h  

 

Descargar  NET Tutorial 53
(149 KB. Requiere Visual Studio 2010 / XNA 4)