domingo, 1 de abril de 2012

Desplegando el Fondo del Juego

Carrera de XNA – Capítulo 4 – Artículo 5

Hasta ahora hemos logrado crear nuestra nave, pero verla volando en un fondo azul no da la mejor de las experiencias. El próximo paso es crear un fondo transparente para dar la impresión de movimiento. Para esto crearemos una clase de tipo Parallax, que nos permite mover imágenes en múltiples capas a diferentes velocidades. Esta clase contendrá toda la lógica necesaria para el fondo y la usaremos desde nuestro Game1.

Crearemos unas nueva clase, llamada ParallaxingBackground.cs en nuestro proyecto.

 

Clase ParallaxingBackground.cs

Procederemos a reemplazar nuestros usings por lo siguiente:

// ParallaxingBackground.cs

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

Tal y como hicimos en la clase Animación, vamos a declarar algunas variables y crear 3 métodos que luego completaremos.

// The image representing the parallaxing background
Texture2D texture;

// An array of positions of the parallaxing background

Vector2 [] positions;
// The speed which the background is moving
int speed;

public void Initialize()

{

}

public void Update()

{

}

public void Draw()

{

}

Reemplazaremos el método Initialize por el siguiente código:

public void Initialize(ContentManager content, String texturePath, int screenWidth, int speed)
{
    // Load the background texture we will be using
    texture = content.Load<Texture2D>(texturePath);

    // Set the speed of the background
    this.speed = speed;

    // If we divide the screen with the texture width then we can determine the number of tiles need.
    // We add 1 to it so that we won't have a gap in the tiling
    positions = new Vector2[screenWidth / texture.Width + 1];

    // Set the initial positions of the parallaxing background
    for (int i = 0; i < positions.Length; i++)
    {
        // We need the tiles to be side by side to create a tiling effect
        positions[i] = new Vector2(i * texture.Width, 0);
    }
}

Aquí cargamos el archivo de fondo (a través del Content.Load) como hemos hecho anteriormente.  Luego definimos las posiciones que va a ocupar el fondo, dividiendo el ancho de la pantalla por el ancho de la textura y agregando un “+1” para que el borde seguro.

Para finalizar establecemos cada posición del vector de fondo. Para esto usamos el ciclo for que recorre nuestro array de posiciones y establecemos en cada elemento un nuevo Vector2D, con las posición X  valuada en i  por el ancho de nuestra textura y la posición Y en 0.

Ahora pasamos al método Update que se encargará de modificar la posición del fondo, de manera similar a la que se mueve el jugador en nuestra clase Game1.

public void Update()
{
    // Update the positions of the background
    for (int i = 0; i < positions.Length; i++)
    {
        // Update the position of the screen by adding the speed
        positions[i].X += speed;
        // If the speed has the background moving to the left
        if (speed <= 0)
        {
            // Check the texture is out of view then put that texture at the end of the screen
            if (positions[i].X <= -texture.Width)
            {
                positions[i].X = texture.Width * (positions.Length - 1);
            }
        }
        // If the speed has the background moving to the right
        else
        {
            // Check if the texture is out of view then position it to the start of the screen
            if (positions[i].X >= texture.Width * (positions.Length - 1))
            {
                positions[i].X = -texture.Width;
            }
        }
    }
}

Analizando un poco el código, lo que hacemos es mover sorbe el eje X nuestro fondo y dependiendo la “aceleración” le damos mas o menso velocidad. Esto es un truco visual, ya que tenemos el dibujo de fondo fuera de la pantalla y lo rotamos con el que se ve (y así de forma infinita). Esto genera una sensación suave de movimiento sin “cortes” visibles.

Para finalizar en esta clase, modificamos el método Draw.

public void Draw(SpriteBatch spriteBatch)
{
    for (int i = 0; i < positions.Length; i++)
    {
        spriteBatch.Draw(texture, positions[i], Color.White);
    }
}

Ahora que finalizamos con nuestra clase procederemos a modificar el Game1 para inicializar, cargar actualizar y dibujar el fondo.

 

Dentro de Game1.cs

En la parte superior de nuestra clase declararemos las siguientes variables.

// Image used to display the static background
Texture2D mainBackground;
// Parallaxing Layers
ParallaxingBackground bgLayer1;
ParallaxingBackground bgLayer2;

Ahora, en el método Initialize procederemos a crear una instancia de nuestro ParallaxingBackground en cada una.

bgLayer1 = new ParallaxingBackground();
bgLayer2 = new ParallaxingBackground();

A continuación vamos a actualizar nuestro método de carga LoadContent() para poner en memoria las texturas del fondo.

// Load the parallaxing background
bgLayer1.Initialize(Content, "Imagenes/fondoCapa1", GraphicsDevice.Viewport.Width, -1);
bgLayer2.Initialize(Content, "Imagenes/fondoCapa2", GraphicsDevice.Viewport.Width, -2);

mainBackground = Content.Load<Texture2D>("Imagenes/fondoPrincipal");

Llamaremos al método de actualización de las capas de fondo en nuestro método Update() luego de actualizar al jugador, de la siguiente manera.

// Update the parallaxing background
bgLayer1.Update();
bgLayer2.Update();

Como último paso, dibujaremos el fondo en el método Draw(), utilizando lo creado dentro de ParallaxBackground. Este código hay que colocarlo antes del código que dibuja al jugador.

spriteBatch.Draw(mainBackground, Vector2.Zero, Color.White);
// Draw the moving background
bgLayer1.Draw(spriteBatch);
bgLayer2.Draw(spriteBatch);

Así se debería ver nuestro juego en este momento.

image

Para bajar el juego en la versión del juego en este estado:  http://sdrv.ms/JaYXDD

3 comentarios:

  1. muy buen post solo tengo que aprender a usar mas la interpretacion de crear juegos

    ResponderEliminar
  2. Un error, la imagen queda encima de la nave y por esto no se ve la nave. Como lo arreglo?

    ResponderEliminar
  3. no se si sea demaciado tarde algunos meses despues sin embargo ya me fije que eso depende en que orden llames a dibujar colocalo de esta manera en la parte draw de la game1.cs y se arreglara:

    ahi te la paso toda mejor para que no quede duda

    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.CornflowerBlue);
    spriteBatch.Begin();


    spriteBatch.Draw(mainBackground, Vector2.Zero, Color.White);


    // Draw the moving background
    bgLayer1.Draw(spriteBatch);
    bgLayer2.Draw(spriteBatch);
    jugador.Draw(spriteBatch);

    spriteBatch.End();
    // TODO: Add your drawing code here

    base.Draw(gameTime);
    }

    ResponderEliminar