Scrolling Backgrounds

Scrolling backgrounds

Go into Paint.NET and create an 800x480 picture. Draw mountains, but make sure that the mountains end on the right side on the same pixel that they start on on the left side. Color the mountains green and the sky blue. Save your file as hills.png.

Create a new project called Scrolling.

Add our Viewport code. Note that this requires a Rectangle variable called screen.

In declarations area:

float scaleFactor = 1;

Rectangle screen;

GamePadState pad;

In Initialize:

// Set a viewport so we never have to worry about

//drawing anything outside of the playing area!

Viewport v = newViewport();

v.X = (int) (GraphicsDevice.Viewport.Width * (1-scaleFactor)/2);

v.Y = (int) (GraphicsDevice.Viewport.Height * (1-scaleFactor)/2);

v.Width = (int) (GraphicsDevice.Viewport.Width * scaleFactor);

v.Height = (int) (GraphicsDevice.Viewport.Height * scaleFactor);

GraphicsDevice.Viewport = v;

screen.Width = GraphicsDevice.Viewport.Width;

screen.Height = GraphicsDevice.Viewport.Height;

To scroll, we need two copies of the background. We will constantly be moving one copy off of the screen, while we will be moving one copy on the screen.

We will need an array of two images. Declare the following:

struct SpriteStruct

{

public Texture2D texture;

public Rectangle position;

public float X;

public Color color;

}

SpriteStruct [] hills;

We also need to keep track of how fast we are scrolling:

constfloat secondsToCrossScreen =2;

float pixelsPerTick;

float totalPixelsTraveled;

And which direction we are moving:

enumScrollingState

{

movingLeft,

movingRight

}

ScrollingState scrollingState;

In Initialize, create the hills array and the pixels per tick:

hills = new SpriteStruct[2];

pixelsPerTick = (screen.Width / secondsToCrossScreen / 60);

And initialize your direction:

scrollingState = ScrollingState.movingRight;

In LoadContent, initialize the hills array.

for (int i = 0; i < 2; i++)

{

hills[i].texture = Content.Load<Texture2D>("ScrollingHills");

if (scrollingState == ScrollingState.movingLeft)

{

hills[i].position.X = i * screen.Width;

hills[i].X = i * screen.Width;

}

else

{

hills[i].position.X = -i * screen.Width;

hills[i].X = -i * screen.Width;

}

hills[i].position.Y = 0;

hills[i].position.Width = screen.Width;

hills[i].position.Height = screen.Height;

hills[i].color = Color.White;

}

Add to Update:

UpdateHills();

Write the UpdateHills method:

void UpdateHills()

{

for (int i = 0; i < 2; i++)

{

if (scrollingState == ScrollingState.movingRight)

{

// NOTE: X is the true position--a float!

hills[i].X += pixelsPerTick;

// if we go too far, we may have gone several pixels past

if (hills[i].X > screen.Width)

hills[i].X = hills[i].X – (screen.Width * 2);

// Convert the true (float) position into the nearest pixel (int)

hills[i].position.X = (int)(hills[i].X + 0.5f);

}

else

{

// background moves to left

hills[i].X -= pixelsPerTick;

if (hills[i].X < -screen.Width)

hills[i].X = hills[i].X + (screen.Width * 2);

hills[i].position.X = (int)(hills[i].X + 0.5f);

}

}

}

And, we need to draw our hills.

spriteBatch.Begin();

for (int i = 0; i < 2; i++)

spriteBatch.Draw(hills[i].texture, hills[i].position, hills[i].color);

spriteBatch.End();

To test our movement in both directions, we need this in Update:

pad = GamePad.GetState(PlayerIndex.One);

if (pad.Buttons.A == ButtonState.Pressed)

scrollingState = ScrollingState.movingLeft;

if (pad.Buttons.B == ButtonState.Pressed)

scrollingState = ScrollingState.movingRight;

Now let's add a mountain climber. In the declarations area:

SpriteStruct climber;

In LoadContent:

climber.texture = Content.Load<Texture2D>("hillclimber");

climber.position.Width = (int) (screen.Width * .05f);

climber.position.Height = (int) (screen.Height * 0.10f);

climber.position.X = 0; // (int)(489 * scaleFactor);

climber.position.Y = (int)(187 * scaleFactor) - climber.position.Height;

climber.color = Color.White;

In Update:

UpdateClimber();

UpdateClimber (let students write this on their own):

publicvoid UpdateClimber()

{

if (scrollingState == ScrollingState.movingRight)

{

climber.X += pixelsPerTick;

// if we go too far, we may have gone several pixels past

if (climber.X > screen.Width)

climber.X = climber.X - screen.Width;

// Convert the true (float) position into the nearest pixel (int)

climber.position.X = (int)(climber.X + 0.5f);

}

else

{

// background moves to left

climber.X -= pixelsPerTick;

// if we go too far, we may have gone several pixels past

if (climber.X < -climber.position.Width)

climber.X = screen.Width;

// Convert the true (float) position into the nearest pixel (int)

climber.position.X = (int)(climber.X + 0.5f);

}

}

11/7/2018Day018--FinishNestedLoops--ScrollingBackgrounds.docxPage 1 of 4