kalabaza.com.mx
Sitio de animación y desarrollo de video juegos

 

Bienvenidos a esta nuevo post en el que continuaremos con la programación del scroll en el  Background de los juegos 2D.

En esta ocasión hice bastantes cambios a la versión anterior por ser un método diferente de programación, sin embargo el programa lo empecé utilizando el código del post anterior, como lo he estado haciendo hasta ahora. Espero que no haya confusión con los cambios de código pero trataré de explicarlo lo mejor posible.

 

En este ocasión vamos a ver los siguientes puntos:

 

  • Explicación previa
  • Agregar propiedades a AnimSprite
  • Carga de imágenes para los backgrounds
  • Desplazamiento de los backgrounds
  • Modificación de método Draw()
     

Explicación previa

 

Como siempre voy a explicar primero lo que vamos a hacer. Anteriormente teníamos tres backgrounds que se desplazaban en sentido opuesto al desplazamiento del personaje cuando este alcanzaba uno de los límites predefinidos en los extremos de la pantalla. Estos background se iban repitiendo de tal forma que el avance se volvía infinito. En esta ocasión vamos limitar el avance en ambos extremos de nuestro escenario y vamos a ocupar también tres background pero no consecutivos, sino sobrepuestos y que se desplazan a diferentes velocidades para crear mayor profundidad en el escenario. Además el fondo que se encuentra más al fondo mantendrá un desplazamiento constante independiente del movimiento del personaje para imitar el desplazamiento de las nubes.

 

 

Agregar propiedades a AnimSprite

 

Vamos a empezar por hacer unas modificaciones a nuestra clase AnimSprite; estas modificaciones consisten en agregar un par de propiedades que son las dimensiones de los sprites, a estas dos propiedades las llamaremos Largo y Altura y las declararemos en la parte de arriba de nuestra clase.

 

  public int Largo;
  public int Altura;

 

Estos dos valores no los vamos a asignar nosotros sino que vamos a obtener su valor directamente de las imágenes al momento de cargarlas, escribiendo el siguiente código en el método CargaImagen()

 

  Altura = SpriteMov[0].Height;
  Largo = SpriteMov[0].Width;

 

De esta forma, cada vez que se cargue una imagen tendremos a nuestra disposición estos dos valores. Sin embargo cabe señalar que para el caso en el que ocupamos la clase para cargar sprites animados como es el caso de Megaman, lo que nos devolverían estas variables sería las dimensiones de la última imagen cargada la cual puede o no tener las mismas dimensiones de las otras.

 

 

Carga de imágenes para los backgrounds

 

Lo que haremos a continuación es cargar las imágenes que vamos a ocupar dentro de nuestro proyecto en la carpeta Sprites, como lo hemos hecho antes. Puedes consultar la explicación que viene en el Post "Carga y animación de un sprites" y puedes descargar las imágenes aqui.

 

Como comenté vamos a ocupar tres fondos de los cuales los primeros dos se repetirán varias veces en la pantalla y el tercero solo se recorrerá conforme el personaje vaya avanzando. Para los dos primeros vamos a crear listas de nuestra clase AnimSprite y para el tercero solo crearemos un objeto con el siguiente código

 

        List<AnimSprite> FondosCielo = new List<AnimSprite>();

        List<AnimSprite> FondosPicos = new List<AnimSprite>();

        AnimSprite Fondo = new AnimSprite()

 

Este código va dentro de la declaración de variables de nuestra clase Engine y sustituira la declaración del arreglo Fondos que teníamos anteriormente en esa ubicación; Si tienes duda sobre la sintaxis de las listas puedes consultar el post “Listas”

 

Ya con nuestros objetos declarados lo siguiente es escribir el código para cargar las imágenes. Para hacer esto vamos a sustituir el código que ocupábamos para este propósito dentro del LoadContent() de tal forma que el método completo quedará de la siguiente forma:

 

 protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);

           // Sección 1 Cielo azul

            int PosTmp = 0;

              for (int i = 1;i < 5; i++)
              {
                AnimSprite FondoTmp = new AnimSprite(PosTmp, 0, 0, new Vector2(0, 0));
                FondoTmp.CargaImagen(Content.Load<Texture2D>(“Sprites/Fondo3″ ));
                FondosCielo.Add(FondoTmp);
                PosTmp = FondoTmp.Largo * i;
              }

           // Sección 2 Picos

            PosTmp = 0;

              for (int i = 1; i < 8; i++)
            {
               AnimSprite FondoTmp = new AnimSprite(PosTmp, 325, 0, new Vector2(0, 0));

                FondoTmp.CargaImagen(Content.Load<Texture2D>(“Sprites/Fondo2″));
                FondosPicos.Add(FondoTmp);
                PosTmp = FondoTmp.Largo * i;
            }

 

            //Sección 3 Piso

             Fondo = new AnimSprite(0, 353, 0, new Vector2(0, 0));
             Fondo.CargaImagen(Content.Load<Texture2D>(“Sprites/Fondo1″));

            //Sección 4 Personaje

              for (int i = 1; i<=7; i++)
                Megaman.CargaImagen(Content.Load<Texture2D>(“Sprites/MM”+ i));

        }

Puse comentarios para poder explicar el código por partes.
En la primer sección vamos a cargar la imagen de más al fondo, la cual he denominado Cielo azul.

 

 

Iniciamos por declarar la variable PosTmp que va a guardar la posición inicial de nuestras imágenes que carguemos en nuestra lista. Enseguida lo que vamos a hacer es utilizar el ciclo for para cargar cuatro veces la imagen en la lista  FondosCielo  (desde i= 1 hasta i=5 ) esto es porque esta imagen tiene de dimensiones 256 x 482 y aunque se necesitan tres imágenes para cubrir toda la pantalla, necesitamos una imagen adicional para cubrir el área que queda al desplazarse por completo una de las imágenes; Puedes cambiar el límite del  for  a 4 para entender mejor lo que pasa.

 

Dentro del ciclo for tenemos lo siguiente:

 

 AnimSprite FondoTmp = new AnimSprite(PosTmp, 0, 0, new Vector2(0, 0));

 

En esta línea lo que hacemos es instanciar un objeto temporal  AnimSprite de nombre FondoTmp; Este objeto tendrá como posición inicial en X el valor de PosTmp, el cual originalmente es cero y conforme va avanzando el loop se va incrementando de acuerdo al largo de la imagen. Por ejemplo, para nuestro ejemplo la imagen que  ocupamos tiene de dimensiones en Largo y Alto de 256 x 482 respectivamente. Por lo tanto el valor de PosTmp será el siguiente para cada valor de i dentro del for:

 

 

i PosTmp
1 0
2 256
3 512
4 768

 

La posición en Y será constante e igual a cero, el ángulo de rotación será también cero así como las coordenadas del centro de rotación que esta definido por el vector que se instancia como parámetro final. Enseguida tenemos la siguiente línea:

 

FondoTmp.CargaImagen(Content.Load<Texture2D>(“Sprites/Fondo3″ ));

 

que como ya sabemos por post anteriores nos sirve para cargar nuestra imagen Fondo3 en el objeto que acabamos de crear.

La siguiente línea

 

FondosPicos.Add(FondoTmp);

 

se utiliza para agregar el objeto que acabamos de instanciar dentro de nuestra lista y finalmente en la última línea

 

PosTmp = FondoTmp.Largo * i;

 

incrementamos el valor de PosTmp de acuerdo a la tabla anterior.

 

En la sección 2 denominada ‘Picos’ tenemos la misma estructura pero reiniciamos el valor de PostTmp a cero y en lugar de Fondo1 vamos a cargar la imagen Fondo2.

 

 

Además dado que las dimensiones de esta nueva imagen son 128 x 108 será necesario copiar siete veces la imagen en la lista FondosPicos  (desde i= 1 hasta i = 8).

 

Nota: La mejor solución para definir el número de veces que la imagen se guarda en la lista es determinarlo en base al ancho de la imagen a carga de tal forma que rellene por completo toda la pantalla y agregamos una imagen más para cubrir el espacio faltante al desplazarse. En ese ejemplo ocupo valores constantes para que sea más fácil de entender.

 

En la sección 3 denominada ‘Piso’ la estructura es diferente, dado que solo vamos a ocupar una imagen que va a ocupar todo nuestro escenario.

 

 

Por lo tanto solo instanciamos en objeto Fondo como hemos estado haciendo y definimos su posición en la coordenada (0,0). Finalmente cargamos la imagen Fondo1 con ángulo de rotación 0 y origen en (0,0).

 

En la última sección denominada ‘Personaje’ seguimos cargando los sprites de megaman como en los post anteriores.

 

 

Desplazamiento de los backgrounds

 

Ya con las imágenes cargadas lo siguiente es escribir el código para desplazarlas conforme avanza nuestro personaje. Para hacer esto vamos a modificar el método Update() de nuestra clase Engine. Como expliqué al principio, el background del cielo va a desplazarse independientemente del movimiento del personaje. Este desplazamiento será de un pixel por cada ciclo del juego y será de derecha a izquierda. Para lograr esto vamos a escribir el siguiente código dentro de nuestro if principal del método Update()

 

          foreach (AnimSprite Tmp in FondosCielo)
              Tmp.XPos -= 1;

 

Lo que hacemos aquí es desplazar un píxel a la izquierda cada uno de los background dentro de nuestra lista FondosCielo; como comenté antes, este código esta fuera de las condiciones de dirección de los personajes así que siempre se ejecuta.

 

Dentro de nuestro código original  tenemos enseguida los dos if’s que controlan  los cambios en el juego de acuerdo a la tecla presionada, izquierda o derecha. Dentro del primer if (correspondiente a la condición de que se ha presionado la tecla a la DERECHA) vamos a sustituir el código anterior por el siguiente:

 

//Avance
   if (Megaman.XPos < 540 || (Megaman.XPos <graphics.PreferredBackBufferWidth -- 40 &&
     Fondo.XPos < graphics.PreferredBackBufferWidth-Fondo.Largo+10 ))
    Megaman.XPos += 10;
   else if (Fondo.XPos>= graphics.PreferredBackBufferWidth-Fondo.Largo+10)
  {
 //Cielo
      for(int i= 0; i < FondosCielo.Count;i++)
        FondosCielo[i].XPos -= 3;

//Picos
     for (int i = 0; i < FondosPicos.Count; i++)
     {
        FondosPicos[i].XPos -= 6;

          if (FondosPicos[i].XPos + FondosPicos[i].Largo < 0)
          {
             if (i == 0)
                FondosPicos[i].XPos = FondosPicos[FondosPicos.Count - 1].XPos +
FondosPicos[FondosPicos.Count - 1].Largo-6;

             else
                FondosPicos[i].XPos = FondosPicos[i - 1].XPos + FondosPicos[i - 1].Largo-6;
          }
      }


// Piso
 Fondo.XPos -= 10;
 }


//Megaman

  if (Megaman.UltimaDir == 0 && Megaman.XPos < graphics.PreferredBackBufferWidth -- 40)
   Megaman.UpdateMov();
  else
   Megaman.FrameActual = 6;
 

Megaman.UltimaDir = 0;

 

Nuevamente el código en este bloque está dividido en cinco partes definidas por las etiquetas: Avance, Cielo, Picos, Piso y Megaman. En la sección Avance tendremos, como su nombre lo indica, la condición que hacer que el personaje avance o no cuando se presiona la tecla de dirección a la derecha. Lo que queremos es limitar el movimiento para que solo se pueda mover dentro del área definida por la imagen de piso que ocupamos. Al igual que en el post anterior vamos de permitir que nuestro personaje avance mientras no alcance el límite derecho definido por nosotros (Megaman.XPos < 540) sin embargo tenemos que agregar una nueva condición que permitirá avanzar a nuestro personaje hasta el final de la pantalla cuando se haya alcanzado el final de la imagen definida por nuestro objeto Piso. Esta condición tendrá que verificar que la posición de Megaman sea menor al límite derecho de la pantalla. Este límite esta definido por la constante graphics.PreferredBackBufferWidth que para nuestro ejemplo tiene un valor de 640, sin embargo como recordarán el origen de los sprites se encuentra en el extremo superior izquierdo, entonces se permitimos que Megaman alcance este límite habrá salido de la pantalla. Es por eso que necesitamos restar el ancho de los sprites de Megaman para que siempre se mantenga dentro de la pantalla. Este ancho es aproximadamente 40 pixeles y digo aproximadamente porque el ancho real del sprite es 44 pixeles pero a la derecha tienen un espacio en blanco variable para cada imagen por consiguiente nuestra condición queda como:

 

Megaman.XPos <graphics.PreferredBackBufferWidth -- 40

 

pero si dejamos esta condición así, permitira a Megaman que alcance el límite de la pantalla y no le importará la condición anterior. Es por eso que tenemos que agregar una condición adicional a esta parte del if. Esta parte debe permitir a Megaman que alcance el límite de la pantalla pero cuando la posición de Fondo este a una posición n donde n es el negativo del Largo de la imagen más el ancho de la pantalla osea:

 

Fondo.XPos < graphics.PreferredBackBufferWidth-Fondo.Largo+10

 

El 10 adicional es una corrección que hay que hacer porque el avance de Fondo es de 10 en 10 unidades. Con esto nos quedará completo el if de la Sección ‘Avance’.

 

Si la condición anterior no se cumple entonces debemos verificar primero que Fondo no este completamente a la izquierda para permitir el desplazamiento de los demás fondos. Esto lo hacemos verificando que la posición de Fondo sea mayor al negativo del largo de la imagen más el ancho de la pantalla o lo que es lo mismo:

 

Fondo.XPos>= graphics.PreferredBackBufferWidth-Fondo.Largo+10

 

Nuevamente el 10 es un valor de corrección.

 

En la sección denominada ‘Cielo’ vamos a desplazar tres pixeles a la izquierda todos nuestras imágenes que están dentro de la lista FondosCielo con ayuda del for que recorrerá todas las imágenes en la lista. Esto será lo único que haremos por ahora pero más adelante explicaré porque.

 

En la sección ‘Picos’ tenemos también un for que recorrerá todas las imágenes de nuestra lista FondosPicos pero en lugar de recorrer las imágenes tres pixeles las recorreremos seis. Esto, como comenté al principio nos creará un efecto de profundidad en nuestro escenario.
Lo que hacemos a continuación es verificar que cada imagen que vamos recorriendo se encuentre dentro de los límites de la pantalla de la siguiente manera:

 

 

Como se muestra en la imagen, si la posición actual de la imagen (FondosPicos[i].XPos) esta en una posición negativa ‘n’ tal que ‘n’ = -- FondosPicos[i]. Largo  esto significaría que la imagen ha salido por completo de la pantalla en cuyo caso lo que hacemos es colocar esta imagen a la derecha al final de la última imagen de la lista o mejor dicho a la derecha de la imagen que este más a la derecha de la pantalla. La pregunta ahora sería cual es el índice de dicha imagen. Primero si la imagen que se salió de la pantalla es la primer imagen o sea aquella con índice i ==0 entonces sabemos que la imagen más a la derecha es la última en la lista y para encontrar el último índice utilizamos la propiedad Count que nos regresa el número de elementos contenidos en la lista y le restamos 1 para obtener el último índice.

 

 

Una vez que conocemos el último indicie solo nos resta sumar la posición en X del mismo al ancho o Largo de las imágenes que componen la lista y restarle 6 pixeles como se muestra en la siguiente línea:

 

  FondosPicos[i].XPos = FondosPicos[FondosPicos.Count - 1].XPos + FondosPicos[FondosPicos.Count - 1].Largo-6;

 

Para un caso diferente sabemos que si siempre realizamos el movimiento de las imágenes a la derecha del último elemento de la lista esta debería tener un índice siguiente menor al que vamos a desplazar, así que  solo tendríamos que restar 1 al índice que vamos a desplazar.

 

 

y al igual que en el caso anterior solo sumamos la posición de este elemento al largo de las imágenes y le restamos 6 pixeles.

 

FondosPicos[i].XPos = FondosPicos[i - 1].XPos + FondosPicos[i - 1].Largo-6;

 

Para nuestra sección ‘Piso’ solo nos queda restar 10 pixeles a nuestra imagen. Como puedes observar esta imagen es la que más se desplaza y este desplazamiento es equivalente al que realiza el personaje porque se encuentran en el mismo plano, además no se necesita ninguna validación porque esta imagen no se repite.

 

En nuestra última sección vamos a seguir actualizando el sprite que se va a mostrar en la animación de Megaman desplazándose, sin embargo como ahora tenemos límites en cada extremo de la pantalla tenemos que verificar que no los haya alcanzado antes de seguir con el siguiente sprite. Lo único que hacemos es verificar que la posición de megaman este dentro de los límites de la pantalla para permitirle que se desplace de lo contrario se detendrá la animación y se mostrará el sprite de megaman de pie. Finalmente establecemos como última dirección 0 que es a la derecha

 

Dentro de la condición de que se haya presionado la tecla de dirección IZQUIERDA, tendremos que escribir el siguiente código.

 

//Avance
  if (Megaman.XPos > 100 || (Megaman.XPos > 0 && Fondo.XPos >= 0))
    Megaman.XPos -= 10;

  else if (Fondo.XPos<0)
  {

//Cielo
    for (int i = FondosCielo.Count-1; i >= 0; i--)
    {
      FondosCielo[i].XPos += 3;

        if (FondosCielo[i].XPos > graphics.PreferredBackBufferWidth)
        {
           if (i == FondosCielo.Count -- 1)
              FondosCielo[i].XPos = FondosCielo[0].XPos -- FondosCielo[i].Largo + 3;
           else
              FondosCielo[i].XPos = FondosCielo[i + 1].XPos -- FondosCielo[i].Largo + 3;
        }
    }

//Picos
    for (int i = FondosPicos.Count -- 1; i >= 0; i--)
    {
      FondosPicos[i].XPos += 6;

        if (FondosPicos[i].XPos > graphics.PreferredBackBufferWidth)
        {
           if (i == FondosPicos.Count -- 1)
              FondosPicos[i].XPos = FondosPicos[0].XPos -- FondosPicos[i].Largo + 6;
           else
              FondosPicos[i].XPos = FondosPicos[i + 1].XPos -- FondosPicos[i].Largo + 6;
        }
    }

//Piso
  Fondo.XPos += 10;
}
 

//Megaman

  if (Megaman.UltimaDir == 1 && Megaman.XPos > 0)
    Megaman.UpdateMov();
  else
    Megaman.FrameActual = 6;

Megaman.UltimaDir = 1;

 

Dado que la estructura es la misma que el bloque anterior solo explicaré algunas diferencias importantes. Primero, como es obvio todas las condiciones y los límites se basan en el lado izquierdo de la pantalla, así por ejemplo en la sección Avance permitimos el desplazamiento de Megaman siempre y cuando no rebase el límite permitido que es hasta X = 100 o hasta el final de la pantalla si Fondo se encuentra recorrida completamente a la derecha.

 

En la sección cielo la diferencia principal con el bloque anterior es que sí cuenta con una validación después de incrementar 3 pixeles a la posición de FondoCielo ya que si alguna de las imágenes se sale de la pantalla se pasará al principio de la lista de manera inversa a lo que teníamos en el bloque anterior. Esta misma lógica se aplica ala sección ‘Picos’ en el que al salir una imagen del lado de la pantalla se recorre enseguida al principio de la lista.

 

 

Finalmente en la sección ‘Megaman’ al igual que en bloque anterior, actualizamos los sprites de Megaman siempre y cuando no se salga de la pantalla.Fuera de estos dos bloques de condición vamos a escribir el siguiente código

 

  for (int i = 0; i < FondosCielo.Count; i++)
  {
      if (FondosCielo[i].XPos + FondosCielo[i].Largo < 0)
      {
          if (i == 0)
            FondosCielo[i].XPos = FondosCielo[FondosCielo.Count - 1].XPos + FondosCielo[FondosCielo.Count - 1].Largo;
          else
            FondosCielo[i].XPos = FondosCielo[i - 1].XPos + FondosCielo[i - 1].Largo;
      }
  }

 

Este código lo que hace es verificar cada una de las imágenes de la lista FondoCielo y la razón por la que está afuera de las condiciones es porque como recordarán, ese fondo se mueve independientemente y por lo tanto necesitamos verificar que en ese movimiento no se salga de la pantalla. Es por esta razón que en el primer bloque el avance FondoCielo no tenía ningún límite para su avance pues se necesitaba validar al presionar la tecla de dirección derecha y también cuando no se presionaba ninguna tecla. De esta forma nos ahorramos una de las validaciones.

 

Lo que hacemos, como en casos anteriores es verificar que la posición de las imágenes FondoCielo estén siempre dentro de la pantalla o de lo contrario se moverá al final de la lista la que este fuera.

 

 

Modificación del método Draw()

 

Lo último que nos resta es dibujar en pantalla tanto los fondos como a nuestro personaje para esto vamos a escribir en dentro del método Draw() de nuestra clase AnimSprite el siguiente código:

 

    foreach (AnimSprite Tmp in FondosCielo)
      Tmp.Draw(spriteBatch);

    foreach (AnimSprite Tmp in FondosPicos)
      Tmp.Draw(spriteBatch);

  Fondo.Draw(spriteBatch);

  Megaman.Draw(spriteBatch);
  base.Draw(gameTime);

 

Lo que hacemos es dibujar cada una de las imágenes de cada una de las listas y finalmente dibujamos a Megaman en su posición actual. Es importante que se escriba el código en este orden porque se Irán dibujando y apilado las imágenes en el orden en que se va leyendo el código por lo tanto si dibujamos una lista antes de la otra se quedarán atrás y no se verán.

 

Finalmente mandamos llamar al método Draw() de nuestra clase base y listo, ya tenemos nuestros tres fondos a velocidades diferentes que aunque no tiene aún un sistema de colisión se verá así

 

 

Las ligas a los archivos de este proyecto están aqui

 

 

Espero que no haya sido muy confuso este largo post y que haya sido útil para ustedes. No olvides tus comentario antes de salir.

Gracias y nos vemos en el siguiente post.

 

Piroshi.

 

 


Tags: , , , ,

XNA

 

 

Bienvenidos a este nuevo post en el que como dice el título vamos a programar el scroll del fondo para nuestro juego en 2D que hemos estando programando Si quieres conocer un poco sobre algunos tipos de fondos que se pueden programar en un juego 2D, puedes consultar el post “Background Images” antes de continuar.


Los puntos que vamos a ver en este post son los siguientes :

  • Cargar imágenes de fondo
  • Crear un Arreglo de objetos para los fondos
  • Programación del movimiento del scroll
  • Aplicación de este método

Primero voy a explicar lo que vamos a hacer.

Hasta el momento lo que tenemos es a nuestro personaje que se puede desplazar de derecha a izquierda en un escenario de fondo fijo. Si el personaje se desplaza fuera de los límites de la pantalla, simplemente sale de nuestro campo de visión y hay que avanzar en la dirección opuesta para volverlo a ver. Lo que queremos es básicamente un escenario más grande y que nuestra cámara imaginaria siga el movimiento de nuestro personaje. Para lograr esto vamos a programar un fondo con avance por movimiento del personaje. Podríamos cargar una imagen grande y desplazarla conforme el personaje va avanzando como se ve en la siguiente imagen.

 

 

FondoLargo1

El problema con esta solución es que tendríamos que cargar una imagen muy grande y si hay partes del nivel en las que el personaje se desplaza hacia arriba o abajo tendríamos partes de la imagen que irían vacías y se desperdiciaría el espacio. Es cierto que si estamos programando un juego en 2D en XNA nos debería importar un cacahuate desperdiciar memoria y más aún que estamos empezando con un programa tan sencillo podríamos cargar imágenes muy grandes sin preocuparnos por el desempeño, sin embargo creo que siempre es bueno tener en mente la optimización de recursos, principalmente porque las técnicas que aprendamos aquí las podemos llevar a otros entornos de desarrollo como dispositivos móviles en los que el uso de memoria y procesador sigue siendo algo muy importante, por lo que se recurre algunas veces al desarrollo de juegos basados en tiles para ahorrar recursos. Además si ocupamos tiles para el fondo podemos ahorrarnos también tiempo de diseño; bueno en caso de que empieces a desarrollar tus propios fondos.

Por estas razones es que utilizaré un método en que utilizo tres fondos que se irán mostrando uno tras otro conforme el personaje va avanzando de la siguiente manera:


FondoLargo2

 

Cuando el personaje avance a la derecha y llegue a la coordenada X = 540 empezaremos a desplazar  el fondo a la izquierda y para nuestro ejemplo también si el personaje avanza a la izquierda y alcanza la coordenada X=100 se desplazará a la derecha. Por otro lado, la forma en la que se irán mostrando los fondos será cíclico, es decir en el siguiente orden: uno, dos, tres, uno, dos, tres, uno…. etc. Si el avance es hacia la izquierda será de igual forma : tres ,dos , uno, tres, dos, uno … etc.

 

 

Cargar imágenes de fondo

 

Lo primero que vamos a hacer es cargar las imágenes de fondo a nuestro proyecto de la misma forma en que lo hicimos en el post “Carga y animación de sprites”; Es importante que cargues las tres porque Fondo1.png, aunque tiene el mismo nombre fue modificada.
Las tres imágenes de fondo las puedes bajar de aquí

 

 

Crear un Arreglo de objetos para los fondos

 

Lo siguiente que vamos a hacer es utilizar nuestra clase AnimSprite para los fondos de imagen. La razón de este cambio es porque ahora necesitamos modificar la posición de los mismo y con la estructura actual tendríamos que declara un vector por cada fondo, cosa que rompería con nuestra estructura orientada a objetos que queremos mantener pues estaríamos utilizando un objeto y sus propiedades como entidades diferentes. Talvez la solución más adecuada sería crear una nueva clase Fondos o una clase Sprites de la que la heredera sus funciones AnimSprites pero creo que si hacemos este cambio será más adelante cuando empecemos a agregar otro tipo de elementos al juego.

 

Para crear los objetos vamos a abrir nuestra clase Engine.cs y primero vamos a sustituir la línea

 

         privateTexture2DFondo1;

 

por esta otra:

 

        AnimSprite[] Fondos = newAnimSprite[3];

 

para declarar nuestro arreglo que utilizaremos para los tres fondos. Por otro lado tenemos que modificar el código que utlilizamos para cargar las imagenes para hacerlo de una forma parecida a la que cargamos los sprites de Megaman. El código lo vamos a agregar dentro de nuestro método LoadContent() para sustituir al código que utilizábamos anteriormente y quedará así:

           
for (int i = 1; i <= 3; i++)
           {
                int Px = (i – 1) * 730;
                Fondos[i - 1] = new AnimSprite(Px, 0,0, new Vector2(0,0));
                Fondos[i - 1].CargaImagen(Content.Load<Texture2D>(“Sprites/Fondo” + i));
           }

 

Lo que estamos haciendo aquí, es iterar tres veces para cargar los tres fondos y como hicimos con los sprites de Megaman, aprovechamos el número al final del nombre de la imagen para no tener que escribir el código tres veces.
La variable temporal Px la ocupamos para determinar la posición X inicial de los fondos, aunque esta posición solo nos interesa para las primeras dos imágenes, como veremos más adelante. La forma en que determinamos la posición es utilizar la variable i del ciclo for para multiplicarlo por 730, que es el ancho de cada imagen de fondo; Es importante que las tres imágenes tengan las mismas dimensiones y si cargan otras imágenes es importante modificar este valor por el ancho de las imágenes a cargar, por otro lado, si deciden cargar imágenes de diferentes dimensiones este valor deberá ser variable.
Una vez que determinamos la posición X por cada fondo, instanciamos cada objeto con el constructor que creamos la vez anterior. Ya con el objeto creado utilizamos el método CargaImagen() para copiar cada imagen en los objetos.
Finalmente en este paso vamos a modificar en el método Draw() de nuestra clase Engine.cs para dibujar el fondo utilizando el método Draw() de nuestros objetos pero para hacer esto tengo que explicar varias cosas antes.
Primero, como ya explique, vamos a ocupar tres imágenes de fondo que se irán desplazando en la pantalla en sentido contrario al desplazamiento de nuestro personaje. Las dimensiones de cada imagen son 730×480 y conforme la primer imagen se va desplazando, se va mostrando la siguiente y una vez que esta a alcanzado el extremo opuesto de la pantalla, ocupará toda la pantalla hasta que se desplace lo suficiente para dar espacio a la siguiente. Lo que quiero decir es que en el proceso siempre se mostrarán una o dos imágenes en pantalla pero nunca tres. (Para que esto último ocurriera se necesitaría que el ancho de las imágenes de fondo fuera menor al ancho de la pantalla o para nuestro caso 480 pixeles ya que de esta forma habría un punto en el que se mostrarán tres imágenes en pantalla).

 

 

TresFondos

 

 

Por consiguiente vamos a estar manejando el movimiento de dos imágenes a la vez y por lo tanto primero vamos a declarar dos variables que utilizaremos para definir los dos fondos que se mostrarán. Estas dos variables se declararan dentro de nuestra clase Engine.cs y tendrán el valor inicial 0 y 1 que serán los dos primeros fondo que empezaremos a manejar.

 

        int FIndex1 = 0, FIndex2 = 1;

 

 

Nota: Existe una forma de programar el scroll de la pantalla en el que se cargan todos los fondos a la vez y va modificando la coordenada X de cada uno de ellos. Esta forma es más fácil de programar pero implica haber cargado todos los fondos en memoria, que es algo que como comente al principio quiero evitar.

 

 

Ya que tenemos las dos variables declaradas, ya podemos escribir las siguientes líneas dentro del código Draw().

 

 

            Fondos[FIndex1].Draw(spriteBatch);
            Fondos[FIndex2].Draw(spriteBatch);

 

 

Programación del movimiento del scroll

 

Lo siguiente que vamos a hacer es modificar el método Update() que es donde se llevará a cabo el cambio de posición de nuestros dos fondos.  Empezaremos por limitar el movimiento de nuestro personaje; Anteriormente incrementábamos 10 pixeles la posición del personaje si avanzaba a la derecha o disminuimos 10 si avanzaba a la izquierda. Lo que haremos ahora es permitir este mismo movimiento solo si se encuentra dentro del área permitida que es entre 100 y 540 que es 100 pixeles más del borde izquierda y 100 pixeles menos del borde derecho.

 

 

limites_Pant

 

 

Para hacer esto vamos a escribir un if a nuestro incremento de la posición al avanzar a la derecha de la siguiente manera

 

                 if (Megaman.XPos < 540)
                      Megaman.XPos += 10;

 

de igual forma limitamos el avance a la izquierda de la siguiente manera:

 

                  if (Megaman.XPos > 100)
                      Megaman.XPos -= 10;

 

Con esto limitamos el avance del personaje pero no la animación. Lo que vamos a hacer ahora es incluir el código que desplaza los fondos para crear la ilusión de que el personaje sigue avanzando. Para lograr esto incluimos código debajo del if que agregamos para el avance a la derecha.

 

                  else
                 {
                      Fondos[FIndex1].XPos -= 10;
                      Fondos[FIndex2].XPos -= 10;

                        if (Fondos[FIndex2].XPos == 0)
                       {
                         FIndex1 = FIndex2;
                         Fondos[FIndex1].XPos = 0;

                           if(FIndex2 < 2)
                              FIndex2 += 1;
                           else
                             FIndex2 = 0;

                         Fondos[FIndex2].XPos = 730;
                     }
                 }

 

Lo que hacemos primero es reducir 10 pixeles a la posición en X de los dos fondos que estamos dibujando a la vez; Originalmente son los fondos 0 y 1.
Ya que reducimos los valores, verificamos que el segundo fondo (FIndex2) no haya alcanzado el borde izquierdo de la pantalla. De ser así necesitamos tener preparado el siguiente fondo del lado derecho y además vamos a cambiar los índices de los fondos de tal forma que el índice FIndex1 siempre esté apuntando al fondo de la izquierda y el índice FIndex2 siempre apunte al índice más a la derecha, como se muestra en la siguiente imagen:

 

 

CambioIndex

 

 

Lo que hacemos para lograr esto es pasar el valor de FIndex2 a FIndex1 , este movimiento lo podemos ver como si estuviéramos utilizando apuntadores y queremos que FIndex1 apunte ahora a la imagen a la que apuntaba FIndex2. Ya que  hicimos este cambio ahora vamos a mover el fondo a la posición 0 y con esto tendríamos a los dos Fondos con la misma imagen y en la misma posición. Los siguiente es cambiar primero la imagen que se desplazará del lado izquierdo. Para determinar esto lo que vamos a hacer es incrementar en 1 el valor de FIndex2 si el valor previo es menor a 2 (que es el indice de nuestro último fondo ) o le pasamos el valor de 0 si ya estábamos mostrando el último fondo. Por último vamos a desplazar este fondo a la posición X=730 que es el ancho de todas nuestras imágenes.
De igual forma para el desplazamiento a la izquierda escribimos este código.

 

                  else
                 {
                      if (Fondos[FIndex1].XPos == 0)
                     {
                          FIndex2 = FIndex1;
                          Fondos[FIndex2].XPos = 0;

                            if (FIndex1 > 0)
                              FIndex1 -= 1;
                           else
                              FIndex1 = 2;

                          Fondos[FIndex1].XPos = -730;
                     }

                      Fondos[FIndex1].XPos += 10;
                      Fondos[FIndex2].XPos += 10;
                 }

 

Para el desplazamiento a la izquierda lo que tenemos que hacer es incrementar la posición de los fondos en lugar de reducirlo. Sin embargo como podemos observar, este incremento de la posición de las variables no esta al principio del bloque sino al final, esto es debido a que si al iniciar el programa decidimos movernos a la izquierda primero incrementaría la posición en X del fondo y después verificaría si es igual a cero pero ya no sería 0 sino 10. Por otro lado, cuando el primer fondo alcanza la posición 0 lo vamos a desplazar a la izquierda a la posición -730 y el fondo al que apunta FIndex2 estará en pantalla. El código completo de este ejemplo lo puedes descargar aquí

 

 

Aplicación de este método

 

La razón principal para utilizar este método para el scroll es, como comenté antes, la facilidad para reutilizar los fragmentos de fondo y crear un fondo más grande de varias combinaciones. Para lograr esto lo que podemos hacer es utilizar un arreglo de índices en el que podamos almacenar que indice va a continuación del otro y seguir utilizando nuestras variables FIndex1 y FIndex2 para aumentar al fondo que se va a mostrando como se muestra en el siguiente esquema:

 

 

FondosArreglo

 

 

Como podemos ver utilizamos los mismos tres fondos y las mismas dos variables pero como paso intermedio tenemos el arreglo que va almacenar los indices de los fondos. Este arreglo puede ser tan grande como queramos y al contrario de nuestro ejemplo puede tener un límite en el que impidamos el avance del personaje. La programación de esta aplicación la dejo de tarea a quién quiera aplicarla para seguir en el siguiente post con la segunda parte de scrolls para fondos.

Como siempre espero sus comentarios y sugerencias y espero que haya sido de su agrado este post. Nos vemos en el siguiente.

 

 

Piroshi.

 

 

 


Tags: ,

Powered by Wordpress
Theme © 2005 - 2009 FrederikM.de
BlueMod is a modification of the blueblog_DE Theme by Oliver Wunder