Skip to content
septiembre 16, 2010 / 100xna

[Basico] Parallax Scroll


Nota: Esta entrada la escribí hace ya algún tiempo en el foro de www.creagamers.es. Si quieres ver la entrada original, sigue el este enlace.


¿Que es Parallax Scroll?
Parallax Scroll (o scrolling parallax) es una técnica aplicada a juegos 2D donde superponiendo varias capas y moviendo cada capa a una velocidad distinta, se consigue un efecto de profundidad en el juego.
El parallax scroll es una técnica que se usaba mucho en los antiguos juegos 2D. Juegos como Mario Bros, Sonic, Castlevania, etc… hacen uso de esta técnica. Podéis encontrar más información en la wikipedia: Parallax_scrolling

¿Que vamos a hacer?
En este ejemplo, vamos a hacer dos tipos de parallax:

  • Movimiento automático: Ideal para juegos de naves que se mueven automáticamente hacia la derecha.
  • Movimiento manual: Solo se mueve cuando pulsamos una tecla de dirección. Ideal para plataformas u otro tipo de juegos donde queremos que la pantalla se mueva con nuestro personaje.

      Vale, me gusta la idea ¿Que necesito para hacerlo?
      Pues necesitas VisuaStudio 2008 Professional (si tienes dinero para pagarlo,  ;)), o Visual C# 2008 Express (gratuito). También necesitáis, lógicamente, XNA 3.1 instalado. Si no lo tienes instalado, visita esta web: Instalar XNA 3.1

      Lo más importante: necesitamos las capas. Os dejo con 3 imágenes, que además de mostrar que soy un negado dibujando, nos servirán para hacer el pequeño ejemplo que vamos a programar. Descargar imágenes para el ejemplo

      También os dejo con el código fuente para que podáis ver como se aplica en verdad: Código Fuente del proyecto

      Y por último, unos conocimientos básicos de programación. No muchos, pero lo mínimo como para entender lo que estáis haciendo. Que eso de copy/paste sabemos hacerlo todos,  😀

      ¿Vale, he visto el código fuente, lo he probado, pero no me entero de nada. Lo puedes explicar?
      Claro, para eso estamos.
      Primero vamos a pegarle un vistazo a lo que tenemos:

       

      Como podéis ver, lo que tenemos es que el juego contiene una lista de capas.

      Empezamos por la clase "CapaParallax". Esta clase representa una capa de las que os he hablado antes.

      La capa tiene varios atributos. Los importantes son la textura (la imagen que queremos mostrar) y la velocidad, que representa la velocidad con la que se va a mover esa capa. Como bien he dicho antes, el efecto de profundidad se consigue moviendo varias capas a distinta velocidad. Normalmente, las que están más atrás se mueven más lentas, y las que están más próximas al jugador se mueven más rápido.

      private Texture2D textura; //Textura de la capa
      private Vector2 posicion; //Posicion donde pintamos la textura
      private float velocidad; //Velocidad de movimiento de la capa

       

      La otra variables son para conseguir que la imagen sea "continua". Es decir, que se convierta en un bucle. Cuando desaparece por un lado, vuelve a aparecer, y así no quedan huecos en blanco entre las imágenes.

       

      private Vector2 desplazamiento; //Offset de la textura

      Vamos a definir dos métodos: "moverDeerecha()" y "moverIzquierda()". Cada método desplazará la capa hacia la dirección indicada tantos píxeles como indique el atributo "velocidad".

      public void MoverDerecha(GameTime gameTime){
          float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;

          posicion.X -= velocidad * delta;
          posicion.X = posicion.X % textura.Width;
      }

      public void MoverIzquierda(GameTime gameTime){
          float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;

          posicion.X += velocidad * delta;
          posicion.X = posicion.X % textura.Width;
      }

       

      En el metodo "Update()" Lo que vamos a hacer es mover la capa hacia la izquierda. Asi dará la sensación de que nos movemos a la derecha.

      public void Update(GameTime gameTime){            
          MoverDerecha(gameTime);            
      }
       

      HAZLO TU: También puedes definir sólo un método y como argumento pasarle la dirección que queremos que se mueva: "mover(dirección)". Si tienes alguna duda, pregunta

      Por último, en el método "Draw()" lo que haremos será pintar la textura en la posición calculada, y en caso de que no ocupe toda la pantalla, vamos a dibujar una 2º textura (la misma) para dar la sensación de continuidad.

      public void Draw(SpriteBatch spriteBatch){
          //Como es una capa "continua", tenemos que dibujarla
          // otra vez cuando se salga de la pantalla
          if (posicion.X < viewportWidth)
          {
              spriteBatch.Draw(textura, posicion, Color.White);
          }
          spriteBatch.Draw(textura, posicion + desplazamiento, Color.White);
      }

       

      Ahora que tenemos la clase "CapaParallax", vamos a usarla en el juego. Para eso, vamos a la clase "Game1.cs".
      En esta clase, para representar las capas, tenemos una lista donde vamos a almacenar todas las capas:

      private List<CapaParallax> capasParallax;

       

      Y las texturas que usaremos en el juego:

      private Texture2D planeta; //Capa del fondo
      private Texture2D espacio; //Capa intermedia
      private Texture2D rocas; //Capa mas cercana

       

      En esta lista tenemos que meter todas las capas que queremos usar en el juego. Hay que meterlas en orde

      protected override void Initialize(){
          //Cargamos las texturas de las capas
          planeta = this.Content.Load<Texture2D>("planeta");
          rocas = this.Content.Load<Texture2D>("rocas");
          espacio = this.Content.Load<Texture2D>("espacio");

          //Creamos las capas
          capasParallax = new List<CapaParallax>();
          
          //Cuidado con el orden de insercion.
          //1º lo mas alejado, luego lo mas cercano
          capasParallax.Add(new CapaParallax(graphics, planeta, 0.0f)); //la velocidad es 0, no se mueve
          capasParallax.Add(new CapaParallax(graphics, espacio, 10.0f));
          capasParallax.Add(new CapaParallax(graphics, rocas, 50.0f));

          base.Initialize();
      }

       

      En el método "Update()" vamos a actualizar las capas. Como tenemos dos modos de movimiento (manual/automático) vamos a comprobar en que tipo estamos. En caso de ser automático, simplemente llamamos al método "Update" de todas las capas de la list. Para recorrer la lista de capas, podemos usar un "foreach" (más simple) o un bucle "for" (más eficiente.)

      foreach (CapaParallax capa in capasParallax){
          capa.Update(gameTime);
      }

      NOTA: Si habéis visto el código fuente, existe un atributo llamado "automático". Este atributo indica si el movimiento de las capas es automático o no. En el método "Uptate" comprobamos si está pulsada la tecla 1 o 2, y si estan pulsadas, asignamos en tipo de movimiento (automático o manual) según corresponda. Si lo queremos hacer siempre automático, no haría falta que metieras el atributo automático y que comprobaras que tecla de dirección esta pulsada.

      Si es manual, comprobamos que tecla hemos pulsado. Dependiendo de la tecla pulsada, movemos hacia un lado o hacia otro con los métodos "moverIzquierda" y "moverDerecha" de cada capa. Igual que antes, hay que recorrer todas las capas de la lista!

      if (Keyboard.GetState().IsKeyDown(Keys.Right)) {
          foreach (CapaParallax capa in capasParallax)
          {
              capa.MoverDerecha(gameTime);
          }
      }
      else if (Keyboard.GetState().IsKeyDown(Keys.Left)) {
          foreach (CapaParallax capa in capasParallax)
          {
              capa.MoverIzquierda(gameTime);
          }
      }

       

      Por último, nos queda pintar las capas. En el metodo "Draw()", recorremos la lista de capas llamando al método "Draw" de cada capa. Como por defecto XNA pinta de "atrás hacia delante" (deferred), si quieres que las capas estén detrás de tu personaje, escenario, enemigos, etc… pinta las capas antes de pintar cualquier cosa más en el juego.

      protected override void Draw(GameTime gameTime){
          GraphicsDevice.Clear(Color.Black); //pintamos el fondo de color negro

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

          //Pintamos las capas
          foreach (CapaParallax capa in capasParallax){
              capa.Draw(spriteBatch);
          }
          spriteBatch.End();
      }

      ¡Ya lo tengo hecho! (y lo he entendido) ¿Como puedo mejorar lo que tengo?
      Bien, llegó el momento de que trastees con XNA, que es como realmente se aprende. Ahora mismo tienes un scroll muy básico. Puedes mejorarlo, por ejemplo, metiendo varias imágenes en una capa, y en lugar de que siempre se repita la misma, vaya cogiendo al azar cual es la "parte" que se va a mostrar ahora.

      Imaginar que cada [X] es una imagen de la misma capa. Pues lo que digo seria algo asi:
          [1]  [4]  [2]  [1]  [5]  [3]  [1] …

      De esta forma se conseguiría una capa más "llamativa", ya que no se repetiría siempre igual.

      Si tienes alguna duda más, no dudes en preguntar aquí. Y si realizas mejoras, escribe un comentario y así todos aprendemos!

      También podrías encapsular el parallax dentro de una clase "Nivel" para tener el código más limpio y ordenado. Podrías pensar en algo así:

       

      Espero que os sirva de ayuda este pequeño tutorial. Es bastante simple, pero puede servir como punto de partida para hacer un jueguecillo simple en XNA.

      Anuncios

      2 comentarios

      1. Carlos / Oct 27 2010 10:36 pm

        Como ya te comente en su momento, felicidades por el tutorial 😉
        Y gracias por citarnos a http://www.creagamers.es en el articulo
        Un saludo

      2. marcos / Nov 11 2010 5:25 am

        oie felicidades pues yoo estudio la carrera de ing en sistemas y pues un profesor nos esta pidiendo este tipo de juegos y la verdad me gusta eso de acer juegos y la verdad despues me gustaria aprender hacer juegos flash neta felicidades y pues espero contactarte para cualquier duda o pasar informacion para nutrir mas nuestra sed de aprender

      Los comentarios están cerrados.

      A %d blogueros les gusta esto: