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 es un juego clásico de cartas. En esta implementación, lo haremos para 2
jugadores. Cada jugador inicia con 2 cartas, y el objetivo es que la suma de
los puntos de las cartas sea 21. Si el jugador se pasa de 21, pierde. Gana el
que tenga 21 punto o el que más se aproxime.
Las cartas del 2 a 10, valen el número de la carta, es decir, el 2 vale 2, e 3
vale 3, y así sucesivamente
La J, Q y K, valen 10 puntos
El As vale 1 u 11 puntos dependiendo de lo que más le convenga al jugador
3. Cree un proyecto XNA. Yo lo llame: Black Jack
Cree la carpeta Images y agregue las imágenes que utilizaremos en este proyecto,
que son: un fondo verde, un logo de Black Jack y las 52 cartas que están PN,
donde P es la pinta (P: Corazones, D: Diamantes, P: Picas, T: Tréboles) y N el
número, que va del 2 al 10, más: J, Q, K y A.
Cree la carpeta Fonts y cree un nuevo archivo de letras llamado Font. Cambie
estas etiquetas:
<FontName>Impact</FontName>
<Size>24</Size>
Agreguemos la enumeración GameState que utilizamos en el ejemplo anterior. No
olvide cambiar el nombre del NameSpace
Agregue una nueva clase llamada Pinta, la cual será una enumeración con las
pintas de la baraja
enum Pinta
{
Corazón,
Diamante,
Pica,
Trébol
}
Agregue una nueva clase llamada Carta, la cual empaquetará todos los atributos
de una carta
4. using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Black_Jack
{
class Carta
{
public Texture2D Textura { get; set; }
public Pinta Pinta { get; set; }
public string Letra { get; set; }
public int Valor1 { get; set; }
public int Valor2 { get; set; }
}
}
Primero pintemos como se verá nuestro juego cuando lo ejecutemos.
Agreguemos estos atributos a la clase Game1
Texture2D fondo;
Texture2D logo;
SpriteFont font;
GameState gameState;
int width;
int height;
En el constructor de la case Game1, adicione las siguientes líneas:
5. // change windows size
width = 900;
height = 600;
graphics.PreferredBackBufferWidth = width;
graphics.PreferredBackBufferHeight = height;
En el Initizalice:
gameState = GameState.Uninitiated;
En el Load
fondo = Content.Load<Texture2D>("Images/FondoVerde");
logo = Content.Load<Texture2D>("Images/BlackJack");
font = Content.Load<SpriteFont>("Fonts/Font");
En el Draw
spriteBatch.Begin();
spriteBatch.Draw(fondo, new Vector2(0, 0), Color.White);
spriteBatch.Draw(logo, new Vector2((width - logo.Width) / 2, 20), Color.White);
if (gameState == GameState.Uninitiated)
{
spriteBatch.DrawString(font, "Presioner ENTER para empezar...", new Vector2(250, 250),
Color.White);
}
spriteBatch.End();
6. Probemos lo que llevamos hasta el momento:
Ahora empecemos con la lógica del juego. Vamos a cargar toda la baraja en memoria y
cuando el usuario presione ENTER, vamos a darle a cada jugador 2 cartas y las vamos a
mostrar
Vamos a adicionar estos nuevos atributos a la clase Game1
KeyboardState tecladoPrevio;
Random rd = new Random();
List<Carta> baraja;
List<Carta> jugador1;
List<Carta> jugador2;
7. En el Initialize:
baraja = new List<Carta>();
jugador1 = new List<Carta>();
jugador2 = new List<Carta>();
Ahora empecemos con la lógica del juego. Vamos a cargar toda la baraja en memoria y
cuando el usuario presione ENTER, vamos a darle a cada jugador 2 cartas y las vamos a
mostrar
Vamos a adicionar estos nuevos atributos a la clase Game1
KeyboardState tecladoPrevio;
Random rd = new Random();
List<Carta> baraja;
List<Carta> jugador1;
List<Carta> jugador2;
Adicionemos el método LoadBaraja. El cual carga todo el mazo de cartas en memoria (este
método puede ser reutilizable por otros juegos de cartas)
private void LoadBaraja()
{
Pinta pinta = Pinta.Corazón;
string pintaLetra = "C";
for (int i = 0; i < 4; i++)
{
for (int j = 1; j <= 13; j++)
{
string letra;
int valor1;
int valor2;
if (j == 1)
8. {
letra = "A";
valor1 = 1;
valor2 = 11;
}
else if (j == 11)
{
letra = "J";
valor1 = 10;
valor2 = 10;
}
else if (j == 12)
{
letra = "Q";
valor1 = 10;
valor2 = 10;
}
else if (j == 13)
{
letra = "K";
valor1 = 10;
valor2 = 10;
}
else
{
letra = j.ToString();
valor1 = j;
valor2 = j;
}
Texture2D textura = Content.Load<Texture2D>("Images/" + pintaLetra + letra);
Carta carta = new Carta();
carta.Letra = letra;
9. carta.Pinta = pinta;
carta.Textura = textura;
carta.Valor1 = valor1;
carta.Valor2 = valor2;
baraja.Add(carta);
}
pinta++;
if (pinta == Pinta.Diamante) pintaLetra = "D";
if (pinta == Pinta.Pica) pintaLetra = "P";
if (pinta == Pinta.Trébol) pintaLetra = "T";
}
}
Adicionemos el método AsignarCarta. El cual le asigna una carta NO repetida al jugador
(este método puede ser reutilizable por otros juegos de cartas)
private void AsignaCarta(List<Carta> jugador)
{
int index = rd.Next(0, baraja.Count - 1);
jugador.Add(baraja[index]);
baraja.RemoveAt(index);
}
Adicionemos estas líneas al método Update
10. carta.Pinta = pinta;
carta.Textura = textura;
carta.Valor1 = valor1;
carta.Valor2 = valor2;
baraja.Add(carta);
}
pinta++;
if (pinta == Pinta.Diamante) pintaLetra = "D";
if (pinta == Pinta.Pica) pintaLetra = "P";
if (pinta == Pinta.Trébol) pintaLetra = "T";
}
}
Adicionemos el método AsignarCarta. El cual le asigna una carta NO repetida al jugador
(este método puede ser reutilizable por otros juegos de cartas)
private void AsignaCarta(List<Carta> jugador)
{
int index = rd.Next(0, baraja.Count - 1);
jugador.Add(baraja[index]);
baraja.RemoveAt(index);
}
Adicionemos estas líneas al método Update
12. Agregue estas líneas al Draw, antes del spriteBatch.End();
if (gameState == GameState.Running)
{
spriteBatch.DrawString(font, "I) Carta jugador izquierda, D) Carta jugador derecha, P) Plantar",
new Vector2(50, 250), Color.White);
MostrarCartas(jugador1, 100, 350);
MostrarCartas(jugador2, 500, 350);
}
Probemos lo que llevamos hasta el momento:
13. Ahora agreguemos la lógica del juego y el manejo de puntajes
Adicione estos atributos a la clase Game1:
int puntaje1Jugador1;
int puntaje2Jugador1;
int puntaje1Jugador2;
int puntaje2Jugador2;
int ganador;
En el Initialize:
puntaje1Jugador1 = 0;
puntaje2Jugador1 = 0;
puntaje1Jugador2 = 0;
puntaje2Jugador2 = 0;
ganador = 0;
14. Adicione el método revisar puntajes:
private void RevisarPuntajes()
{
puntaje1Jugador1 = 0;
puntaje2Jugador1 = 0;
puntaje1Jugador2 = 0;
puntaje2Jugador2 = 0;
foreach (Carta carta in jugador1)
{
puntaje1Jugador1 += carta.Valor1;
puntaje2Jugador1 += carta.Valor2;
}
foreach (Carta carta in jugador2)
{
puntaje1Jugador2 += carta.Valor1;
puntaje2Jugador2 += carta.Valor2;
}
}
Cambien el método Update por el siguiente:
15. 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
KeyboardState tecladoActual = Keyboard.GetState();
if ((gameState == GameState.Uninitiated || gameState == GameState.Finish) &&
tecladoActual.IsKeyDown(Keys.Enter))
{
gameState = GameState.Running;
jugador1.Clear();
jugador2.Clear();
LoadBaraja();
AsignaCarta(jugador1);
AsignaCarta(jugador2);
AsignaCarta(jugador1);
AsignaCarta(jugador2);
RevisarPuntajes();
}
if (gameState == GameState.Running &&
tecladoActual.IsKeyDown(Keys.I) &&
!tecladoPrevio.IsKeyDown(Keys.I) &&
(puntaje1Jugador1 < 21 || puntaje2Jugador1 < 21))
{
AsignaCarta(jugador1);
RevisarPuntajes();
}