Creating the Parallax and Scrolling Background

This article is cross-posted from DracoWing.com.  Draco Wing is a new XNA based game for the Xbox 360 I am working on, and I will be keeping a “diary” of sorts on the design and development of the game.

The gameplay in Draco Wing will require the background to scroll, while the player’s spaceship stays centered in the play field.  I want the play field to be adjustable, as I don’t have a HUD designed yet, so it’s a requirement that this be configurable.  I’m also going to setup a star field behind the background so I can create a simple parallax effect.  The background and the star field will need to scroll in all directions and loop, e.x. the player can fly off the left side of the map and reappear on the right.

I’m going to start off with the background being 2048x4096, or “quite freaking huge”, and will 1-1 map ship coordinates with the background.  This is going to make the artist happy, and hopefully performance and size will let me keep it in the end product, but we might have to cut it down a bit later in production and scale the result.  With Dxt compression this image at 24 bit is 4mb (if I use a true Alpha channel instead of color keying, it’s 8mb – the artist can deal with keying).  For comparison, my star field image is 256x256 at 8 bit is 33 kb.

Displaying the images on screen turns out to be quite simple with XNA.  The framework ships with a group of SamplerStates for wrapping a texture that will repeat the texture to fill the target space: SamplerState.PointWrap, SamplerState.LinearWrap, and SamplerState.AnisotropicWrap.  The differences between these are explained by Shawn Hargreaves here and here, but the short answer is they tell the GPU how to map a pixel from the source texture to the screen when scaling is involved.  The point method is the fastest, by just finding the closest pixel to the target and scaling that one pixel.  Linear takes a sample of the surrounding pixels, and creates an average color value that results in a less “pixelated” or “blocky” result.  Anisotropic is similar to Linear, only takes into account any height / width ratio differences between source and target.  These different values really come into play with things like 3D terrain, but in my case I’m not doing any scaling so I can go with Point and have no loss in visual quality.

With XNA and the GPU doing all the hard math for me, the only part I need to do is set the “start point” for the star field and background, which is based on the location of the ship in game space (remember in screen space, the ship doesn’t move).  In initialization I create a Rectangle called “view” that is the screen space I want the background to render in.  Then in the Update method for my custom Background class I calculate the start points:

public void Update(GameTime gametime, Point location) {
starfieldRect.X = location.X % starfield.Bounds.Width;
starfieldRect.Y = location.Y % starfield.Bounds.Height;
backgroundRect.X = location.X - view.Width / 2;
backgroundRect.Y = location.Y - view.Height / 2;
}

During initialization I set the Height and Width properties to that of the view, since these won’t change during gameplay.  By dividing the value of location by two on the starfield cause the stars to move twice as slow, and creates the desired parallax effect.  Even though the background screen space size is the same at the game space size, I have to account for the fact the ship is in the middle of the play field and thus subtract half the view from the location.  (Have I mentioned the value of keeping graph paper near your desk when developing games?)

The Draw method is basic as well, just make sure to enable the desired SampleState in the Begin call:

public void Draw(SpriteBatch spriteBatch, GraphicsDevice GraphicsDevice) {
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.Default, RasterizerState.CullNone);
spriteBatch.Draw(starfield, view, starfieldRect, Color.White);
spriteBatch.Draw(background, view, backgroundRect, Color.White);
spriteBatch.End();
}

 

Check me out, I’m going to Mars!

image


Posted 11-26-2010 2:15 AM by Michael C. Neel

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)