martes, 30 de marzo de 2010

Desarrollo de un cuego 2D con XNA III - Proyecto en blanco

Ok, estimados luego de una pausa debida a contratiempos con terremotos y otras tragedias de por medio(como entrar a clases y tener que trabajar) he vuelto.

En este post veremos el esqueleto que nos entrega Visual Studio cuando creamos un proyecto de tipo "Windows Game (3.1)".

Primero, veremos que carpetas y archivos crea:

Bien pues, aquí tenemos, sin haber escrito una sola línea de código, solo indicando el tipo de proyecto que deseamos crear, esta estructura.

Tenemos en References, entre otras, las referencias a las dlls de XNA

Microsoft.Xna.Framework Microsoft.Xna.Framework.Game
Son los espacios de nombre esenciales de XNA, déjenlas tal cual por ahora.

Luego tenemos la carpeta content donde tenemos las dlls que refieren a los Pipelines, que estudiaremos mas adelante pero por lo pronto podemos decir que son los que nos permiten manejar distintos tipos de contenido que podremos agregar a esta carpeta.

Como podrán suponer por los nombres de las dlls, algunos de estos pipelines nos permitirán operar con audio, video, texturas, etc.

Luego tenemos el Game.Ico que es el ícono de nuestro programa.

Y luego tenemos 2 clases que son la médula de nuestro humilde primer proyecto en blanco:

Program.cs
Game1.cs

Program.cs es nuestra clase de entrada al juego, lo primero en ejecutarse.

En su código que incluyo aquí verán en el método Main() que lo único que hace es instanciar la clase Game1 y luego ejecuta el método Run() de la clase Game1.



   1:  using System;
   2:   
   3:  namespace JuegoXNADemo1
   4:  {
   5:      static class Program
   6:      {
   7:          /// <summary>
   8:          /// The main entry point for the application.
   9:          /// </summary>
  10:          static void Main(string[] args)
  11:          {
  12:              using (Game1 game = new Game1())
  13:              {
  14:                  game.Run();
  15:              }
  16:          }
  17:      }
  18:  }
  19:   


A continuación el contenido de la clase Game1



   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 JuegoXNADemo1
  15:  {
  16:   
  17:      public class Game1 : Microsoft.Xna.Framework.Game
  18:      {
  19:          GraphicsDeviceManager graphics;
  20:          SpriteBatch spriteBatch;
  21:   
  22:          public Game1()
  23:          {
  24:              graphics = new GraphicsDeviceManager(this);
  25:              Content.RootDirectory = "Content";
  26:          }
  27:   
  28:          /// <summary>
  29:          /// Allows the game to perform any initialization it needs to before starting to run.
  30:          /// This is where it can query for any required services and load any non-graphic
  31:          /// related content.  Calling base.Initialize will enumerate through any components
  32:          /// and initialize them as well.
  33:          /// </summary>
  34:          protected override void Initialize()
  35:          {
  36:              // TODO: Add your initialization logic here
  37:   
  38:              base.Initialize();
  39:          }
  40:   
  41:          /// <summary>
  42:          /// LoadContent will be called once per game and is the place to load
  43:          /// all of your content.
  44:          /// </summary>
  45:          protected override void LoadContent()
  46:          {
  47:              // Create a new SpriteBatch, which can be used to draw textures.
  48:              spriteBatch = new SpriteBatch(GraphicsDevice);
  49:   
  50:              // TODO: use this.Content to load your game content here
  51:          }
  52:   
  53:          /// <summary>
  54:          /// UnloadContent will be called once per game and is the place to unload
  55:          /// all content.
  56:          /// </summary>
  57:          protected override void UnloadContent()
  58:          {
  59:              // TODO: Unload any non ContentManager content here
  60:          }
  61:   
  62:          /// <summary>
  63:          /// Allows the game to run logic such as updating the world,
  64:          /// checking for collisions, gathering input, and playing audio.
  65:          /// </summary>
  66:          /// <param name="gameTime">Provides a snapshot of timing values.</param>
  67:          protected override void Update(GameTime gameTime)
  68:          {
  69:              // Allows the game to exit
  70:              if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  71:                  this.Exit();
  72:              
  73:              // TODO: Add your update logic here
  74:   
  75:              base.Update(gameTime);
  76:          }
  77:   
  78:          /// <summary>
  79:          /// This is called when the game should draw itself.
  80:          /// </summary>
  81:          /// <param name="gameTime">Provides a snapshot of timing values.</param>
  82:          protected override void Draw(GameTime gameTime)
  83:          {
  84:              GraphicsDevice.Clear(Color.CornflowerBlue);
  85:   
  86:              // TODO: Add your drawing code here
  87:   
  88:              base.Draw(gameTime);
  89:          }
  90:      }
  91:  }


El contenido de la clase Game1, como puede apreciarse, no es tan escueto como el de la clase Program.

Si nos abstraemos de detalles podemos ver la clase Game1 como lo siguiente:


  1. Primero, Game1 es una clase que hereda del espacio de nombres Microsoft.Xna.Framework.Game(El que está en nuestra carpeta de referencias del proyecto).
  2. Game1 (Y todo juego Xna que desarrollemos) tiene, cuando menos, los métodos
  • Initialize()
  • LoadContent()
  • UnloadContent()
  • Update(GameTime gameTime)
  • Draw(GameTime gameTime)
Estos métodos incluidos en Game1 nos dan una idea del ciclo de vida de esta aplicación.

  • El primer método en ejecutarse es Initialize(), en este debiésemos inicializar nuestros dispositivos y configuraciones.
  • LoadContent() Vuelca el contenido que necesitemos(gráficos, audio, etc) sobre nuestros dispositivos dejándolos disponibles para suutilización en el loop del juego.
  • El "loop del juego" está compuesto por 2 loops asíncronos que son los llevados a cabo por los métodos Update(GameTime gameTime) y Draw(GameTime gameTime).
  • En el método Update(GameTime gameTime) debemos incorporar la lógica de nuestro juego, por ejemplo: controlar si un proyectil alcanza a un personaje, calcular la trayectoria y posición de un proyectil, analizar el nivel de vida, calcular puntajes, etc.
  • En el método Draw(GameTime gameTime), en función de la data calculada en el método Update(GameTime gameTime) debiésemos "dibujar" el estado actual del juego.
  • Finalmente, una vez terminado el loop del juego, ya sea por muerte del personaje o cualquier otra condición que determine este punto de término han de descargarse los contenidos en el método UnloadContent()
Este pequeño código entregado por el proyecto en blanco ya inicia el dispositivo gráfico y establece un fondo de pantalla de color azul(CornFlowerBlue para ser mas exacto).

Si les apetece, pueden ejecutar este proyecto y verán esta ventana.



Estamos de acuerdo, no es nada muy excitante, ni nos consume el vértigo, pero créalo o no, este es su primer juego en Xna.

Bueno, eso por hoy, ya estaremos de vuelta analizando mas a fondo los métodos de la clase game

Desde la terremoteada pero aperrada tierra de Chile les saluda.

Manuel Gatica Holtmann
.

PD: No puedo terminar el post sin agradecer a quien hizo http://www.manoli.net/csharpformat/ un excelente sitio para taggear codigo para incluir en blogspot y que es el sitio que utilicé en esta ocasión para poder mostrar el código de manera decente.

-__-