Creación de juegos mediante la plataforma XNA de Microsoft Visual Studio
Links para descargar material:
Parte 01: https://www.dropbox.com/s/2b3f27izg3wfqws/01.XNA.zip
Parte 02: https://www.dropbox.com/s/ep3634jsjullkbs/02.XNA.zip
Parte 03: https://www.dropbox.com/s/9e3q068t6mlkted/03.XNA.zip
Parte 04: https://www.dropbox.com/s/u4navlzlhtecjm0/04.XNA.zip
Parte 05: https://www.dropbox.com/s/oqjll5c73kbvu1j/05.XNA.zip
2. Introducción
Este será el primero de una serie de juegos que nos servirán de base para
construir nuestros propios juegos.
El juego consiste en que aparecen los escudos de los equipos de Futbol de
Medellín y Nacional (los puedes cambiar por los equipos de tu preferencia) y
aparecen una serie de balones, al azar en cualquier posición de la pantalla. El
escudo que primero tome el balón, anota un punto. El que primero tome 10
balones, gana el juego.
Cabe anotar que los dos escudos no se pueden tocar, un escudo bloquea el
otro.
3. Cree un proyecto XNA. Yo lo llame: DIM vs. NAL
Cree la carpeta Images y agregue las imágenes que utilizaremos en este proyecto:
Balon2.png, CanchaFutbol.jpg, DIM.png y NAL.png
Cree la carpeta Sound y agregue los sonidos que utilizaremos en este proyecto:
GolDIM.wav, GolNAL.wav, y Music.mp3
Cree la carpeta Fonts y cree un nuevo archivo de letras llamado Font. Cambie
estas etiquetas:
<Size>30</Size>
<Style>Bold</Style>
Ya hemos preparado todo para empezar, primero dibujemos como se verá nuestro
juego. Para esto agreguemos los siguientes atributos a la clase Game1:
Texture2D DIM;
Texture2D NAL;
Texture2D Balon;
Texture2D CanchaFutbol;
Rectangle cuadradoDIM;
Rectangle cuadradoNAL;
Rectangle cuadradoBalon;
int width;
int height;
En el constructor de la clase Game1, cambiemos el tamaño de la ventana con
estas líneas:
4. // change windows size
width = 960;
height = 600;
graphics.PreferredBackBufferWidth = width;
graphics.PreferredBackBufferHeight = height;
En el Load, carguemos los objetos con las siguientes líneas:
// Load images
DIM = Content.Load<Texture2D>("Images/DIM");
NAL = Content.Load<Texture2D>("Images/NAL");
Balon = Content.Load<Texture2D>("Images/Balon2");
CanchaFutbol = Content.Load<Texture2D>("Images/CanchaFutbol");
// Set the objects
cuadradoDIM = new Rectangle(100, (height - DIM.Height) / 2, 99, 119);
cuadradoNAL = new Rectangle(width - NAL.Width - 100, (height - NAL.Height) / 2, 99, 142);
cuadradoBalon = new Rectangle((width - Balon.Width) / 2, (height - Balon.Height) / 2, 68, 68);
En el Draw, colocar las siguientes líneas:
spriteBatch.Begin();
spriteBatch.Draw(CanchaFutbol, new Vector2(0, 0), Color.White);
spriteBatch.Draw(DIM, cuadradoDIM, Color.White);
spriteBatch.Draw(NAL, cuadradoNAL, Color.White);
spriteBatch.Draw(Balon, cuadradoBalon, Color.White);
spriteBatch.End();
Ya podemos probar lo que llevamos
Ahora pongamos movimiento a los escudos de los equipos
5. Agreguemos estos 2 nuevos atributos:
int velocityDIM;
int velocityNAL;
En el Initialize los inicializamos:
// Determine the size move
velocityDIM = 2;
velocityNAL = 2;
Y en el Update, colocamos la siguiente lógica:
var teclado = Keyboard.GetState();
// Move DIM
if (teclado.IsKeyDown(Keys.A)) cuadradoDIM.X -= velocityDIM;
if (teclado.IsKeyDown(Keys.D)) cuadradoDIM.X += velocityDIM;
if (teclado.IsKeyDown(Keys.W)) cuadradoDIM.Y -= velocityDIM;
if (teclado.IsKeyDown(Keys.S)) cuadradoDIM.Y += velocityDIM;
cuadradoDIM.X = (int)MathHelper.Clamp(cuadradoDIM.X, 0, width - cuadradoDIM.Width);
cuadradoDIM.Y = (int)MathHelper.Clamp(cuadradoDIM.Y, 0, height - cuadradoDIM.Height);
// Move NAL
if (teclado.IsKeyDown(Keys.Up)) cuadradoNAL.Y -= velocityNAL;
if (teclado.IsKeyDown(Keys.Down)) cuadradoNAL.Y += velocityNAL;
if (teclado.IsKeyDown(Keys.Left)) cuadradoNAL.X -= velocityNAL;
if (teclado.IsKeyDown(Keys.Right)) cuadradoNAL.X += velocityNAL;
cuadradoNAL.X = (int)MathHelper.Clamp(cuadradoNAL.X, 0, width - cuadradoNAL.Width);
cuadradoNAL.Y = (int)MathHelper.Clamp(cuadradoNAL.Y, 0, height - cuadradoNAL.Height);
6. Ya podemos probar el movimiento de los escudos de los equipos
Ahora vamos a agregar un estado de juego y la lógica para capturar los balones, evitar las
colisiones de los escudos, llevar un puntaje y los sonidos del juego
Agreguemos una nueva clase llamada: GameState, esta va a ser una enumeración con los
diferentes estados que va a tener el juego. Esta clase la seguiremos usando para
posteriores juegos. Lleva las siguientes líneas:
7. enum GameState
{
Uninitiated,
Running,
Finish
}
Agregue las siguientes propiedades a la clase Game1
SpriteFont font;
GameState gameState;
SoundEffect golDIM;
SoundEffect golNAL;
Song music;
int puntosDIM;
int puntosNAL;
En el Initialize, colocar las siguientes líneas:
// Initialize the scores
puntosDIM = 0;
puntosNAL = 0;
En el Load, colocar las siguientes líneas:
// Load font
font = Content.Load<SpriteFont>("Fonts/Font");
// Load sounds
golDIM = Content.Load<SoundEffect>("Sound/GolDIM");
golNAL = Content.Load<SoundEffect>("Sound/GolNAL");
music = Content.Load<Song>("Sound/Music");
Agregue el método NewBall
8. private void NewBall()
{
do
{
Random rd = new Random();
int posX = rd.Next(0, width - cuadradoBalon.Width) + 1;
int posY = rd.Next(0, height - cuadradoBalon.Height) + 1;
cuadradoBalon.X = posX;
cuadradoBalon.Y = posY;
if (!cuadradoBalon.Intersects(cuadradoDIM) && !cuadradoBalon.Intersects(cuadradoNAL)) return;
} while (true);
}
Agregue el método PlayMusic:
private void PlayMusic(Song gameplayMusic)
{
try
{
MediaPlayer.Play(gameplayMusic);
MediaPlayer.IsRepeating = true;
}
catch { }
}
Cambie el método Update por el siguiente:
9. protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
var teclado = Keyboard.GetState();
if (gameState == GameState.Running)
{
// Backup previous values
int antXDIM = cuadradoDIM.X;
int antYDIM = cuadradoDIM.Y;
int antXNAL = cuadradoNAL.X;
int antYNAL = cuadradoNAL.Y;
// Move DIM
if (teclado.IsKeyDown(Keys.A)) cuadradoDIM.X -= velocityDIM;
if (teclado.IsKeyDown(Keys.D)) cuadradoDIM.X += velocityDIM;
if (teclado.IsKeyDown(Keys.W)) cuadradoDIM.Y -= velocityDIM;
if (teclado.IsKeyDown(Keys.S)) cuadradoDIM.Y += velocityDIM;
cuadradoDIM.X = (int)MathHelper.Clamp(cuadradoDIM.X, 0, width - cuadradoDIM.Width);
cuadradoDIM.Y = (int)MathHelper.Clamp(cuadradoDIM.Y, 0, height - cuadradoDIM.Height);
// Move NAL
if (teclado.IsKeyDown(Keys.Up)) cuadradoNAL.Y -= velocityNAL;
if (teclado.IsKeyDown(Keys.Down)) cuadradoNAL.Y += velocityNAL;
if (teclado.IsKeyDown(Keys.Left)) cuadradoNAL.X -= velocityNAL;
if (teclado.IsKeyDown(Keys.Right)) cuadradoNAL.X += velocityNAL;
10. cuadradoNAL.X = (int)MathHelper.Clamp(cuadradoNAL.X, 0, width - cuadradoNAL.Width);
cuadradoNAL.Y = (int)MathHelper.Clamp(cuadradoNAL.Y, 0, height - cuadradoNAL.Height);
// Checks if the players crash!
if (cuadradoDIM.Intersects(cuadradoNAL))
{
cuadradoDIM.X = antXDIM;
cuadradoDIM.Y = antYDIM;
cuadradoNAL.X = antXNAL;
cuadradoNAL.Y = antYNAL;
}
// Check if DIM catch the ball
if (cuadradoDIM.Intersects(cuadradoBalon))
{
golDIM.Play();
puntosDIM++;
NewBall();
}
// Check if NAL catch the ball
if (cuadradoNAL.Intersects(cuadradoBalon))
{
golNAL.Play();
puntosNAL++;
NewBall();
}
if (puntosDIM >= 10 || puntosNAL >= 10)
{
MediaPlayer.Stop();
gameState = GameState.Finish;
}
14. Taller #6
Modificar el juego anterior para que aparezcan 4 obstáculos de forma
aleatoria (donde no haya, ni balón ni escudos). Estos obstáculos no permiten
que los escudos pasen por encima de ellos, haciendo el juego un poco más
interesante