+ All Categories
Home > Documents > XNA 4.0 Side Scrolling - Murray State...

XNA 4.0 Side Scrolling - Murray State...

Date post: 25-Jun-2018
Category:
Upload: hoangcong
View: 228 times
Download: 0 times
Share this document with a friend
23
XNA 4.0 Side Scrolling
Transcript

XNA 4.0

Side Scrolling

Setting up the Graphics Display

For a side-scrolling application we will want the vertical resolution of the graphical

display region to match the vertical resolution of the background image.

The default name of the graphical display in XNA is graphics and can be accessed

from anywhere in the code. We set the preferred size of the graphical display from

within the Initialize( ) method.

In our case we are using a background image of size 4096 x 348 so we set the vertical

resolution to 348. Note that the maximum dimension of a Texture2D in XNA 4.0 is

4096 to which we have resized our sample background image using an image editor.

graphics.PreferredBackBufferWidth = 800;

graphics.PreferredBackBufferHeight = 348;

graphics.ApplyChanges();

pano_bkg_01.jpg

spriteBatch.Draw(panobkg, bkgorigin, bkg, Color.White, 0, bkgorigin, 1, 0, 1);

(0,0)

graphics window

keystate = Keyboard.GetState();

if (keystate.IsKeyDown(Keys.Right))

bkg.X += 4;

if (keystate.IsKeyDown(Keys.Left))

bkg.X -= 4;

if (bkg.X < 0)

bkg.X = 0;

if (bkg.X > panobkg.Width - bkg.Width)

bkg.X = panobkg.Width - bkg.Width;

Selecting the Background Image

The portion of pano_bkg_01.jpg that is selected to display is determined by the X value

of the upper left corner of the bkg Rectangle.

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

Texture2D panobkg;

Rectangle bkg;

Vector2 bkgpos;

Vector2 bkgorigin;

KeyboardState keystate;

public Game1()

{

graphics = new GraphicsDeviceManager(this);

Content.RootDirectory = "Content";

}

protected override void Initialize()

{

base.Initialize();

bkgpos.X = 0;

bkgpos.Y = 0;

graphics.PreferredBackBufferWidth = 800;

graphics.PreferredBackBufferHeight = 348;

bkg = new Rectangle(0, 0, graphics.PreferredBackBufferWidth,

graphics.PreferredBackBufferHeight);

bkgorigin.X = 0;

bkgorigin.Y = 0;

graphics.ApplyChanges();

}

protected override void LoadContent()

{

spriteBatch = new SpriteBatch(GraphicsDevice);

panobkg = Content.Load<Texture2D>("pano_bkg_01");

}

panoramicView Source

panoramicView.zip

protected override void LoadContent()

{

spriteBatch = new SpriteBatch(GraphicsDevice);

panobkg = Content.Load<Texture2D>("pano_bkg_01");

}

protected override void Update(GameTime gameTime)

{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

this.Exit();

keystate = Keyboard.GetState();

if (keystate.IsKeyDown(Keys.Right))

bkg.X += 4;

if (keystate.IsKeyDown(Keys.Left))

bkg.X -= 4;

if (bkg.X < 0)

bkg.X = 0;

if (bkg.X > panobkg.Width - bkg.Width)

bkg.X = panobkg.Width - bkg.Width;

base.Update(gameTime);

}

protected override void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();

spriteBatch.Draw(panobkg, bkgorigin, bkg, Color.White, 0,bkgorigin, 1, 0, 1);

spriteBatch.End();

base.Draw(gameTime);

}

panoramicView Source (concluded)

panoramicView.zip

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

Texture2D panobkg; // panoramic background image

Rectangle bkg; // rectangle of size that matches the graphical display

Vector2 bkgpos; // upper left corner of region of panobkg being displayed

Vector2 bkgorigin; // always equal to (0,0)

Vector2 homerpos; // position of character in display region

KeyboardState keystate;

Rectangle homer; // rectangle 57x87 pixels for spritesheet blitting

Texture2D homersprite; // homer_spritesheet

Random rnd = new Random();

float homerflip; // character rotation angle

Vector2 homercenter = new Vector2(28, 43);

int homercount; // sprite frame count for running and jumping sequence

int jumpcount; // set to either 0 (no jumping) or 7 (jumping)

int mshomer = 60; // sprite animation frame time (60 milliseconds)

int msdel; // accumulator for animation frame time

double y; // character vertical position (used for jumping)

int ybase; // limiting value of y position (bottom of display region)

double vy; // vertical velocity of character (used for jumping)

double ay = -0.1; // effect of gravity on character (downward acceleration)

SoundEffect woohoo; // character sounds

SoundEffect scream;

SoundEffect doh;

theJogger Global Declarations

The panoramicView demo project has been modified/extended to include a running and

jumping character (Homer Simpson). The new version is named theJogger. The following

is a list of the globally defined parameters used in this project.

protected override void Initialize()

{

base.Initialize();

bkgpos.X = 0; // upper-left corner of display region position on panobkg

bkgpos.Y = 0;

graphics.PreferredBackBufferWidth = 800;

graphics.PreferredBackBufferHeight = 348;

bkg = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);

bkgorigin.X = 0;

bkgorigin.Y = 0;

graphics.ApplyChanges(); //changes the display (graphics) as specified in earlier statements

homer.X = 0;

homer.Y = 0;

homer.Width = 57;

homer.Height = 87;

homercount = 6;

jumpcount = 0;

homerflip = 0;

msdel = 0;

homerpos.X = graphics.PreferredBackBufferWidth / 2; // middle of display horizontal

homerpos.Y = graphics.PreferredBackBufferHeight - 63; // bottom of display vertical

ybase = (int)homerpos.Y;

vy = 0.0;

}

theJogger Initialize( ) Method

protected override void LoadContent()

{

spriteBatch = new SpriteBatch(GraphicsDevice);

panobkg = Content.Load<Texture2D>("pano_bkg_01");

homersprite = Content.Load<Texture2D>("homer_spritesheet");

woohoo = Content.Load<SoundEffect>("woohoo");

scream = Content.Load<SoundEffect>("scream");

doh = Content.Load<SoundEffect>("doh");

}

theJogger LoadContent( ) Method

Once the content has been associated with theJogger project it is loaded into the

predefined entities. In this case we have two graphical elements, pano_bkg_01 and the

homer_spritesheet, and three soundeffect elements, woohoo, scream, and doh.

protected override void Update(GameTime gameTime)

{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

this.Exit();

msdel += gameTime.ElapsedGameTime.Milliseconds;

keystate = Keyboard.GetState();

if (keystate.IsKeyDown(Keys.Right))

{

homer.Y = 0;

if (homerpos.X < bkg.Width / 2 - 43)

homerpos.X += 4;

else

bkg.X += 4;

if (bkg.X >= panobkg.Width - bkg.Width)

homerpos.X += 4;

if (msdel > mshomer)

{

homercount -= 1;

msdel = 0;

if (homercount < 0)

homercount = 5;

}

}

if (keystate.IsKeyDown(Keys.Left))

{

homer.Y = 87;

if (homerpos.X > bkg.Width / 2 + 43)

homerpos.X -= 4;

else

bkg.X -= 4;

if (bkg.X <= 0)

homerpos.X -= 4;

if (msdel > mshomer)

{

homercount -= 1;

msdel = 0;

if (homercount < 0)

homercount = 5;

}

}

theJogger Update( ) Method

The character will remain in the middle of the display region while running left or right as

the panoramic scene scrolls in the background. Upon reaching the left or right limit of

the background, the running character will move from the middle of the display toward

the edge. When running away from the edge the character will return to the center of

the display before the background begins moving again.

if (keystate.IsKeyDown(Keys.Up) && jumpcount == 0)

{

vy = 1.3;

jumpcount = 7;

homercount = 0;

woohoo.Play();

}

if (jumpcount > 0)

{

vy += ay;

y += vy + ay / 2.0;

homerpos.Y -= (int)y;

if (homerpos.Y > ybase)

{

homerpos.Y = ybase;

jumpcount = 0;

vy = 0.0;

y = 0.0;

}

}

if (keystate.IsKeyDown(Keys.Space) && homerflip == 0)

{

homerflip = (float)0.05;

if (rnd.Next(10)>4)

doh.Play();

else

scream.Play();

}

theJogger Jumping and Flipping Animation

A jump is initiated by pressin the up-arrow key. This shifts

the sprite blit to the jump sequence portion of the

spritesheet.

Initiating a jump also sets the vertical velocity of the

character vy to 1.3. The physics of the jump action

assumes a constant acceleration downward (gravity)

modeled by the kinematics relations:

ay = -0.1

vy = vy + ay*t

y = y + vy*t + 1/2 ay * t (we let t=1)

The spacebar causes the character to spin for a few

revolutions while the running, jumping or standing

animation continues.

homer.X = (homercount + jumpcount) * 57;

if (homerpos.X > bkg.Width - 35)

homerpos.X = bkg.Width - 35;

if (homerpos.X < 35)

homerpos.X = 35;

if (bkg.X < 0)

bkg.X = 0;

if (bkg.X > panobkg.Width - bkg.Width)

bkg.X = panobkg.Width - bkg.Width;

base.Update(gameTime);

}

running sequence

jumpcount = 0

standing jumping sequence

jumpcount = 7

left

r

igh

t

stops character at limits of

panoramic background image

Blitting the Character Sprite Sheet

protected override void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();

spriteBatch.Draw(panobkg, bkgorigin, bkg, Color.White, 0, bkgorigin, 1, 0, 1);

spriteBatch.Draw(homersprite, homerpos, homer, Color.White, homerflip, homercenter, 2, 0, 0);

spriteBatch.End();

base.Draw(gameTime);

}

theJogger Draw( ) Method

Finally, everything is ready for drawing a frame of theJogger demo. First the portion of

the background image that is visible is drawn in the graphical display and then the

character is drawing against the background.

source image

position in display

rectangle holding image to be drawn

tinting effect (White = no tinting)

sprite rotation in radians

layer depth 0 = top layer

special effects leave at 0

scale of sprite

center of rotation of sprite

Game Design

The first step in game design is having an idea for the game. This may seem like an odd

statement but it is the first step and is skipped more often than you might suppose.

Superman 64

Elf Bowling

Leisure Suit Larry: Box Office Bust

Charlie's Angels

Catfight

Desert Bus

Aquaman: Battle for Atlantis

Big Rigs: Over the Road Racing

Artwork

Once you have your game concept defined you should begin developing your artwork.

This usually begins with the background image which can help to establish the overall style

of your game.

In this example, we use Power Point to construct simple scenes and characters.

We copy these images to Paint Shop Pro for additional manipulation (any bitmap editing

program will do for this step.

For sprite sheets we are using magenta (255,0,255) as the transparency color. Magenta

rectangles can be created in Power Point and placed as to background of any objects

placed in the foregound.

A screenshot of PPT slides or simply selecting and copying these objects to a bitmap

editing program such as Paint Shop Pro will convert these collections of vectorize dobjects

into bitmap images.

If your source images have anti-aliasing features the magenta background may get

blended at the borders which will produce magenta halo around your sprites. This can be

removed by reducing the number of colors in the bitmap and then editing the palate to

force all near-magenta pixels to the transparency color.

Power Point can be used to

arrange simple shapes into a scene.

For a side scrolling game you might

want to build the background in

sections.

A few simple shapes can be copied and re-arranged

to add variety while maintaining continuity.

As segments of the background scene are ready they

are converted to bipmaps by transferring them to an

image editing application such as PaintShopPro.

Using techniques such as cut-and-paste, flip, and mirror you can tweak your scene

within the bitmap editing application.

This scene is 4096 x 480 pixels. If you are building a game for a mobile device or a

desktop computer that does not support HiDef, you will be limited to a maximum

dimension of 2048 pixels.

For now we will use a simple red ball as our character which will be placed in a

32x32 pixel sprite sheet.

PPT source

image

PNG sprite sheet

from Paint Shop Pro

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

KeyboardState kbd; // game will use keyboard interface

Rectangle bkgdisplay; // display window will be set to 640x480

Rectangle CharRect; // character rectangle will be 32x32 pixels

Vector2 CharPosDisp; // handles maxY at bottom of display issues

Vector2 CharOrig; // will be set to (16,16) which is the center of the character

Vector2 CharPos; // character position

Vector2 CharVel; // character velocity

Vector2 CharAcc; // character acceleration

Vector2 bkgorig; // adjusted to keep character in center of scene when not near extremes

Vector2 orig = new Vector2(0, 0); // upper-left corner of display region

Vector2 TextOrig = new Vector2(15, 1); // location for start of text banner for key legend

bool contact; // ensures that character is in contact with a surface before jumping

Texture2D character; // will hold character sprite sheet

Texture2D bkg; // will hold background bitmap image

SpriteFont font; // font to display key legend at top of screen

SideScrollingDemo

The variables defined for this game include the character position, velocity, and

acceleration which will be used to define the display of the character and the portion of

the backgound image for each frame.

protected override void Initialize()

{

base.Initialize();

graphics.PreferredBackBufferWidth = 640; // display is set to 640x480

graphics.PreferredBackBufferHeight = 480;

bkgdisplay = new Rectangle(0, 0, 640, 480);

graphics.IsFullScreen = true; // game will run in fullscreen mode

graphics.ApplyChanges();

CharAcc.Y = (float)-0.3; // a constant downward acceleration simulates gravity

CharRect.X = 0;

CharPos.X = 0;

CharRect.Width = 32;

CharRect.Height = 32;

CharPos.Y = 0;

CharOrig.X = 16;

CharOrig.Y = 16;

CharPosDisp.X = 16;

CharPosDisp.Y = 480 - CharPos.Y;

contact = true;

}

protected override void LoadContent()

{

spriteBatch = new SpriteBatch(GraphicsDevice);

bkg = Content.Load<Texture2D>("side_scroller_bkg");

character = Content.Load<Texture2D>("character");

font = Content.Load<SpriteFont>("SpriteFont1");

bkgorig.X = 0;

bkgorig.Y = 0;

}

Setting up the Game with the

Initialize( ) & LoadContent( ) Methods

protected override void Update(GameTime gameTime)

{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

this.Exit();

kbd = Keyboard.GetState();

if (kbd.IsKeyDown(Keys.Q))

this.Exit();

if (kbd.IsKeyDown(Keys.Right))

CharAcc.X = (float)0.4;

if (kbd.IsKeyDown(Keys.Left))

CharAcc.X = (float)-0.4;

if (kbd.IsKeyDown(Keys.Space) && contact)

{

CharVel.Y = (float)7.0;

contact = false;

}

if (kbd.IsKeyUp(Keys.Right) && kbd.IsKeyUp(Keys.Left))

CharAcc.X = (float)0.0;

CharVel.X += CharAcc.X;

CharVel.Y += CharAcc.Y;

CharPos.X += CharVel.X + (float)CharAcc.X / 2;

CharPos.Y += CharVel.Y + (float)CharAcc.Y / 2;

Driving the Character using Acceleration

While left or right arrow keys are pressed the

acceleration of the character in the X direction is

set to -0.4 or +0.4 respectively.

If character is in contact with a surface (for now

this is just the ground) pressing the SpaceBar sets

the Y velocity of the character to +7.0.

When arrow keys are up the character acceleration

is set to 0.0.

Laws of Kinematics applied here. Note for

simplicity delta-time is assumed to be unity (1.0).

if (CharPos.X < CharSize / 2)

{

CharPos.X = CharSize / 2;

CharVel.X = (float)0.0;

CharAcc.X = (float)0.0;

}

if (CharPos.X > bkg.Width - CharSize / 2)

{

CharPos.X = bkg.Width - CharSize / 2;

CharVel.X = (float)0.0;

CharAcc.X = (float)0.0;

}

if (CharPos.Y < CharSize / 2)

{

CharPos.Y = CharSize / 2;

CharVel.Y = (float)0.0;

contact = true;

}

if (CharPos.Y > bkg.Height - CharSize / 2)

CharPos.Y = bkg.Height - CharSize / 2;

CharVel.X *= (float)0.9;

bkgdisplay.X = (int)CharPos.X - graphics.PreferredBackBufferWidth/2;

if (bkgdisplay.X < 0)

bkgdisplay.X = 0;

if (bkgdisplay.X > bkg.Width - graphics.PreferredBackBufferWidth)

bkgdisplay.X = bkg.Width - graphics.PreferredBackBufferWidth;

CharPosDisp.X = CharPos.X - bkgdisplay.X;

CharPosDisp.Y = 445 - CharPos.Y;

base.Update(gameTime);

}

Character not permitted to move beyond left-side

of play region.

Character not permitted to move beyond right-side

of play region.

Character not permitted to move below bottom of

play region (ground surface).

Character not permitted to move above top of play

region.

Character X velocity slows to zero when not being

accelerated by arrow keys.

When character reaches edges of play region,

background image is blocked to keep it in the

display.

protected override void Draw(GameTime gameTime)

{

//GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();

spriteBatch.Draw(bkg, bkgorig, bkgdisplay, Color.White, 0, orig, 1, 0, 1);

spriteBatch.Draw(character, CharPosDisp, CharRect, Color.White, 0, CharOrig, 1, 0, 0);

spriteBatch.DrawString(font, "Left Arrow = move left Right Arrow = move right

Space = jump Q = quit", TextOrig, Color.CadetBlue);

spriteBatch.End();

base.Draw(gameTime);

}

Draw( ) Method

The Draw( ) method puts the background image at level 1 (back) and

the character at level 0 (front).

The Key Legend is displayed at the top of the screen and remains fixed

relative to the display as the backgroun scrolls behind it.

For now our character is a red ball. As we continue to develop or game

it will be replaced with an animated character.


Recommended