Microsoft XNA Game Estudio con C# y Visual Estudio

En este post trabajaremos con XNA Game Estudio, si como yo usted siempre ha querido crear un juego sin ser un profesional en ese ámbito; XNA Game Estudio es su solución esta herramienta se puede desarrollar sobre el Visual Estudio 2010 se puede descargar desde aquí.

Bueno haremos algo muy sencillo un juego de carreras de esos que antes se veían en 2d con la cámara desde arriba como esta imagen:

Sin título

No será perfecto pero tocaremos lo mas básico que podríamos tener en un juego; control de teclas para el movimiento de nuestro coche,  texto en el juego, control de colisiones, etc.

Comencemos, lo primero será descargar y instalar el XNA para poder hacer nuestro juego. Pero que es el XNA Game Estudio, es un producto de desarrollo de juegos creado por Microsoft que simplifica el desarrollo para plataformas de Windows y Xbox 360. Y lo mas importante es que corre sobre visual estudio programándose con C#.

Lo segundo será descargar las imágenes y sonido que usaremos sobre el juego lo descargaremos, desde aquí en un archivo .ra. Echo esto comencemos creando un nuevo proyecto le llamaremos RacingCars, si instalaste el XNA te aparecerá esto:

Snap8

Nos creara un proyecto como este:

Snap9

Estará dividido en dos partes la primera es donde programemos toda la lógica de nuestro juego, por defecto nos creara una clase Game que será donde programare este juego. Y la segunda partes como aparece entre paréntesis será el contenedor de todos los recursos de mi juego imágenes, sonidos, etc.

Abriremos la clase Game1 se vera así al quitarle todos los comentarios:

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. namespace RacingCars
  12. {
  13.     public class Game1 : Microsoft.Xna.Framework.Game
  14.     {
  15.         GraphicsDeviceManager graphics;
  16.         SpriteBatch spriteBatch;
  17.         public Game1()
  18.         {
  19.             graphics = new GraphicsDeviceManager(this);
  20.             Content.RootDirectory = «Content»;
  21.         }
  22.         protected override void Initialize()
  23.         {
  24.             base.Initialize();
  25.         }
  26.         protected override void LoadContent()
  27.         {
  28.             spriteBatch = new SpriteBatch(GraphicsDevice);
  29.         }
  30.         protected override void UnloadContent()
  31.         {
  32.         }
  33.         protected override void Update(GameTime gameTime)
  34.         {
  35.             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  36.                 this.Exit();
  37.             base.Update(gameTime);
  38.         }
  39.         protected override void Draw(GameTime gameTime)
  40.         {
  41.             GraphicsDevice.Clear(Color.CornflowerBlue);
  42.             base.Draw(gameTime);
  43.         }
  44.     }
  45. }

Ahora cargaremos los recursos que descargamos anteriormente los sonidos y las imágenes que ocupare.

Snap10

Snap11

Snap12

Snap13

Snap14

El proyecto queda de esta forma ya con esto solo queda programar nuestro juego.

Lo primero será declarar unas variables Textura2D que me servirá para contener las imágenes en este caso las del camino y Vector2D que me servirá para indicarle el lugar donde estará el camino.

Codigo
  1. namespace RacingCars
  2. {
  3.     public class Game1 : Microsoft.Xna.Framework.Game
  4.     {
  5.         GraphicsDeviceManager graphics;
  6.         SpriteBatch spriteBatch;
  7.         //variables para cargar el camino
  8.         Texture2D[] Camino = new Texture2D[2];
  9.         Vector2[] posCamino = new Vector2[2];
  10.         public Game1()
  11.         {
  12.             graphics = new GraphicsDeviceManager(this);
  13.             Content.RootDirectory = «Content»;
  14.         }

Creadas las variables tendremos que cargar el camino y la posición del mismo esto lo haremos el el método LoadContent(). Recordando que como es una carrera el camino tiene que dar la impresión de movimiento para ello usaremos dos veces la misma imagen del camino, así dará la idea de que este se mueve; esto lo lograremos usando un bucle for:

LoadContent
  1. protected override void LoadContent()
  2. {
  3.     spriteBatch = new SpriteBatch(GraphicsDevice);
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         Camino[i] = Content.Load<Texture2D>(«camino»);
  7.     }
  8.     posCamino[0] = Vector2.Zero;
  9.     posCamino[1] = new Vector2(0, -599);
  10. }

En este punto hemos cargado el camino pero falta hacer un método que me mueva el camino o de la impresión de movimiento a este método lo llamaremos MueveCamino().

MueveCamino
  1. protected override void LoadContent()
  2. {
  3.     spriteBatch = new SpriteBatch(GraphicsDevice);
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         Camino[i] = Content.Load<Texture2D>(«camino»);
  7.     }
  8.     posCamino[0] = Vector2.Zero;
  9.     posCamino[1] = new Vector2(0, -599);
  10. }
  11. private void MueveCamino()
  12. {
  13.     int vel = 6;
  14.     int max = graphics.PreferredBackBufferHeight;
  15.     for (int j = 0; j < 2; j++)
  16.     {
  17.         posCamino[j].Y += vel;
  18.         if (posCamino[j].Y > max)
  19.             posCamino[j].Y = -595;
  20.     }
  21. }

La variable vel me servirá para decirle la velocidad del camino a mayor numero mas velocidad y max contendrá el tamaño máximo en el alto que puede tener este camino. Ya tenemos el método pero tenemos que llamarlo desde alguna parte de la clase en este caso del método Update:

Codigo
  1. protected override void Update(GameTime gameTime)
  2. {
  3.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  4.         this.Exit();
  5.     MueveCamino();
  6.     base.Update(gameTime);
  7. }

Con esto solo queda dibujar nuestra animación para ello lo haremos dentro del método Draw(), de la clase este método cuenta con tres métodos que podemos utilizar Begin(), Draw() y End(). estos métodos sirven para iniciar, dibujar y terminar nuestra animación. Si lo programamos queda así:

Codigo
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.End();
  8.     base.Draw(gameTime);
  9. }

Si lo corremos lograríamos ver el camino y dar la impresión de movimiento:

Snap18

Lo grado esto falta la manipulación del teclado o en caso de un proyecto para Xbox 360 el estado del control. Pero primero al igual que el camino tenemos que crear unas variables para la textura y el vector de nuestro carro.

Codigo
  1. namespace RacingCars
  2. {
  3.     public class Game1 : Microsoft.Xna.Framework.Game
  4.     {
  5.         GraphicsDeviceManager graphics;
  6.         SpriteBatch spriteBatch;
  7.         //variables para cargar el camino
  8.         Texture2D[] Camino = new Texture2D[2];
  9.         Vector2[] posCamino = new Vector2[2];
  10.         //variables de carro
  11.         Texture2D Carro;
  12.         Vector2 posCarro;
  13.         int maxIzq = 349;
  14.         int maxDer = 446;

Las otras dos variables me servirán para dar el ancho de mi camino para que no se salga del mismo. Al igual que el camino lo primero que haremos será cargar nuestra imagen del carro3, asi que lo haremos en el LoadContent.

Codigo
  1. protected override void LoadContent()
  2. {
  3.     spriteBatch = new SpriteBatch(GraphicsDevice);
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         Camino[i] = Content.Load<Texture2D>(«camino»);
  7.     }
  8.     Carro = Content.Load<Texture2D>(«carro3»);
  9.     posCarro = new Vector2(350, 300);
  10.     posCamino[0] = Vector2.Zero;
  11.     posCamino[1] = new Vector2(0, -599);
  12. }

La variable carro carga la imagen del carro y la variable poscarro indica donde tiene que aparecer el carro al iniciar el juego. Echo esto lo que resta es hacer la manipulación del carro a través del teclado, esto lo lograremos colocando esto en el método Update() nos quedaría de esta forma:

Codigo
  1. protected override void Update(GameTime gameTime)
  2. {
  3.     KeyboardState estadoTeclado = Keyboard.GetState();
  4.     if (estadoTeclado.IsKeyDown(Keys.Left))
  5.     {
  6.         posCarro.X -= 4;
  7.         if (posCarro.X < maxIzq)
  8.             posCarro.X = maxIzq;
  9.     }
  10.     else if (estadoTeclado.IsKeyDown(Keys.Right))
  11.     {
  12.         posCarro.X += 4;
  13.         if (posCarro.X > maxDer)
  14.             posCarro.X = maxDer;
  15.     }
  16.     else if (estadoTeclado.IsKeyDown(Keys.Up))
  17.     {
  18.         posCarro.Y -= 3;
  19.         if (posCarro.Y < 0)
  20.             posCarro.Y = 0;
  21.     }
  22.     else if (estadoTeclado.IsKeyDown(Keys.Down))
  23.     {
  24.         posCarro.Y += 3;
  25.         if (posCarro.Y > 460)
  26.             posCarro.Y = 460;
  27.     }
  28.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  29.         this.Exit();
  30.     MueveCamino();
  31.     base.Update(gameTime);
  32. }

Ya que hemos echo esto solo queda dibujar nuestro caro en el juego:

Codigo
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.Draw(Carro, posCarro, Color.White);
  8.     spriteBatch.End();
  9.     base.Draw(gameTime);
  10. }

Si compilamos y corremos veremos que ya podemos manipular nuestro carro:

Snap19

Pero que nuestro carro aparezca solo no tiene nada de emocionante así que pongamos unos coches que le pongan algo de presión a nuestro juego. Lo primero que hacemos será crear unos vectores y texturas para nuestros carros además de otras variables de esta forma:

Codigo
  1. public class Game1 : Microsoft.Xna.Framework.Game
  2. {
  3.     GraphicsDeviceManager graphics;
  4.     SpriteBatch spriteBatch;
  5.     //variables para cargar el camino
  6.     Texture2D[] Camino = new Texture2D[2];
  7.     Vector2[] posCamino = new Vector2[2];
  8.     //variables de carro
  9.     Texture2D Carro;
  10.     Vector2 posCarro;
  11.     int maxIzq = 349;
  12.     int maxDer = 446;
  13.     //variables de los autos
  14.     Texture2D[] Coches = new Texture2D[2];
  15.     Vector2[] posCoches = new Vector2[2];
  16.     //donde apareceran los autos en el eje X y en Y
  17.     int[] posX = { 350, 441 };
  18.     int posAleatoria;
  19.     //variable para determinar la posicion aleatoria
  20.     Random ran = new Random();
  21.     //rectangulo de los otros coches
  22.     Rectangle[] recCoches = new Rectangle[2];
  23.     //variable bool de deteccion de colision
  24.     bool deteccionActiva = true;
  25.     //velocidad de los coches
  26.     int velCoches = 10;

Como lo puedes ver así como se hizo anteriormente se creara dos vectores y dos texturas como se hizo en el camino aquí también y a sí tendremos dos autos con los que puede colisionar nuestro carro. Ya con nuestras variables solo tendríamos que ocuparlas de esta forma:

Primero carguemos en el método LoadContent los caros que queremos que sirvan de obstáculo en nuestro juego.

Codigo
  1. protected override void LoadContent()
  2. {
  3.     spriteBatch = new SpriteBatch(GraphicsDevice);
  4.     //Carga el camino
  5.     for (int i = 0; i < 2; i++)
  6.     {
  7.         Camino[i] = Content.Load<Texture2D>(«camino»);
  8.     }
  9.     //carga los otros carros
  10.     for (int i = 0; i < 2; i++)
  11.     {
  12.         Coches[i] = Content.Load<Texture2D>(«carro2»);
  13.         posAleatoria = ran.Next(-1000, 0);
  14.         posCoches[i].Y = posAleatoria;
  15.         posAleatoria = ran.Next(0, 2);
  16.         posCoches[i].X = posX[posAleatoria];
  17.     }
  18.     //carga el carro que se maneja
  19.     Carro = Content.Load<Texture2D>(«carro3»);
  20.     posCarro = new Vector2(350, 300);
  21.     posCamino[0] = Vector2.Zero;
  22.     posCamino[1] = new Vector2(0, -599);
  23. }

Ya que tenemos cargados los carros solo hay que hacer que se muevan así como hicimos con el camino,  tendremos que crear un método que me mueva los carros de esta forma:

Codigo
  1. private void MueveOtrosAutos()
  2. {
  3.     int maxHeight = graphics.PreferredBackBufferHeight;
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         posCoches[i].Y += velCoches;
  7.         if (posCoches[i].Y > maxHeight)
  8.         {
  9.             posAleatoria = ran.Next(-1000, 1);
  10.             posCoches[i].Y = posAleatoria;
  11.             posAleatoria = ran.Next(0, 2);
  12.             posCoches[i].X = posX[posAleatoria];
  13.         }
  14.     }
  15. }

Ahora solo queda dibujar los carros en la pantalla y cargar el movimiento de los carros eso lo haremos en el método Draw y el método  update así:

update
  1. protected override void Update(GameTime gameTime)
  2. {
  3.     KeyboardState estadoTeclado = Keyboard.GetState();
  4.     if (estadoTeclado.IsKeyDown(Keys.Left))
  5.     {
  6.         posCarro.X -= 4;
  7.         if (posCarro.X < maxIzq)
  8.             posCarro.X = maxIzq;
  9.     }
  10.     else if (estadoTeclado.IsKeyDown(Keys.Right))
  11.     {
  12.         posCarro.X += 4;
  13.         if (posCarro.X > maxDer)
  14.             posCarro.X = maxDer;
  15.     }
  16.     else if (estadoTeclado.IsKeyDown(Keys.Up))
  17.     {
  18.         posCarro.Y -= 3;
  19.         if (posCarro.Y < 0)
  20.             posCarro.Y = 0;
  21.     }
  22.     else if (estadoTeclado.IsKeyDown(Keys.Down))
  23.     {
  24.         posCarro.Y += 3;
  25.         if (posCarro.Y > 460)
  26.             posCarro.Y = 460;
  27.     }
  28.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  29.         this.Exit();
  30.     MueveCamino();
  31.     MueveOtrosAutos();
  32.     base.Update(gameTime);
  33. }
Draw
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.Draw(Carro, posCarro, Color.White);
  8.     for (int i = 0; i < 2; i++)
  9.     {
  10.         spriteBatch.Draw(Coches[i], posCoches[i], Color.White);
  11.     }
  12.     spriteBatch.End();
  13.     base.Draw(gameTime);
  14. }

Hoy ya se esta completando el juego en este momento somos capaces de ver para donde va el asunto, en este punto meteremos el control de colisiones para que sea mas interesante el juego. Esto nos servirá para ver cuando perdimos y lo bueno que somos conduciendo, como lo hemos echo antes hay que cargar esto el el método update() así:

Codigo
  1. protected override void Update(GameTime gameTime)
  2. {
  3.     Rectangle recCarro = new Rectangle((int)posCarro.X, (int)posCarro.Y, Carro.Width, Carro.Height);
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  7.         Coches[i].Width, Coches[i].Height);
  8.     }
  9.     for (int i = 0; i < 2; i++)
  10.     {
  11.         recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  12.         Coches[i].Width, Coches[i].Height);
  13.     }
  14.     for (int j = 0; j < 2; j++)
  15.     {
  16.         if (recCarro.Intersects(recCoches[j]))
  17.             deteccionActiva = false;
  18.     }
  19.     KeyboardState estadoTeclado = Keyboard.GetState();
  20.     if (estadoTeclado.IsKeyDown(Keys.Left))
  21.     {
  22.         posCarro.X -= 4;
  23.         if (posCarro.X < maxIzq)
  24.             posCarro.X = maxIzq;
  25.     }
  26.     else if (estadoTeclado.IsKeyDown(Keys.Right))
  27.     {
  28.         posCarro.X += 4;
  29.         if (posCarro.X > maxDer)
  30.             posCarro.X = maxDer;
  31.     }
  32.     else if (estadoTeclado.IsKeyDown(Keys.Up))
  33.     {
  34.         posCarro.Y -= 3;
  35.         if (posCarro.Y < 0)
  36.             posCarro.Y = 0;
  37.     }
  38.     else if (estadoTeclado.IsKeyDown(Keys.Down))
  39.     {
  40.         posCarro.Y += 3;
  41.         if (posCarro.Y > 460)
  42.             posCarro.Y = 460;
  43.     }
  44.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  45.         this.Exit();
  46.     MueveCamino();
  47.     MueveOtrosAutos();
  48.     base.Update(gameTime);
  49. }

Ahora solo hay que identificar esto en el método Draw para que reconozca las colisiones de nuestro coche, para ello haremos esto:

Codigo
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.Draw(Carro, posCarro, Color.White);
  8.     for (int i = 0; i < 2; i++)
  9.     {
  10.         spriteBatch.Draw(Coches[i], posCoches[i], Color.White);
  11.     }
  12.     if (deteccionActiva == true)
  13.     {
  14.         spriteBatch.Draw(Carro, posCarro, Color.White);
  15.     }
  16.     else if (deteccionActiva == false)
  17.     {
  18.         spriteBatch.Draw(Carro, posCarro, Color.White);
  19.         deteccionActiva = true;
  20.         base.ResetElapsedTime();
  21.         base.Exit();
  22.     }
  23.     spriteBatch.End();
  24.     base.Draw(gameTime);
  25. }

En el if si la deteccionactiva es false se cierra el juego. si lo corremos ya podremos jugar con el mismo y veremos que tan bueno somos. Ahora solo queda agregarle unos efectos como texto y sonido comencemos con el texto en pantalla como el medidor de velocidad.

Para escribir texto en la pantalla tendremos que agregar una nueva variable:

Codigo
  1. public class Game1 : Microsoft.Xna.Framework.Game
  2. {
  3.     GraphicsDeviceManager graphics;
  4.     SpriteBatch spriteBatch;
  5.     //variables para cargar el camino
  6.     Texture2D[] Camino = new Texture2D[2];
  7.     Vector2[] posCamino = new Vector2[2];
  8.     //variables de carro
  9.     Texture2D Carro;
  10.     Vector2 posCarro;
  11.     int maxIzq = 349;
  12.     int maxDer = 446;
  13.     //variables de los autos
  14.     Texture2D[] Coches = new Texture2D[2];
  15.     Vector2[] posCoches = new Vector2[2];
  16.     //donde apareceran los autos en el eje X y en Y
  17.     int[] posX = { 350, 441 };
  18.     int posAleatoria;
  19.     //variable para determinar la posicion aleatoria
  20.     Random ran = new Random();
  21.     //rectangulo de los otros coches
  22.     Rectangle[] recCoches = new Rectangle[2];
  23.     //variable bool de deteccion de colision
  24.     bool deteccionActiva = true;
  25.     //velocidad de los coches
  26.     int velCoches = 10;
  27.     //spritefotn para la velocidad
  28.     SpriteFont velCarroText;

Echo esto tenemos que cargar el siguiente elemento en nuestra solución.

Snap21

Snap23

Si abrimos este archivo encontraremos varias propiedades que podemos utilizar. Como tamaño de letra, el estilo, el espacio, el tipo de letra, etc.

Codigo
  1. <?xmlversion=«1.0«encoding=«utf-8«?>
  2. <XnaContentxmlns:Graphics=«Microsoft.Xna.Framework.Content.Pipeline.Graphics«>
  3.   <AssetType=«Graphics:FontDescription«>
  4.     <FontName>Arial</FontName>
  5.     <Size>14</Size>
  6.     <Spacing>0</Spacing>
  7.     <UseKerning>true</UseKerning>
  8.     <Style>Bold</Style>
  9.     <CharacterRegions>
  10.       <CharacterRegion>
  11.         <Start></Start>
  12.         <End>~</End>
  13.       </CharacterRegion>
  14.     </CharacterRegions>
  15.   </Asset>
  16. </XnaContent>

Borrando los comentarios quedaría así como pueden ver cambie el tipo de letra por Arial y la letra en negrita. ya que tenemos nuestro archivo de texto hay que cargarlo en el método Loadcontent().

Codigo
  1. protected override void LoadContent()
  2. {
  3.     //carga del texto
  4.     velCarroText = Content.Load<SpriteFont>(«Velocidad»);
  5.     spriteBatch = new SpriteBatch(GraphicsDevice);
  6.     //Carga el camino
  7.     for (int i = 0; i < 2; i++)
  8.     {
  9.         Camino[i] = Content.Load<Texture2D>(«camino»);
  10.     }
  11.     //carga los otros carros
  12.     for (int i = 0; i < 2; i++)
  13.     {
  14.         Coches[i] = Content.Load<Texture2D>(«carro2»);
  15.         posAleatoria = ran.Next(-1000, 0);
  16.         posCoches[i].Y = posAleatoria;
  17.         posAleatoria = ran.Next(0, 2);
  18.         posCoches[i].X = posX[posAleatoria];
  19.     }
  20.     //carga el carro que se maneja
  21.     Carro = Content.Load<Texture2D>(«carro3»);
  22.     posCarro = new Vector2(350, 300);
  23.     posCamino[0] = Vector2.Zero;
  24.     posCamino[1] = new Vector2(0, -599);
  25. }

Ahora hay que dibujarlo en el juego de esta forma:

Codigo
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.Draw(Carro, posCarro, Color.White);
  8.     for (int i = 0; i < 2; i++)
  9.     {
  10.         spriteBatch.Draw(Coches[i], posCoches[i], Color.White);
  11.     }
  12.     if (deteccionActiva == true)
  13.     {
  14.         spriteBatch.Draw(Carro, posCarro, Color.White);
  15.     }
  16.     else if (deteccionActiva == false)
  17.     {
  18.         spriteBatch.Draw(Carro, posCarro, Color.White);
  19.         deteccionActiva = true;
  20.         base.ResetElapsedTime();
  21.         base.Exit();
  22.     }
  23.     //mostrar el texto
  24.     spriteBatch.DrawString(velCarroText, «Velocidad : «, new Vector2(650, 0), Color.White);
  25.     spriteBatch.End();
  26.     base.Draw(gameTime);
  27. }

Ya pusimos el texto hoy hay que hacer que me muestre la velocidad del carro. para ello inicializaremos una variable que me mida la velocidad y comenzara en cero. para que acelere y desacelere el velocímetro utilizaremos lo que programamos en el método update() para mover el carro en este caso la tecla hacia arriba para acelerar y la tecla hacia bajo para desacelerar así:

Codigo
  1. public class Game1 : Microsoft.Xna.Framework.Game
  2. {
  3.     GraphicsDeviceManager graphics;
  4.     SpriteBatch spriteBatch;
  5.     //variables para cargar el camino
  6.     Texture2D[] Camino = new Texture2D[2];
  7.     Vector2[] posCamino = new Vector2[2];
  8.     //variables de carro
  9.     Texture2D Carro;
  10.     Vector2 posCarro;
  11.     int maxIzq = 349;
  12.     int maxDer = 446;
  13.     //variables de los autos
  14.     Texture2D[] Coches = new Texture2D[2];
  15.     Vector2[] posCoches = new Vector2[2];
  16.     //donde apareceran los autos en el eje X y en Y
  17.     int[] posX = { 350, 441 };
  18.     int posAleatoria;
  19.     //variable para determinar la posicion aleatoria
  20.     Random ran = new Random();
  21.     //rectangulo de los otros coches
  22.     Rectangle[] recCoches = new Rectangle[2];
  23.     //variable bool de deteccion de colision
  24.     bool deteccionActiva = true;
  25.     //velocidad de los coches
  26.     int velCoches = 10;
  27.     //spritefotn para la velocidad
  28.     SpriteFont velCarroText;
  29.     //velocidad de carro
  30.     int velocidadCarro = 0;
Codigo
  1. protected override void Update(GameTime gameTime)
  2. {
  3.     Rectangle recCarro = new Rectangle((int)posCarro.X, (int)posCarro.Y, Carro.Width, Carro.Height);
  4.     for (int i = 0; i < 2; i++)
  5.     {
  6.         recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  7.         Coches[i].Width, Coches[i].Height);
  8.     }
  9.     for (int i = 0; i < 2; i++)
  10.     {
  11.         recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  12.         Coches[i].Width, Coches[i].Height);
  13.     }
  14.     for (int j = 0; j < 2; j++)
  15.     {
  16.         if (recCarro.Intersects(recCoches[j]))
  17.             deteccionActiva = false;
  18.     }
  19.     KeyboardState estadoTeclado = Keyboard.GetState();
  20.     if (estadoTeclado.IsKeyDown(Keys.Left))
  21.     {
  22.         posCarro.X -= 4;
  23.         if (posCarro.X < maxIzq)
  24.             posCarro.X = maxIzq;
  25.     }
  26.     else if (estadoTeclado.IsKeyDown(Keys.Right))
  27.     {
  28.         posCarro.X += 4;
  29.         if (posCarro.X > maxDer)
  30.             posCarro.X = maxDer;
  31.     }
  32.     else if (estadoTeclado.IsKeyDown(Keys.Up))
  33.     {
  34.         //velocimetro acelerar el carro
  35.         velocidadCarro++;
  36.         if (velocidadCarro > 10)
  37.             velocidadCarro = 10;
  38.         posCarro.Y -= 3;
  39.         if (posCarro.Y < 0)
  40.             posCarro.Y = 0;
  41.     }
  42.     else if (estadoTeclado.IsKeyDown(Keys.Down))
  43.     {
  44.         //velocimetro desacelerar el carro
  45.         velocidadCarro -= 1;
  46.         if (velocidadCarro < 0)
  47.             velocidadCarro = 0;
  48.         posCarro.Y += 3;
  49.         if (posCarro.Y > 460)
  50.             posCarro.Y = 460;
  51.     }
  52.     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  53.         this.Exit();
  54.     MueveCamino();
  55.     MueveOtrosAutos();
  56.     base.Update(gameTime);
  57. }

Y para que lo muestre en pantalla solo cambiamos la línea en el método Draw que me mostraba el texto de esta forma.

Codigo
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     GraphicsDevice.Clear(Color.CornflowerBlue);
  4.     spriteBatch.Begin();
  5.     for (int i = 0; i < 2; i++)
  6.         spriteBatch.Draw(Camino[i], posCamino[i], Color.White);
  7.     spriteBatch.Draw(Carro, posCarro, Color.White);
  8.     for (int i = 0; i < 2; i++)
  9.     {
  10.         spriteBatch.Draw(Coches[i], posCoches[i], Color.White);
  11.     }
  12.     if (deteccionActiva == true)
  13.     {
  14.         spriteBatch.Draw(Carro, posCarro, Color.White);
  15.     }
  16.     else if (deteccionActiva == false)
  17.     {
  18.         spriteBatch.Draw(Carro, posCarro, Color.White);
  19.         deteccionActiva = true;
  20.         base.ResetElapsedTime();
  21.         base.Exit();
  22.     }
  23.     //mostrar el texto
  24.     spriteBatch.DrawString(velCarroText, «Velocidad : « + velocidadCarro.ToString(), new Vector2(650, 0), Color.White);
  25.     spriteBatch.End();
  26.     base.Draw(gameTime);
  27. }

Ya no queda mucho por hacer solo colocarle un sonido cuando acelera el caro para eso usare el archivo Motor.wav que tengo en mi carpeta de sonidos. para ello al instalar esta aplicación también me instaló Microsoft Cross-Plataform Audio Creation Tool (XACT) que viene adjunto en la instalación de XNA, que nos sirve para preparar nuestros sonidos para el juego. Solo tenemos que abrirlo:

  • botón inicio.

Snap24

  • Todos los Programas y escogemos esto.

Sin 1título

Nos abrirá esto:

Snap26

Aquí creamos un Nuevo Wave Bank que va a contener nuestros archivos de sonido y agregaremos los sonido que ocuparemos en nuestro juego. Pero antes creemos un nuevo proyecto de sonidos y los guardamos en la carpeta del proyecto que creamos “sonidos”.

Snap27

Snap29

En este Wave Banks insertemos nuestros sonidos para el juego.

Snap30

Snap31

Snap32

Ahora crearemos un Sound Banks donde crearemos los archivos de sonidos a partir del sonido original.

Snap33

Snap34

Al hacer esto se nos abrirá esta ventana:

Snap35

Hoy solo queda arrastrar el sonido a la segunda parte de la ventana de abajo y automáticamente aparecerá en la primera parte.

Snap36

Ahora que ya tenemos los archivos en el Cue, vamos a abrir el XACT Auditioning Utility, Para esto vamos a Inicio Programas- XNA 2.0- Tools – XACT Auditioning Utility, nos aparece algo así:

Sin 1título

Snap39

Con esto lograremos la conexión con el proyecto que tenemos en XACT, ahora solo resta seleccionar nuestro sonido de motor y reproducirlo y observamos cómo se conecta el XACT Auditioning Utility. Ya por utimo tenemos que construir nuestro proyecto, para esto damos clic en File->Build. Listo ya tenemos preparados nuestros sonidos.

Snap40

Snap41

Los sonidos creados están guardados en la carpeta del proyecto sonidos veamos:

Snap42

Ya creado nuestros sonidos para el proyecto solo hay que utilizarlo en nuestro proyecto. Para eso hay que declarar unas variables.

Codigo
  1. GraphicsDeviceManager graphics;
  2. SpriteBatch spriteBatch;
  3. //variables para cargar el camino
  4. Texture2D[] Camino = new Texture2D[2];
  5. Vector2[] posCamino = new Vector2[2];
  6. //variables de carro
  7. Texture2D Carro;
  8. Vector2 posCarro;
  9. int maxIzq = 349;
  10. int maxDer = 446;
  11. //variables de los autos
  12. Texture2D[] Coches = new Texture2D[2];
  13. Vector2[] posCoches = new Vector2[2];
  14. //donde apareceran los autos en el eje X y en Y
  15. int[] posX = { 350, 441 };
  16. int posAleatoria;
  17. //variable para determinar la posicion aleatoria
  18. Random ran = new Random();
  19. //rectangulo de los otros coches
  20. Rectangle[] recCoches = new Rectangle[2];
  21. //variable bool de deteccion de colision
  22. bool deteccionActiva = true;
  23. //velocidad de los coches
  24. int velCoches = 10;
  25. //spritefotn para la velocidad
  26. SpriteFont velCarroText;
  27. //velocidad de carro
  28. int velocidadCarro = 0;
  29. //sonidos del juego
  30. static AudioEngine audio;
  31. static WaveBank ondas;
  32. static SoundBank sonidos;

Ahora cargaremos nuestro sonidos en el LoadContent().

Codigo
  1. protected override void LoadContent()
  2. {
  3.     //cargar sonidos
  4.     audio = new AudioEngine(@»C:\Users\ulises\Documents\Visual Studio 2010\Projects\Carrera\Carrera\CarreraContent\Sonidos\Win\camaro.xgs»);
  5.     ondas = new WaveBank(audio, @»C:\Users\ulises\Documents\Visual Studio 2010\Projects\Carrera\Carrera\CarreraContent\Sonidos\Win\camaro.xwb»);
  6.     sonidos = new SoundBank(audio, @»C:\Users\ulises\Documents\Visual Studio 2010\Projects\Carrera\Carrera\CarreraContent\Sonidos\Win\camaro.xsb»);
  7.     //carga del texto
  8.     velCarroText = Content.Load<SpriteFont>(«Velocidad»);
  9.     spriteBatch = new SpriteBatch(GraphicsDevice);
  10.     //Carga el camino
  11.     for (int i = 0; i < 2; i++)
  12.     {
  13.         Camino[i] = Content.Load<Texture2D>(«camino»);
  14.     }
  15.     //carga los otros carros
  16.     for (int i = 0; i < 2; i++)
  17.     {
  18.         Coches[i] = Content.Load<Texture2D>(«carro2»);
  19.         posAleatoria = ran.Next(-1000, 0);
  20.         posCoches[i].Y = posAleatoria;
  21.         posAleatoria = ran.Next(0, 2);
  22.         posCoches[i].X = posX[posAleatoria];
  23.     }
  24.     //carga el carro que se maneja
  25.     Carro = Content.Load<Texture2D>(«carro3»);
  26.     posCarro = new Vector2(350, 300);
  27.     posCamino[0] = Vector2.Zero;
  28.     posCamino[1] = new Vector2(0, -599);
  29. }

Echo esto solo queda la ejecución del sonido en el método update(), pondremos que el sonido se ejecute al acelerar el carro en el key.up.

Codigo
  1. protected override void Update(GameTime gameTime)
  2.  {
  3.      Rectangle recCarro = new Rectangle((int)posCarro.X, (int)posCarro.Y, Carro.Width, Carro.Height);
  4.      for (int i = 0; i < 2; i++)
  5.      {
  6.          recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  7.          Coches[i].Width, Coches[i].Height);
  8.      }
  9.      for (int i = 0; i < 2; i++)
  10.      {
  11.          recCoches[i] = new Rectangle((int)posCoches[i].X, (int)posCoches[i].Y,
  12.          Coches[i].Width, Coches[i].Height);
  13.      }
  14.      for (int j = 0; j < 2; j++)
  15.      {
  16.          if (recCarro.Intersects(recCoches[j]))
  17.              deteccionActiva = false;
  18.      }
  19.      KeyboardState estadoTeclado = Keyboard.GetState();
  20.      if (estadoTeclado.IsKeyDown(Keys.Left))
  21.      {
  22.          posCarro.X -= 4;
  23.          if (posCarro.X < maxIzq)
  24.              posCarro.X = maxIzq;
  25.      }
  26.      else if (estadoTeclado.IsKeyDown(Keys.Right))
  27.      {
  28.          posCarro.X += 4;
  29.          if (posCarro.X > maxDer)
  30.              posCarro.X = maxDer;
  31.      }
  32.      else if (estadoTeclado.IsKeyDown(Keys.Up))
  33.      {
  34.          //velocimetro acelerar el carro
  35.          velocidadCarro++;
  36.          if (velocidadCarro > 10)
  37.              velocidadCarro = 10;
  38.          posCarro.Y -= 3;
  39.          if (posCarro.Y < 0)
  40.              posCarro.Y = 0;
  41.          //cargar sonido
  42.          sonidos.PlayCue(«cartcar»);
  43.      }
  44.      else if (estadoTeclado.IsKeyDown(Keys.Down))
  45.      {
  46.          //velocimetro desacelerar el carro
  47.          velocidadCarro -= 1;
  48.          if (velocidadCarro < 0)
  49.              velocidadCarro = 0;
  50.          posCarro.Y += 3;
  51.          if (posCarro.Y > 460)
  52.              posCarro.Y = 460;
  53.      }
  54.      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  55.          this.Exit();
  56.      MueveCamino();
  57.      MueveOtrosAutos();
  58.      base.Update(gameTime);
  59.  }

Así esta terminado nuestro juego hoy solo queda jugar un rato para probarlo no esta perfecto todavía hay que hacerle algunas correcciones pero es funcional.

Espero que te sirva de algo…