XNA, Managed DirectX and Game Programming

Parallax Scrolling Background using the XNA Framework

A little while ago I started playing around with some Parallax Scrolling examples, but recently a community member asked if I could post the sample code I was working on. So after cleaning it up a little bit here it goes.

To start with open a base windows game application and make sure it compiles and runs, next so that the application looks good on both the Xbox 360 and Windows set the display format to a format that looks good on both. Add the following lines of code to the game1 contructor, just under the setup for the content manager.

[code language="C#"]

            // Prefer a resolution suitable for both Windows and XBox 360
            graphics.PreferredBackBufferWidth = 853;
            graphics.PreferredBackBufferHeight = 480;

[/code]

The next step is to add another class to the project and add my background item class. Here is the code for the class.

[code language="C#"]

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace ScrollingBackground
{
    public class BackgroundItem
    {
        public Vector2 Position;
        private Vector2 Direction = new Vector2(-1, 0);
        public float Speed;
        public float SpeedConstant;

        public Texture2D BackgroundTexture;

        private Vector2 positionImage1;
        private Vector2 positionImage2;

        public BackgroundItem(Vector2 position)
        {
            this.Position = position;
        }

        public void LoadGraphicsContent(ContentManager content,string assetName)
        {
            this.BackgroundTexture = content.Load<Texture2D>(assetName);
            this.positionImage1 = this.Position;
            this.positionImage2 = new Vector2(this.Position.X + this.BackgroundTexture.Width, this.Position.Y);
        }

        public void Update(GameTime gameTime)
        {
            float timeDelta = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (this.positionImage1.X < (0 - this.BackgroundTexture.Width))
            {
                this.positionImage1.X = this.positionImage1.X + (this.BackgroundTexture.Width * 2);
            }

            if (this.positionImage2.X < (0 - this.BackgroundTexture.Width))
            {
                this.positionImage2.X = this.positionImage2.X + (this.BackgroundTexture.Width * 2);
            }

            this.positionImage1 += this.Direction * this.Speed * this.SpeedConstant * timeDelta;
            this.positionImage2 += this.Direction * this.Speed * this.SpeedConstant * timeDelta;

 

        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(this.BackgroundTexture, this.positionImage1, Color.White);
            spriteBatch.Draw(this.BackgroundTexture, this.positionImage2, Color.White);
        }
    }
}

[/code]

Now to set up all of the varibles needed for the application, Underneath the where the graphics and content manager are set up add the following...

[code language="C#"]

        GraphicsDeviceManager graphics;
        ContentManager content;

        SpriteBatch spriteBatch;

        Texture2D backgroundSkyTexture;

        BackgroundItem hillsBackground;
        BackgroundItem groundBackground;

[/code]

Adjust the load Graphics call so that it looks like this...

[code language="C#"]

        /// <summary>
        /// Load your graphics content.  If loadAllContent is true, you should
        /// load content from both ResourceManagementMode pools.  Otherwise, just
        /// load ResourceManagementMode.Manual content.
        /// </summary>
        /// <param name="loadAllContent">Which type of content to load.</param>
        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            if (loadAllContent)
            {
                // TODO: Load any ResourceManagementMode.Automatic content
                this.spriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);

                this.backgroundSkyTexture = content.Load<Texture2D>(@"Content\Textures\Background_Sky");

                hillsBackground.LoadGraphicsContent(content,@"Content\Textures\Background_Hills");
                groundBackground.LoadGraphicsContent(content,@"Content\Textures\Background_Ground");

            }

            // TODO: Load any ResourceManagementMode.Manual content
        }

[/code]

So that we can update the Background Items so that they can move, change your update override in the game1 class to look like this...

[code language="C#"]

        /// <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
            hillsBackground.Update(gameTime);
            groundBackground.Update(gameTime);

            base.Update(gameTime);
        }

[/code]

And Finally to draw the Background change your Draw over ride to look like this...

[code language="C#"]

        /// <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)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            this.spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
            this.spriteBatch.Draw(this.backgroundSkyTexture, new Vector2(0, 0), Color.White);

            hillsBackground.Draw(this.spriteBatch);
            groundBackground.Draw(this.spriteBatch);

            this.spriteBatch.End();

            base.Draw(gameTime);
        }


[/code]

I know that the post seems a little rushed, but you should get the idea, Here is a link to the complete code sample so that you can pull it apart if needed. If you have anythoughts on it remember to post them.

Cross Post from www.virtualrealm.com.au
Posted: Sat, Aug 18 2007 23:49 by Glenn Wilson | with no comments
Filed under: , ,
Leave a Comment

(required) 

(required) 

(optional)

(required)