Game State and State Machines - PowerPoint PPT Presentation

1 / 44
About This Presentation
Title:

Game State and State Machines

Description:

State Machines represent the flow of control in your game. Splash. Game ... position2 = Bazooka.Position; InterpolateRocket(ref delta, LoadTime3, State.Loaded) ... – PowerPoint PPT presentation

Number of Views:24
Avg rating:3.0/5.0
Slides: 45
Provided by: cbo4
Category:
Tags: bazooka | game | machines | state

less

Transcript and Presenter's Notes

Title: Game State and State Machines


1
Game State and State Machines
  • Splash Screens
  • Menus
  • Sequencing
  • Branching
  • Text Entry

2
State Machines
  • State Machines represent the flow of control in
    your game

Config
Splash
Menu
Game

3
Big State vs. Little State
  • Big State
  • Screens
  • Splash, main screens, levels, etc.
  • Little State
  • State within a screen/level

TT
4
Big State vs. Little State
  • Big State
  • Screens
  • Splash, main screens, levels, etc.
  • Little State
  • State within a screen/level
  • Sequencing of an animation, acquisition of
    resources, etc.

5
Splash Screens, Levels, etc.
  • All you really need
  • Object-oriented Programming!
  • Superclass
  • Create a superclass for all game screens

6
GameScreen class
public class GameScreen // Game that
uses this screen private MyGame game
public MyGame Game get return game
public GameScreen(MyGame game)
this.game game
// // These are the functions game
screens need to support. //
public virtual void Initialize()
public virtual void LoadContent()
public virtual void Activate() public
virtual void Deactivate() public
virtual void Update(GameTime gameTime)
public virtual void Draw(GameTime gameTime)
public virtual void DrawSprites(GameTime
gameTime, SpriteBatch spriteBatch)
Initialization and keeping track of the game that
uses this screen.
7
Activate and Deactivate functions
public class GameScreen // Game that
uses this screen private MyGame game
public MyGame Game get return game
public GameScreen(MyGame game)
this.game game
// // These are the functions game
screens need to support. //
public virtual void Initialize()
public virtual void LoadContent()
public virtual void Activate() public
virtual void Deactivate() public
virtual void Update(GameTime gameTime)
public virtual void Draw(GameTime gameTime)
public virtual void DrawSprites(GameTime
gameTime, SpriteBatch spriteBatch)
Most of the functions are just mapping standard
functions every screen needs to know how to do.
Activate and Deactivate are new. Well call
Activate when a screen becomes active. Well
call Deactivate when a screen is taken down.
8
DrawSprites function
public class GameScreen // Game that
uses this screen private MyGame game
public MyGame Game get return game
public GameScreen(MyGame game)
this.game game
// // These are the functions game
screens need to support. //
public virtual void Initialize()
public virtual void LoadContent()
public virtual void Activate() public
virtual void Deactivate() public
virtual void Update(GameTime gameTime)
public virtual void Draw(GameTime gameTime)
public virtual void DrawSprites(GameTime
gameTime, SpriteBatch spriteBatch)
To draw 2D, we begin the sprite batch, then draw.
This function allows us to put that
functionality in one place
9
Adding a Splash to Step 4
  • Created GameScreen class
  • Created XwingGameScreen class derived from
    GameScreen
  • Moved most of the functionality to
    XwingGameScreen
  • Created a way to keep track of the current screen
  • Called current screen functions from main game
    class
  • Added SplashGameScreen class derived from
    GameScreen
  • Created means to switch in the main game class

10
The XwingGameScreen class
public class XwingGameScreen GameScreen
public XwingGameScreen(XwingG
ame game) base(game)
xwing new Xwing(Game) asteroids
new AsteroidField(Game)
public override void LoadContent()
public override void
Activate()
base.Activate() lastKeyboardState
Keyboard.GetState() lastGamePadState
GamePad.GetState(PlayerIndex.One)
public override void Update(GameTime
gameTime)
base.Update(gameTime) public
override void Draw(GameTime gameTime)
xwing.Draw(Game.Graphics, gameTime)
asteroids.Draw(Game.Graphics,
gameTime) public override
void DrawSprites(GameTime gameTime,

SpriteBatch spriteBatch)
spriteBatch.DrawString(scoreFont, scoreString,

new Vector2(10, 10), Color.White)
11
Keeping track of current screen
// Our game screens
XwingGameScreen xwingScreen null
SplashGameScreen splashScreen null //
The game screen we are playing GameScreen
screen null
public XwingGame()
xwingScreen new
XwingGameScreen(this) splashScreen
new SplashGameScreen(this) screen
splashScreen
12
Calling GameScreen functions from main game class
protected override void Initialize()
base.Initialize()
camera.Initialize() camera.Eye
new Vector3(2000, 2000, 2000)
camera.ZNear 100 camera.ZFar
1000000 xwingScreen.Initialize()
splashScreen.Initialize()
protected override void LoadContent()
xwingScreen.LoadCont
ent() splashScreen.LoadContent()
screen.Activate()

protected override void Update(GameTime
gameTime)
screen.Update(gameTime)
camera.Update(gameTime)
base.Update(gameTime)
protected override void Draw(GameTime gameTime)
graphics.GraphicsDevice.Clear(
Color.Black) screen.Draw(gameTime)
spriteBatch.Begin(SpriteBlendMode.Alp
haBlend,
SpriteSortMode.BackToFront,
SaveStateMode.SaveStat
e) screen.DrawSprites(gameTime,
spriteBatch) spriteBatch.End()
base.Draw(gameTime)
13
SplashGameScreen
public class SplashGameScreen GameScreen
private Texture2D splash
private double time public
SplashGameScreen(XwingGame game) base(game)
public override void
LoadContent() splash
Game.Content.LoadltTexture2Dgt("xwingsplash")
public override void Activate()
base.Activate()
time 0
14
SplashGameScreen
public override void Update(Microsoft.Xna.
Framework.GameTime gameTime)
base.Update(gameTime) time
gameTime.ElapsedGameTime.TotalSeconds
if (time gt 3)
Game.SetScreen(XwingGame.GameScreens.Xwing)
public override void
DrawSprites(GameTime gameTime, SpriteBatch
spriteBatch) int wid
Game.Graphics.GraphicsDevice.Viewport.Width
int hit Game.Graphics.GraphicsDevice.View
port.Height int imgWid
(int)((16.0 / 9.0) hit) int
tooWide imgWid - wid Rectangle
rect new Rectangle(-tooWide / 2, 0, imgWid,
hit) spriteBatch.Draw(splash, rect,
Color.White)
15
Means to switch screens in main game class
public enum GameScreens Splash, Xwing
public void SetScreen(GameScreens
newScreen)
screen.Deactivate() switch
(newScreen) case
GameScreens.Splash screen
splashScreen break
case GameScreens.Xwing
screen xwingScreen
break
screen.Activate()
Game.SetScreen(XwingGame.GameScreens.Xwing)
This is how it is called
16
Important Properties
Youll need to be able to access some things that
would have been just member variables before.
The camera class is a good example. Create
public properties for this purpose.
public Camera Camera get return
camera public SoundBank SoundBank
get return soundBank public
GraphicsDeviceManager Graphics get return
graphics
In my main game class (XwingGame)
17
Class Designer
18
A few words about splash screen images
  • Create them with a 169 aspect ratio (1067 x 600
    for example)
  • Ensure they work okay at a 43 aspect ratio (pad
    on left and right)

19
And resize to a power of two in each dimension
Well stretch it back out when we draw it.
  • 1066x800 original
  • 1024x512 resized
  • Graphics systems require images to be powers of 2
    in each dimension!

20
Drawing our splash image
This code works for 169 or 43 aspect ratios.
Will work for any aspect ratio by making the
image fill top to bottom.
public override void DrawSprites(GameTime
gameTime, SpriteBatch spriteBatch)
int wid Game.Graphics.GraphicsDevice.View
port.Width int hit
Game.Graphics.GraphicsDevice.Viewport.Height
int imgWid (int)((16.0 / 9.0) hit)
int tooWide imgWid - wid
Rectangle rect new Rectangle(-tooWide / 2, 0,
imgWid, hit) spriteBatch.Draw(splash,
rect, Color.White)
Notice No reference to how big the image is!
21
How do we do this?
  • This is called a state machine
  • or Finite State Machines (FSM)
  • Our state is our current screen.
  • Transitions between states are implemented by
    calls to change the game screen.

Config
Splash
Menu
Game

22
Little State state within a page
Ladder is on ground, rising, at window, then
dropping.
23
State Diagram
Visio does these very nicely
What do we need to keep track of?
TT
24
State Diagram
private enum States OnGround, Lifting,
OnSill, Dropping private States state
States.OnGround private float
stateTime 0
25
public override void Update(GameTime
gameTime) float t 0
stateTime (float)gameTime.ElapsedGameTim
e.TotalSeconds switch (state)
case States.OnGround
t 0 if
(stateTime gt 2.0f)
state States.Lifting
stateTime 0
break
case States.Lifting t
stateTime / 4.0f // Time to lift
if (t gt 1)
state States.OnSill
stateTime 0
t 1
break
case States.OnSill
t 1 if (stateTime gt
2.0f)
state States.Dropping
stateTime 0
break case
States.Dropping t 1 -
stateTime / 4.0f if (t lt
0)
state States.OnGround
stateTime 0 t 0
break
ladderDir
Slerp(originalDir, finalDir, t)
ladderUp Slerp(originalUp, finalUp, t)
UpdateOrientation()
26
The basics
  • State is indicated by
  • enum value, time within state

case States.Lifting
t stateTime / 4.0f // Time to
lift if (t gt 1)
state
States.OnSill stateTime
0 t 1
break
  • Transitions are implemented by
  • Time expiration

27
Other possibilities
  • State might include
  • Remaining ammunition, power
  • Transitions can be due to
  • End of an animation
  • Key or button press
  • Collisions

28
A somewhat more complicated example
TT
29
The States
// // State Management
// private enum State Start, BoxClosed,
BoxOpening, ReadyToLoad,
Loading1, Loading2, Loading3, Loaded,
Firing, Empty, BoxClosing
private State state private double
stateTime // Amount of remaining
ammunition private int ammoRemaining 2
30
Time-safe state loops
double deltaTotal gameTime.ElapsedGam
eTime.TotalSeconds while
(deltaTotal gt 0) //
Elapsed time we'll use double
delta deltaTotal switch
(state)
case State.Start
boxClip.Rewind()
boxClip.Speed 0 state
State.BoxClosed delta
0 break
case State.BoxOpening
if (boxClip.Time lt BoxOpenTime)
if
(delta gt BoxOpenTime - boxClip.Time)
delta BoxOpenTime -
boxClip.Time
else
// Open is complete,
switch to ReadyToLoad
state State.ReadyToLoad
boxClip.Speed 0
delta 0
break

UpdateAnimations(delta)
deltaTotal - delta
A state may not consume all of the time available
to it. If not, we loop back to the next state
with the remaining time.
31
Example
Three 1 second loadings should take 3 seconds.
But, what if each frame was 0.3 seconds? Suppose
I just keep track until time has expired?
32
Frame times
Three 1 second loading should take 3 seconds.
But, what if each frame was 0.3 seconds?
Instead, it took 3.6 seconds. Why is that? Does
this matter?
33
Example
Admittedly a contrived example, but suppose each
frame is 0.016 sec, we would accumulate an
average of 0.008 sec per state. Would that ever
matter?
34
public override void Update(GameTime
gameTime) // Total amount
of elapsed time. double delta
gameTime.ElapsedGameTime.TotalSeconds
switch (state)
case State.Loading1
position2 rocket.Position new Vector3(0, 60,
0) InterpolateRocket(ref
delta, LoadTime1, State.Loading2)
break case
State.Loading2 position2
Bazooka.Position Bazooka.Transform.Forward
90 InterpolateRocket(ref
delta, LoadTime2, State.Loading3)
break case
State.Loading3 position2
Bazooka.Position
InterpolateRocket(ref delta, LoadTime3,
State.Loaded) break
//...
UpdateAnimations(delta)
This code is broken, dont use as is!
private void InterpolateRocket(ref double
delta,
double loadTime, State
nextState) if (stateTime lt
loadTime) stateTime
delta float t
(float)(stateTime / loadTime)
rocket.Position Vector3.Lerp(position1,
position2, t) else
// Loading phase is
complete state nextState
stateTime 0
position1 rocketLoading.Position

TT
35
public override void Update(GameTime
gameTime) // Total amount
of elapsed time. double deltaTotal
gameTime.ElapsedGameTime.TotalSeconds
while (deltaTotal gt 0)
// Elapsed time we'll use
double delta deltaTotal
switch (state)
case State.Loading1
position2 rocket.Position new Vector3(0, 60,
0) InterpolateRocket(ref
delta, LoadTime1, State.Loading2)
break case
State.Loading2 position2
Bazooka.Position Bazooka.Transform.Forward
90 InterpolateRocket(ref
delta, LoadTime2, State.Loading3)
break case
State.Loading3 position2
Bazooka.Position
InterpolateRocket(ref delta, LoadTime3,
State.Loaded) break
UpdateAnimations(de
lta) deltaTotal - delta

This code is much better.
private void InterpolateRocket(ref double delta,

double loadTime, State nextState)
if (stateTime lt loadTime)
// Still loading
if (delta gt (loadTime - stateTime))
delta loadTime - stateTime
stateTime delta float t
(float)(stateTime / loadTime)
rocketLoading.Position Vector3.Lerp(position1,
position2, t) else
// Loading phase is
complete state nextState
stateTime 0
position1 rocketLoading.Position
orientation1 rocketLoading.Orientation

TT
36
Keypress state transitions
switch (state)
case State.BoxClosed
if (e.KeyCode Keys.O)
state State.BoxOpening
boxClip.Speed 1
break
case State.ReadyToLoad
if (e.KeyCode Keys.L)
state State.Loading1
rocketLoading ammoRemaining
2 ? Rocket1 Rocket2
position1 rocketLoading.Position
orientation1 rocketLoading.Orientation
position2
rocketLoading.Position new Vector3(0, 60, 0)
orientation2
rocketLoading.Orientation
stateTime 0
break
37
Animation-based State Transitions
case State.BoxOpening
if (boxClip.Time lt BoxOpenTime)

// See how much we can consume
if (delta gt BoxOpenTime - boxClip.Time)
delta
BoxOpenTime - boxClip.Time
else
// Open is
complete, switch to ReadyToLoad
state State.ReadyToLoad
boxClip.Speed 0
delta 0
break
case State.BoxClosing
if (boxClip.Time lt
boxClip.Duration)
// See how much we can
consume if (delta gt
boxClip.Duration - boxClip.Time)
delta boxClip.Duration -
boxClip.Time
else
// Open is complete,
switch to ReadyToLoad
state State.Start
boxClip.Speed 0
delta 0
break
38
The rocket interpolation
private void InterpolateRocket(ref double
delta, double loadTime, State nextState)
if (stateTime lt loadTime)
// Still loading
if (delta gt (loadTime - stateTime))
delta loadTime - stateTime
stateTime delta float t
(float)(stateTime / loadTime)
rocketLoading.Position Vector3.Lerp(position1,
position2, t) rocketLoading.Orien
tation Quaternion.Slerp(orientation1,
orientation2, t) else
// Loading phase is
complete state nextState
stateTime 0
position1 rocketLoading.Position
orientation1 rocketLoading.Orientation

case State.Loading2
// Ending position and orientation
position2
Bazooka.Position Bazooka.Transform.Forward
90 orientation2
Bazooka.Orientation
InterpolateRocket(ref delta, LoadTime2,
State.Loading3) break
case State.Loading3
position2 Bazooka.Position
orientation2
Bazooka.Orientation
InterpolateRocket(ref delta, LoadTime3,
State.Loaded) break
39
Conditional State Transition
case State.Firing
rocketFiring rocketLoading
ammoRemaining--
if (ammoRemaining gt 0)
state
State.ReadyToLoad
else
state
State.Empty
break
40
Another type of state
How would you enter text?
41
Another type of state
Text is complicated in XNA due to the keyboard
model they use. You have to determine a key has
been pressed since the last time update. This
may actually miss some keys. Some have hooked
the Windows keyboard event.
42
XNA Keyboard Input Example
if (state States.NameEntry)
Keys keys
keyboardState.GetPressedKeys()
for (int i 0 i lt keys.Length i)
if (keysi lt Keys.A
keysi gt Keys.Z)
continue if
(lastKeyboardState.IsKeyUp(keysi))
// We have a
keypress char key
if (keyboardState.IsKeyDown(Keys.
LeftShift) keyboardState.IsKeyDown(Keys.RightSh
ift))
key Convert.ToChar(keysi)
else

key (char)(Convert.ToChar(keysi) - 'A'
'a')
name key

43
(No Transcript)
44
Displaying the name entry screen.
public override void DrawSprites(GraphicsD
evice graphics, SpriteBatch spriteBatch, GameTime
gameTime) int wid
graphics.Viewport.Width int hit
graphics.Viewport.Height
int imgWid (int)((16.0 / 9.0) hit)
int tooWide imgWid - wid
Rectangle rect new Rectangle(-tooWide / 2, 0,
imgWid, hit) spriteBatch.Draw(window,
rect, Color.White) int x
(int)(422.0 / 1066.0 imgWid) int y
(int)(497.0 / 600.0 hit)
spriteBatch.DrawString(font, name, new Vector2(x
- tooWide / 2, y), Color.Red)
Just like drawing a splash screen
Displays the name
Write a Comment
User Comments (0)
About PowerShow.com