Parallax Scrolling

From TRCCompSci - AQA Computer Science
Jump to: navigation, search

Parallax Scrolling uses several background images, and then adjust an offset which makes the backgrounds move relative to each other. This makes it look like a scrolling background.

Method 1

This method requires a background to be 3 times the width of the screen, also no zoom is applied so you will need to create your backgrounds exactly as you want them.

Background Class

public class Background
    {
        public Vector2 Position;
        public Vector2 StartPosition;
        public Texture2D Image;
        public int Speed;
        public int Width;

        public Background(Vector2 pos, Texture2D img, int sp, int w)
        {
            StartPosition = pos;
            Position = pos;
            Image = img;
            Speed = sp;
            Width = w;
        }
    }

This is the base code for the background, we have a current position and a starting position for the background, a texture for the image, and an integer for the speed of the background and the overall width of the screen.

We must now create an update method for the background, and a draw method:

        public void Update(GameTime gameTime, int xdist)
        {
            Position.X -= (xdist*Speed);
            if (Position.X <= StartPosition.X - (Width))
                Position.X = StartPosition.X;
            else if (Position.X >= StartPosition.X + Width)
                Position.X = StartPosition.X;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Image, Position, Color.White);
        }

The update method uses xdist as a parameter, this will come from your game and will be negative if the player is moving to the left and positive if the player is moving to the right. The xdist is used to multiply the speed, and then change the X position of the background by this amount. We will set each background with a different speed.

the if statement is important because we need to detect when the background has travelled far enough and needs to be reset to the starting position.

Define a list of backgrounds

In your Game1.cs, we need to create a list to store the backgrounds in use. So declare the following with your other variables:

List<Background> backgrounds = new List<Background>();

In the LoadContent method we need to read in the backgrounds, and add them to our list of backgrounds:

    Vector2 pos = new Vector2(-(graphics.PreferredBackBufferWidth), 0);
    for (int i = 1; i <= 3; i++)
    {
        Background temp = new Background(pos, Content.Load<Texture2D>("Back" + i), i * 2, graphics.PreferredBackBufferWidth);
        Backgrounds.Add(temp);
    }

Each of my graphics are 3 times wider than the screen. The starting position of the background will need to be the -(width of the screen) , 0. The speed is the i value multiplied by 2, to ensure the background closest to the horizon is the slowest and the background furthest away from the horizon is the fastest.

Using the Backgrounds

Now in the Update method of Game1, we need to set a direction for the scrolling, and then update each background:

int direction=0;
if (Keyboard.GetState().IsKeyDown(Keys.A))
{
     direction = -1;
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
     direction = 1;
}

foreach (Background bg in Backgrounds)
     bg.Update(gameTime, direction);

Now in the Draw method of Game1 add the code before any foreground drawing:

spriteBatch.Begin();
    foreach (Background bg in Backgrounds)
        bg.Draw(spriteBatch);
spriteBatch.End();

The Textures

You can create your own background textures, or you can use these HERE. I created these in a matter of minutes, as such they are not perfect but they do show the effect. You will need to put them in the content folder of your project, and you will need to add them to the content pipeline and make sure they are built.

Method 2

This method is based around an online tutorial, it has more features than the previous method and requires a smaller background graphic because it multiplies the distance to move by the time elapsed.

Background Class

We need to create a class to create a background (this will be used to make 3 backgrounds). In your Game1.cs or by adding a class to the project enter the following code:

  public class Background
    {
        private Texture2D Texture;      //The image to use
        private Vector2 Offset;         //Offset to start drawing our image
        public Vector2 Speed;           //Speed of movement of our parallax effect
        public float Zoom;              //Zoom level of our image

        private Viewport Viewport;      //Our game viewport

        //Calculate Rectangle dimensions, based on offset/viewport/zoom values
        private Rectangle Rectangle
        {
            get { return new Rectangle((int)(Offset.X), (int)(Offset.Y), (int)(Viewport.Width / Zoom), (int)(Viewport.Height / Zoom)); }
        }
     }

This creates the basis for a background class. The background class will also need a constructor, this will be used to setup each background with a texture, the speed it scrolls, and a level of zoom:

        public Background(Texture2D texture, Vector2 speed, float zoom)
        {
            Texture = texture;
            Offset = Vector2.Zero;
            Speed = speed;
            Zoom = zoom;
        }

The background class will also need an update method, it essentially adjusts the offset of the background according to the elapsed time:

        public void Update(GameTime gametime, Vector2 direction, Viewport viewport)
        {
            float elapsed = (float)gametime.ElapsedGameTime.TotalSeconds;

            //Store the viewport
            Viewport = viewport;

            //Calculate the distance to move our image, based on speed
            Vector2 distance = direction * Speed * elapsed;

            //Update our offset
            Offset += distance;
        }

The background class will also need a draw method:

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(Texture, new Vector2(Viewport.X, Viewport.Y), Rectangle, Color.White, 0, Vector2.Zero, Zoom, SpriteEffects.None, 1);
}

Define a list of backgrounds

In your Game1.cs, we need to create a list to store the backgrounds in use. So declare the following with your other variables:

        List<Background> backgrounds = new List<Background>();

In the LoadContent method we need to read in the backgrounds, and add them to our list of backgrounds:

            backgrounds.Add(new Background(Content.Load<Texture2D>(@"Clouds1"), new Vector2(300, 300), 0.6f));
            backgrounds.Add(new Background(Content.Load<Texture2D>(@"Clouds2"), new Vector2(500, 500), 0.8f));
            backgrounds.Add(new Background(Content.Load<Texture2D>(@"Clouds3"), new Vector2(700, 700), 1.1f));

You will notice that each background has a different vector for speed. Parallax scrolling create the illusion of movement by moving the backgrounds at different speeds. The float value sets the zoom of the background, the front background has a higher value, and the back background has the lowest value. This creates the best effect but the scrolling will still work if each is set to '1f'.

Using the Backgrounds

Now in the Update method, we need to set a direction for the scrolling, and then update each background:

if (Keyboard.GetState().IsKeyDown(Keys.A))
{
     direction = new Vector2(-1, 0);
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
     direction = new Vector2(1, 0);
}

foreach (Background bg in backgrounds)
     bg.Update(gameTime, direction, GraphicsDevice.Viewport);

Now in the Draw method add the code before any foreground drawing:

spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
    foreach (Background bg in backgrounds)
        bg.Draw(spriteBatch);
spriteBatch.End();

The Textures

You can create your own background textures, or you can use these HERE. You will need to put them in the content folder of your project, and you will need to add them to the content pipeline and make sure they are built.