How to Create a Parallax Effect in Monogame
This post will explain how to create a parallax effect in Monogame. First, take a look at the demo video to see what we will be doing:
This effect can be accomplished quite easily in Monogame. We create a Background class, so that we can layer multiple backgrounds together. This class will keep track of individual background images, speed, and zoom level.
Have a look at the documented code below:
Since the background textures are drawn to wrap, we create the illusion of moving the image by setting an Offset point to begin drawing our texture. This offset is manipulated by a Direction vector during the Update call.
I have provided a main Game class to demonstrate an implementation of this technique:
Feel free to download the source code.
Contact me with any questions or comments.
This effect can be accomplished quite easily in Monogame. We create a Background class, so that we can layer multiple backgrounds together. This class will keep track of individual background images, speed, and zoom level.
Have a look at the documented code below:
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; namespace MonogameParallax { 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)); } } public Background(Texture2D texture, Vector2 speed, float zoom) { Texture = texture; Offset = Vector2.Zero; Speed = speed; Zoom = zoom; } 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; } public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(Texture, new Vector2(Viewport.X, Viewport.Y), Rectangle, Color.White, 0, Vector2.Zero, Zoom, SpriteEffects.None, 1); } } }In order for these Backgrounds to fill our entire viewport area, they need to be drawn using a LinearWrap SamplerState. The SampleState is specified during our SpriteBatch initialization.
Since the background textures are drawn to wrap, we create the illusion of moving the image by setting an Offset point to begin drawing our texture. This offset is manipulated by a Direction vector during the Update call.
I have provided a main Game class to demonstrate an implementation of this technique:
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Collections.Generic; using Microsoft.Xna.Framework.Input; namespace MonogameParallax { public class MonogameParallax : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; List<Background> Backgrounds; public MonogameParallax() : base() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); //Load the background images Backgrounds = new List<Background>(); 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)); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { KeyboardState kbState = Keyboard.GetState(); if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); //Get directional vector based on keyboard input Vector2 direction = Vector2.Zero; if (kbState.IsKeyDown(Keys.Up)) direction = new Vector2(0, -1); else if (kbState.IsKeyDown(Keys.Down)) direction = new Vector2(0, 1); if (kbState.IsKeyDown(Keys.Left)) direction += new Vector2(-1, 0); else if (kbState.IsKeyDown(Keys.Right)) direction += new Vector2(1, 0); //Update backgrounds foreach (Background bg in Backgrounds) bg.Update(gameTime, direction, GraphicsDevice.Viewport); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); //Draw our parallax backgrounds, using a Linear Wrap spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null); foreach (Background bg in Backgrounds) bg.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } } }
Feel free to download the source code.
Contact me with any questions or comments.
Unfortunately your source code link is dead…