martes, 14 de julio de 2015

Ciclo de Vida en MonoGame

Cuando creamos un nuevo proyecto en MonoGame, la plantilla trae la clase Game1 con varios métodos. ¿Cuándo se ejecuta cada uno? ¿Para qué sirven? Lo primero es el ciclo de vida de una aplicación o juego en nuestro caso. Una imagen que encontré lo resumen bien claro.


Como en todas las aplicaciones de C#, por defecto, el programa arranca en el método Main de la clase Program. Allí dentro, en los proyectos de MonoGame, se instancia un objeto del tipo Game y se llama a su método Run. Internamente, el primer método que se llama es Initialize. En este método hay que escribir todo el código relacionado a inicializar objetos relacionados con el juego. Inmediatamente se llama al método LoadContent una única vez, donde se carga todo lo relacionado al contenido del juego, como sprites, fuentes, audio, etc. Luego viene lo que se denomina "Game Loop" que es la repetición hasta el fin de la invocación a los métodos Update y Draw (aunque a veces no secuencialmente, pero si muchas veces por segundo) repetidamente de acuerdo al "Frame rate" que se haya especificado al inicializar.  Update debe encargarse de tomar los inputs (teclado, gamepad, touchpad) del jugador y actualizar la física, la inteligencia artificial, el estado general del juego y las animaciones, aunque no de dibujarlas, solamente decidir el cuadro o frame que se debe mostrar.  Draw es quien debe dibujar y actualizar la pantalla con lo que se debe ver. Finalmente UnloadContent es llamado cuando el juego se termina y es el encargado de liberar los recursos usados en el juego.

Como verán, es bastante simple. En Initialize lo común es iniciar el nivel, el jugador y todo lo relacionado con el juego. En LoadContent lo que se hace es cargar los recursos, por ejemplo:

 protected override void LoadContent()  
 {  
     // Create a new SpriteBatch, which can be used to draw textures.  
     spriteBatch = new SpriteBatch(GraphicsDevice);  
     fuente = Content.Load<SpriteFont>("MiFuente");
     heroe = Content.Load<Texture2D>("heroe");
 }  

En UnloadContent, iría la liberación, pero generalmente no hay recursos que necesiten ser liberados explícitamente. El grueso de nuestro juego va a estar en Update, donde vamos tomando el input del jugador y actualizando el estado del juego. Y por último en Draw va todo lo que dibujamos. Es muy importante que todas las llamadas a spriteBatch.Draw() se hagan entre los métodos spriteBatch.Begin()spriteBatch.End(), pero no repitiendo estos últimos, sino que utilizándolos una única vez (o unas pocas en algunas excepciones) y llamando a spriteBatch.Draw() varias veces entre esos métodos. ¿Y por qué es esto? Habrán escuchado que las placas de video pueden dibujar millones de polígonos, pero si uno dibuja varias veces sin el cuidado anterior, la aplicación se ralentiza. El tema es que esos millones de polígonos deben venir todos juntos de una sola vez para optimizar el proceso y eso es lo que hace el Begin y End de spriteBatch, juntar todo lo que se dibuja y dibujar una sola vez.

martes, 7 de julio de 2015

Retomando

Hace tiempo que no escribo. Última publicación 22 de septiembre de 2012... puff. Bueno tengo un montón de excusas, pero mejor vamos a escribir código con el fin de crear videojuegos. En la publicación anterior mostré como hacer el "Hola Mundo" y como escribir en XNA. Bueno resulta que eso fue hace tanto que XNA ya está descontinuado. Lo nuevo y corriente es MonoGame. En el sitio oficial pueden ver toda la información, pero en resumidas cuentas, como XNA estaba muy bueno, este proyecto lo continua y además es Open Source, por las dudas que también caiga en algún momento. Lo novedoso es que es multi-plataforma.

Cuando empecé con MonoGame, otra vez me costo un poco lograr escribir algo por pantalla. Por eso, aquí les dejo los pasos que seguí para poder hacerlo:
  1. Si no tenés instalado MonoGame, lo primero obviamente es instalarlo. 
  2. Luego crear un nuevo proyecto. En mi caso fue un proyecto MonoGame para Windows. Aclaro que para los tutoriales estoy usando Visual Studio 2010, pero debería ser similar para versiones más nuevas. 
  3. Buscar la fuente que te guste e instalarla en tu SO. Buscando encontré un enlace con fuentes de Microsoft que se pueden usar libremente, pero finalmente me terminé quedando con Lucida Console que tiene todos los caracteres del mismo tamaño y me facilita otras tareas. En este punto hay que tener cuidado con los derechos de autor, porque por más que la fuente esté en tu PC, es posible que no esté permitido utilizarla con fines comerciales. En mi caso sólo la estoy utilizando para el ejemplo y en todo caso, académicamente y sin fines de lucro.
  4. En el proyecto creado, abrir el Content.mgcb. Este archivo es el que administra el contenido relacionado a sprites, fuentes, audio, etc. Anteriormente en XNA esto se hacia con un proyecto, pero esto quedó en el pasado.
  5. Una vez abierto el archivo, nos aperece la GUI del MonoGame Content Builder. Acá podemos agregar la fuente. Para ello hay que agregar  una "SpriteFont Description", o sea una descripción de una fuente. Es una descripción de la fuente a utilizar, porque la fuente está instalada.
  6. Una vez creado el archivo con el nombre que queremos, hay que editarlo con tu editor de texto o xml favorito. Lo que hay que cambiar fundamentalmente en el texto son los valores de los elementos <FontName> y <Size>. Allí ponemos el nombre de la fuente y el tamaño deseados (en mi caso Lucida Console, tamaño 12). Hay otros elementos pero creo que los más importantes son los que mencioné.
  7. Guardar y cerrar el archivo. Ahora con los cambios listos, hay que compilar el contenido (atajo F6). Todo debería estar Ok y podemos cerrar la GUI del contenido.
  8. Con la fuente cargada en el proyecto, resta instanciar un objeto SpriteFont en nuestro juego para cargarlar y usarla para escribir. Aquí se puede ver el código completo: http://codepaste.net/g83e1g.
En el código se puede ver los métodos básicos que se usan en el ciclo de vida de un juego en MonoGame. Esto me gustaría explicarlo en un próximo post para no alargar este.

Bueno, eso fue todo para la vuelta. He retomado el código para juegos (ahora con MonoGame) y el blog. Espero hacerlo con más frecuencia y que le sirva a alguien más.

Saludos!