Muy simple y solo como ejemplo de la primera aplicación que hice.
Crear el proyecto
Crear los sprites con los que se jugara, muy simples ya que solo están como ejemplo:
Crear la clase que manejara a los jugadores: Paddle
- /// <summary>
- /// Creata una paleta
- /// </summary>
- class Paddle
- {
- /// <summary>
- /// Variable con la posicion
- /// </summary>
- public Point pos;
- /// <summary>
- /// Velocidad de la paleta
- /// </summary>
- public int speed;
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- public Paddle(int x, int y)
- {
- /// La paleta inicia en la posicion que se le pase al constructor
- pos = new Point(x, y);
- /// Velocidad por defecto
- speed = 3;
- }
- }
Crear la clase que maneja el objeto : Ball
- /// <summary>
- /// Creaa un objeto con la pelota
- /// </summary>
- class Ball
- {
- /// <summary>
- /// Posicion de la pelota
- /// </summary>
- public Point pos;
- /// <summary>
- /// Velocidad horizontal y vertical
- /// </summary>
- public int h_speed, v_speed;
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- public Ball(int x, int y)
- {
- /// La posicion inicial de la pelota se le pasa al constructor
- pos = new Point(x, y);
- /// La velocidad inicial y la direccion es randomica
- Random rand = new Random();
- h_speed = rand.Next(3, 7);
- if (rand.Next(0, 2) == 0) h_speed *= -1;
- rand = new Random();
- v_speed = rand.Next(3, 7);
- if (rand.Next(0, 2) == 0) v_speed *= -1;
- }
- }
En la clase Game1.cs, crear variables que contengan a los “jugadores” y la pelota, además una variable que maneje generación de valores randomicos y una con el estado del teclado.
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- Texture2D t_paddle1, t_paddle2, t_ball;
- Paddle paddle1;
- Paddle paddle2;
- Ball ball;
- Random rand = new Random();
- KeyboardState currentState;
Crear un método que inicializa las posiciones de los Sprites en el juego, se llama ResetGame, e incluimos una llamada desde el constructor:
- /// <summary>
- /// Allows the game to perform any initialization it needs to before starting to run.
- /// This is where it can query for any required services and load any non-graphic
- /// related content. Calling base.Initialize will enumerate through any components
- /// and initialize them as well.
- /// </summary>
- protected override void Initialize()
- {
- // TODO: Add your initialization logic
- base.Initialize();
- ResetGame();
- }
- /// <summary>
- /// Inicializa los valores del juego
- /// </summary>
- void ResetGame()
- {
- paddle1 = new Paddle(10, 200);
- paddle2 = new Paddle(770, 200);
- ball = new Ball(385, 285);
- }
En el método LoadContent, que se ha generado automáticamente agregamos la carga de nuestros Sprites:
- /// <summary>
- /// LoadContent will be called once per game and is the place to load
- /// all of your content.
- /// </summary>
- protected override void LoadContent()
- {
- // Create a new SpriteBatch, which can be used to draw textures.
- spriteBatch = new SpriteBatch(GraphicsDevice);
- // TODO: use this.Content to load your game content here
- t_paddle1 = Content.Load<Texture2D>("paddle");
- t_paddle2 = Content.Load<Texture2D>("paddle");
- t_ball = Content.Load<Texture2D>("ball");
- }
En el método Draw, agregamos:
- /// <summary>
- /// This is called when the game should draw itself.
- /// </summary>
- /// <param name="gameTime">Provides a snapshot of timing values.</param>
- protected override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- // TODO: Add your drawing code here
- spriteBatch.Begin();
- spriteBatch.Draw(t_paddle1, new Rectangle(paddle1.pos.X, paddle1.pos.Y, t_paddle1.Width, t_paddle1.Height), Color.CornflowerBlue);
- spriteBatch.Draw(t_paddle2, new Rectangle(paddle2.pos.X, paddle2.pos.Y, t_paddle2.Width, t_paddle2.Height), Color.CornflowerBlue);
- spriteBatch.Draw(t_ball, new Rectangle(ball.pos.X, ball.pos.Y, t_ball.Width, t_ball.Height), Color.CornflowerBlue);
- spriteBatch.End();
- base.Draw(gameTime);
- }
Si se compila y ejecuta en este momento, tenemos el siguiente resultado:
Movimientos Humano y Computadora, Detección de colisiones
Dado que se jugara HumanoVsComputadora, lo primero que se hace es capturar la entrada de teclado y actualizar el movimiento de la paleta del Humano, además validamos que no salgamos de los límites de la ventana, esto lo hacemos desde un nuevo método, UpdatePaddles:
- void UpdatePaddles()
- {
- /// Capturamos las pulsaciones del teclado
- currentState = Keyboard.GetState();
- Keys[] currentKeys = currentState.GetPressedKeys();
- /// Solo hacer caso de las teclas que requerimos
- foreach (Keys key in currentKeys)
- {
- if (key == Keys.Up)
- paddle1.pos.Y -= paddle1.speed;
- if (key == Keys.Down)
- paddle1.pos.Y += paddle1.speed;
- if (key == Keys.Escape)
- this.Exit();
- }
- /// Varificar que no salimos de la ventana
- if (paddle1.pos.Y <= 10) paddle1.pos.Y = 10;
- if (paddle2.pos.Y <= 10) paddle2.pos.Y = 10;
- if (paddle1.pos.Y + t_paddle1.Height >= Window.ClientBounds.Height - 10)
- paddle1.pos.Y = Window.ClientBounds.Height - t_paddle1.Height - 10;
- if (paddle2.pos.Y + t_paddle2.Height >= Window.ClientBounds.Height - 10)
- paddle2.pos.Y = Window.ClientBounds.Height - t_paddle2.Height - 10;
- }
La “inteligencia” de la computadora, se reduce a que su paleta sigue la posición Vertical de la pelota, por lo que el anterior método quedaría así:
- void UpdatePaddles()
- {
- /// Capturamos las pulsaciones del teclado
- currentState = Keyboard.GetState();
- Keys[] currentKeys = currentState.GetPressedKeys();
- /// Solo hacer caso de las teclas que requerimos
- foreach (Keys key in currentKeys)
- {
- if (key == Keys.Up)
- paddle1.pos.Y -= paddle1.speed;
- if (key == Keys.Down)
- paddle1.pos.Y += paddle1.speed;
- if (key == Keys.Escape)
- this.Exit();
- }
- /// La paleta de la computadora solo sigue a la pelota
- paddle2.speed = ball.h_speed;
- if (paddle2.pos.Y + (t_paddle2.Height / 2) > ball.pos.Y)
- paddle2.pos.Y -= paddle2.speed;
- else if (paddle2.pos.Y + (t_paddle2.Height / 2) < ball.pos.Y)
- paddle2.pos.Y += paddle2.speed;
- /// Varificar que no salimos de la ventana
- if (paddle1.pos.Y <= 10) paddle1.pos.Y = 10;
- if (paddle2.pos.Y <= 10) paddle2.pos.Y = 10;
- if (paddle1.pos.Y + t_paddle1.Height >= Window.ClientBounds.Height - 10)
- paddle1.pos.Y = Window.ClientBounds.Height - t_paddle1.Height - 10;
- if (paddle2.pos.Y + t_paddle2.Height >= Window.ClientBounds.Height - 10)
- paddle2.pos.Y = Window.ClientBounds.Height - t_paddle2.Height - 10;
- }
Ahora se requiere mover la pelota, se lo hace desde un nuevo método UpdateBall:
- void UpdateBall()
- {
- /// Actualiza la posicion de la pelota
- ball.pos.X += ball.h_speed;
- ball.pos.Y += ball.v_speed;
- /// Verificar limites
- /// Inferior
- if (ball.pos.Y > (Window.ClientBounds.Height - 10 - t_ball.Height))
- ball.v_speed *= -1;
- /// Superior
- if (ball.pos.Y < 10)
- ball.v_speed *= -1;
- }
Finalmente implementamos un “detector de colisiones”, que simplemente compara las posiciones de los Sprites de la pantalla, y según eso calcula la nueva dirección de la pelota, velocidad después de “golpearla” y si una de las paletas no ha alcanzado a golpear la bola, en cuyo caso el juego comienza de nuevo, llamando al método ResetGame:
- void CheckCollisions()
- {
- /// Verificar si la pelota esta yendo a la izquierda
- if (ball.h_speed < 0)
- {
- /// Verifica si la pelota a rebasado la paleta
- if (ball.pos.X < paddle1.pos.X + 20)
- {
- /// Si la pelota no fue golpeada, fin del juego
- if ((ball.pos.Y + t_ball.Height < paddle1.pos.Y) || (ball.pos.Y > paddle1.pos.Y + t_paddle1.Height))
- {
- ResetGame();
- }
- else
- {
- /// Se golpea la pelota, se cambia su direccion
- /// y se le da una velocidad inicial randomica, entre 3 y 7
- if (ball.h_speed < 0)
- ball.h_speed = rand.Next(3, 7);
- else ball.h_speed = rand.Next(-6, -2);
- if (ball.v_speed < 0)
- ball.v_speed = rand.Next(3, 7);
- else ball.v_speed = rand.Next(-6, -2);
- }
- }
- }
- else
- {
- /// Verifica si la pelota a rebasado la paleta
- if (ball.pos.X + t_ball.Width > paddle2.pos.X)
- {
- /// Si la pelota no fue golpeada, fin del juego
- if ((ball.pos.Y + t_ball.Height < paddle2.pos.Y) || (ball.pos.Y > paddle2.pos.Y + t_paddle2.Height))
- {
- ResetGame();
- }
- else
- {
- /// Se golpea la pelota, se cambia su direccion
- /// y se le da una velocidad inicial randomica, entre 3 y 7
- if (ball.h_speed < 0)
- ball.h_speed = rand.Next(3, 7);
- else ball.h_speed = rand.Next(-6, -2);
- if (ball.v_speed < 0)
- ball.v_speed = rand.Next(3, 7);
- else ball.v_speed = rand.Next(-6, -2);
- }
- }
- }
- }
Implementamos la lógica de actualización del juego, desde le método Update:
- /// <summary>
- /// Allows the game to run logic such as updating the world,
- /// checking for collisions, gathering input, and playing audio.
- /// </summary>
- /// <param name="gameTime">Provides a snapshot of timing values.</param>
- 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
- UpdatePaddles();
- UpdateBall();
- CheckCollisions();
- base.Update(gameTime);
- }
F5 y a jugar!
Los fuentes, aquí:
Publicar un comentario