
Antes de empezar a leer este post puedes consultar el post Estructura básica de un VJ para entender mejor los bloques de código que constituyen un video juego y la diferencia con un programa clásico.
En el post anterior creamos un nuevo proyecto y pudimos probar que al ejecutarlo nos generaba una ventana en modo gráfico que para nosotros fue el hola mundo gráfico, a continuación vamos a analizar los archivos que nos ha generado pero antes que nada me gustaría hacer unas modificaciones en el código.
Como pudimos ver anteriormente al generarse el proyecto se crearon varias carpetas y archivos, primero que nada demos doble clic en el archivo Game1.cs para abrir el código en la ventana principal. El nombre Game1 es el nombre por defecto asignado a nuestra clase principal y al archivo que la contiene. Si queremos cambiar el nombre de esta clase no basta con solo cambiar el nombre en la clase ya que existen varias partes en el proyecto en las que se hace referencia a este nombre. Para poder cambiar todas las referencias sin tener que buscarlas una por una tenemos que seleccionar el nombre de la clase y presionar F2 para que aparezca una ventana, ahí podemos cambiar el nombre en todas las referencias del código, sin embargo, el nombre de archivo lo tenemos que cambiar directamente del lado derecho.
Para el ejemplo yo cambiaré el nombre a Engine.
A continuación vamos a analizar las clases Program.cs y Engine.cs
Program.cs
La clase Program será con la que se inicie la ejecución del programa, básicamente la vamos a utilizar para invocar a nuestra clase principal que contendrá todo el código de nuestro juego.
El código base que se generó al crear el proyecto es el siguiente.
1 using System;
2
3 namespace WindowsGame1
4 {
5 static class Program
6 {
7 /// <summary>
8 /// The main entry point for the application.
9 /// </summary>
10
11 static void Main(string[] args)
12 {
13 using (Engine game = new Engine())
14 {
15 game.Run();
16 }
17 }
18 }
19 }
En la línea 1 le decimos al compilador que vamos a ocupar el namespace System que contiene librerías básicas para la creación de proyectos. Para conocer las clases que incluye puedes consultar la ayuda de Microsoft aquí.
En la línea 3 se declara nuestro namespace el cual tiene el mismo nombre que nuestro proyecto.
En la línea 5 se declara la clase Program que tiene el mismo nombre del archivo
En la línea 11 se encuentra el método Main() que será nuestro punto de partida del juego, el código (string[] args) que se encuentra como parámetros de entrada se utiliza para mandar comandos por línea de comandos al ejecutar el juego, por ejemplo si al terminar nuestro proyecto tenemos un archivo ejecutable llamo Mijuego.exe podríamos escribir
MiJuego Parm1,Parm2
Los dos parámetros que escribamos aquí se guardaran en el arreglo args y podremos ocuparlos como queramos.
Dentro del método Main() se encuentra una instancia a la clase Engine y una llamada al método Run() de la misma. El análisis de la clase Engine lo veremos más adelante.
Otra cosa interesante en este código es que nosotros sabemos que al declarar una clase es necesario instanciar un objeto para poder acceder a sus métodos y parámetros; si aplicamos esta regla al código que estamos analizando ahora necesitaríamos instanciar un objeto de la clase Program y llamar al método Main() a través del mismo. Para evitar esto se declaran tanto la clase Program como el método Main() como static para poder ser invocados sin necesidad de instanciar un objeto.
Engine.cs
Como comenté antes, en esta clase se lleva a cabo el control principal del proyecto porque contiene las funciones de rendereo en pantalla, carga de recursos, etc.
Para analizar el código que se generó automáticamente voy a quitar los comentarios que incluye por default para concentrarnos en las funciones.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Audio;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.GamerServices;
8 using Microsoft.Xna.Framework.Graphics;
9 using Microsoft.Xna.Framework.Input;
10 using Microsoft.Xna.Framework.Media;
11 using Microsoft.Xna.Framework.Net;
12 using Microsoft.Xna.Framework.Storage;
13
14 namespace WindowsGame1
15 {
16 public class Engine : Microsoft.Xna.Framework.Game
17 {
18 GraphicsDeviceManager graphics;
19 SpriteBatch spriteBatch;
20
21 public Engine()
22 {
23 graphics = new GraphicsDeviceManager(this);
24 Content.RootDirectory = “Content”;
25 }
26
27 protected override void Initialize()
28 {
29 base.Initialize();
30 }
31
32 protected override void LoadContent()
33 {
34 spriteBatch = new SpriteBatch(GraphicsDevice);
35 }
36
37 protected override void UnloadContent()
38 {
39 }
40
41 protected override void Update(GameTime gameTime)
42 {
43
44 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
45 this.Exit();
46 base.Update(gameTime);
47 }
48
49 protected override void Draw(GameTime gameTime)
50 {
51 GraphicsDevice.Clear(Color.CornflowerBlue);
52 base.Draw(gameTime);
53 }
54 }
55 }
De la línea 1 a la 12 se agregan los namespace que necesitamos; estos incluyen las clases de la API de XNA que vamos a ocupar.
La línea 14 es la declaración de nuestro espacio de trabajo que es el mismo que ocupamos en Program.cs y es el mismo de nuestro proyecto.
La línea 16 contiene la declaración de nuestra clase principal que hemos nombrado Engine, esta clase hereda de la clase Microsoft.Xna.Framework.Game por lo que ya tendremos a nuestra disposición todos los métodos y características que requiere nuestro juego.
La línea 18 contiene la declaración de nuestro manejador gráfico. Básicamente es el encargado de controlar el hardware de video para desplegar la información en pantalla. Este controlador nos ahorra el trabajo de configurar el flujo de datos con la tarjeta gráfica que de otra forma sería en verdad complejo hacerlo por nuestra cuenta.
La línea 19 declara un objeto de la clase SpriteBatch que es la clase que nos ayudara para la carga de recursos gráficos.
De la línea 21 a la 25 tenemos el constructor de nuestra clase Engine en la que instanciamos nuestra manejador gráfico. Le pasamos como parámetro la palabra reservada this, para decirle con que objeto asociar el manejador que en nuestro caso será la clase Engine. La línea Content.RootDirectory = “Content”; es para indicar al compilador que la carpeta raíz donde se almacenan los recursos será la carpeta “Content”.
De la línea 27 a la 30 sobrescribimos el método Initialize() de nuestra clase base; En el cuerpo del mismo hacemos un llamado al método Initialize() de nuestra clase base, que como su nombre lo indica, iniciará todos los parámetros necesarios antes de iniciar el ciclo de ejecución del juego. Dado que se ejecuta una sola vez al iniciar el juego, aquí se deben incluir todas las inicializaciones a los parámetros que necesitemos.
De la línea 32 a la 35 se sobrescribe el método LoadContent() que se utiliza exclusivamente para cargar los recursos que vayamos a utilizar. Podríamos borrar este método y hacer nuestra carga utilizando el método Initialize() pero se incluye como un método aparte para tener más ordenado nuestro código. Como cuerpo del método se incluye la inicialización de nuestro objeto spriteBatch que declaramos previamente. Este método será invocado una sola vez en el juego.
En la línea 37 se sobrescribe el método UnloadContent() que utilizaremos para liberar la memoria de los recursos que dejemos de utilizar. Será invocado una vez al final del juego.
De la línea 41 a la 47 se sobrescribe el método Update() este es el método principal en cuanto a lógica del juego se refiere. Aquí se debe incluir por ejemplo el análisis de colisiones, el chequeo de las pulsaciones de los botones y cualquier actualización de información que se requiera durante la ejecución. El cuerpo del método solo incluye una validación del teclado que termina el juego si se presiona la tecla ESC y contiene un llamado al método Update() de la clase base.
Por último, de la línea 49 a la 53 se sobrescribe el método Draw() que es el encargado de refrescar la pantalla cada ciclo de tiempo. Se ejecuta después del método Update() para hacer la actualización gráfica del análisis hecho en este último. El cuerpo del método incluye la línea GraphicsDevice.Clear(Color.CornflowerBlue); que nos limpia la pantalla y la rellena del color azul que se muestra por default. Este puede ser cambiado por otro modificando el parámetro de entrada del método. Al final se incluye un llamado al método Draw() de la clase base.
Con esto terminamos el análisis de nuestro código, en el siguiente post empezaremos el desarrollo de un juego en 2D no olvides dejar tus comentarios, nos vemos en el siguiente post.
Piroshi
Tags: xna


