Practice 1: State Design Pattern

Using State Pattern in Game Development

Description of the Game:

  • Game has one avatar
  • The avatar can be in one state at a time.
  • There are fixed set of states including standing, sitting, walking and running.
  • Up arrow, Down arrow, left arrow, right arrow and shift keys will be used in the game
  • The following state diagram gives the state transition based on the key events. Example scenarios and requirements: o If the avatar is in standing state and user hits down arrow key from the keyboard, avatar goes to sitting state.
    • If the avatar is in standing state and user hits up arrow key from the keyboard, avatar stays in the same state, and it makes "beep" sound to indicate an invalid operation.
    • If the avatar is in walking state, and player hits right arrow key, it'll stay in the same state and itll take 10 steps at a time (in case of running, itll take 30 steps)

State Diagram: see image.

PlantUml Code:

@startuml scale
500 width [*] -
> Standing
Standing --> Standing : up
Standing --> Sitting : down
Sitting --> Standing : up
Sitting --> Sitting : right
Sitting --> Sitting :left
Standing --> Walking : right
Standing --> Walking : left
Walking --> Standing : down
Walking --> Walking : right+10
Walking --> Walking : left-10
Walking --> Running : shift
Running --> Walking : shift
Running --> Running : right+30
Running --> Running : left+30
Running --> Running : up
Running --> Running : down
Walking --> Walking : up
@enduml

Implementation

public class GameContext extends JFrame implements KeyListener{
private
private ();
private int x = 0; private
GameState gameState;
public GameContext() { setState(new
StandingState());
stateLbl.setFont(new Font("Arial", Font.BOLD, 40));
xLbl.setFont(new Font("Arial", Font.BOLD, 40));
setLayout(new GridLayout(2,1));
add(xLbl);
add(stateLbl);
addKeyListener(this);
setPreferredSize(new Dimension(400,200));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
pack();
setLocationRelativeTo(null);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
xLbl.setText("x:"+x);
}
public void setState(GameState gameState) {
this.gameState = gameState;
stateLbl.setText(gameState.getName().toUpperCase());
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_UP) {
gameState.up(this);
}else if (e.getKeyCode()==KeyEvent.VK_DOWN) {
gameState.down(this);
}else if (e.getKeyCode()==KeyEvent.VK_LEFT) {
gameState.left(this);
}else if (e.getKeyCode()==KeyEvent.VK_RIGHT) {
gameState.right(this);
}else if (e.getKeyCode()==KeyEvent.VK_SHIFT) {
gameState.shift(this);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args) {
GameContext game = new GameContext();
}
}

public interface GameState {
public void up(GameContext context);
public void down(GameContext context);
public void left(GameContext context);
public void right(GameContext context);
public void shift(GameContext context);
String getName();
}

public class RunningState implements GameState {
public void up(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void down(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void left(GameContext context) {
context.setX(context.getX()-30);
}
public void right(GameContext context) {
context.setX(context.getX()+30);
}

public void shift(GameContext context) {
context.setState(new WalkingState());
}
@Override
public String getName() {
return "running";
}

public class SittingState implements GameState{
public void up(GameContext context) {
context.setState(new StandingState());
}
public void down(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void left(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void right(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void shift(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
@Override
public String getName() {
return "sitting";
}
}

public class StandingState implements GameState{
public void up(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void down(GameContext context) {
context.setState(new SittingState());
}
public void left(GameContext context) {
context.setState(new WalkingState());
}
public void right(GameContext context) {
context.setState(new WalkingState());
}
public void shift(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
@Override
public String getName() {
return "standing";
}
}

public class WalkingState implements GameState {
public void up(GameContext context) {
Toolkit.getDefaultToolkit().beep();
}
public void down(GameContext context) {
context.setState(new StandingState());
}
public void left(GameContext context) {
context.setX(context.getX()-10);
}
public void right(GameContext context) {
context.setX(context.getX()+10);
}
public void shift(GameContext context) {
context.setState(new RunningState());
}
@Override
public String getName() {
return "walking";
}
}

Initial State: see image.

Right arrow pressed four times: see image.

Class Diagram: see image.

PlantUML Code:

@startuml
GameContext o-right- GameState
GameContext .up.> KeyListener
StandingState .up.> GameState
SittingState .up.> GameState
WalkingState .up.> GameState
RunningState .up.> GameState
interface KeyListener{
void keyPressed(KeyEvent)
void keyReleased(KeyEvent)
void keyTyped(KeyEvent)
} class GameContext{
GameState state void
setState(GameState)
} interface GameState{
void up(GameContext)
void down(GameContext)
void left(GameContext)
void right(GameContext)
void shift(GameContext)
String getName()
} class
StandingState{ }
class SittingState{
} class
WalkingState{ }
class RunningState{
}
@enduml

Assignment

In this assignment, you are asked to modify "Programming Practice 1" to meet the following requirements.

Coding Requirements

  • Apply State Pattern
  • Apply Model-View-Controller design pattern

Game Requirements

  • Game has one avatar
  • The avatar can be in one state at a time.
  • There are fixed set of states including standing, sitting, walking, running, crawling and crabwalking.
  • Up arrow, Down arrow, left arrow, right arrow and shift keys will be used in the game
  • The key events and corresponding state updates are summarized in the following table.

Key/States Standing Sitting Walking Running CrabWalking Crawling
Up Jumping Standing NA NA NA Sitting
Down Sitting Crawling Standing NA Sitting NA
Left Walking CrabWalking Walking (-10) Running (-30) CrabWalking (-5) Crawling (-2)
Right Walking CrabWalking Walking (+10) Running (+30) CrabWalking (+5) Crawling (+2)
Shift NA NA Running Walking NA NA

  • Create two different views for the game: AnimatedView and TextView. Sample runs for these two views are given below.

Sample Run: see image.

Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.