Best way to organize Screen states in the code

Hi folks,

Most of the simplest examples of Java2D games have something like:


public void run() {
       while (running) {
             gameUpdate();
             gameRender();
             paintScreen();
       }
}

In each method you have what you need to update, render objects and paint screen. This is very simple and nice when you are showing how to make a game and only have one screen. What about when you have more screens? (menu, Single player mode, multiplayermode, options, etc).
What is the best way to organize this so that each one of this methods knows what to do depending on which part of the game you are?

My initial thought was to create a State class. Each different part of the game would extend from state and then you would have something like this:


public void run() {
       while (running) {
             state.gameUpdate();
             state.gameRender();
             paintScreen();
       }
}

Of course this would mean that the state variable would change inside update sometimes so this might create some problems.

What do you guys think of this? In your experience what is the best way to control the flow of these things?

Thanks

well in most games everything is actively rendered. That means menus are rendered through gameRender() also. So first example stays the same, only you would have more stuff in your gameRender() to check what to render (game or menu for example).

BUT if you are using swing for your game menu you can’t active render swing without using hacky stuff which are unreliable and not tested (see my and CommanderKeith’s discussion over this in java2d subforum). I use swing for game menu, and what I do is put swing menu in one panel and game animation in another. When I want to draw menu I show menu panel and hide game panel, and when I want to draw game I show game panel and hide menu panel. I’ve found CardLayout to be excellent for this, as you can have only one component visible at a time and you can call .show(“component name”) to simply display that component when you want to switch to, let’s say, game menu.

If you are using OpenGL have a look at FengGUI.

I’m using only Java2D and everything is rendered in a JPanel.

I think you didnt understood very well what I wanted. My problem here is that I don’t want to have a gigantic gameUpdate() and gameRender() methods. I want to separate each part of the logic to include only what each part of the game needs to do. That’s why I talked about the State classes and have one for each part of the game, where each one would have their own gameUpdate() and gameRender() and then in my main run() method I would call the one I need at the moment.

Example:


public abstract class State;
public class MenuState extends State;
public class OptionsState extends State;
public class SinglePlayerState extends State;
public class HighScoreState extends State;
...

I just wanted to know if this is a good solution or if there is a better one and more traditional one.

Your state class idea is a good one. I use this interface (though in this case it’s not Java 2D):


 public interface GameState extends InputListener { 
    /** 
     * Get the ID of this state 
     *  
     * @return The game unique ID of this state 
     */ 
    public int getID(); 
     
    /** 
     * Initialise the state. It should load any resources it needs at this stage 
     *  
     * @param container The container holding the game 
     * @param game The game holding this state 
     * @throws SlickException Indicates a failure to initialise a resource for this state 
     */ 
    public void init(GameContainer container, StateBasedGame game) throws SlickException; 
     
    /** 
     * Render this state to the game's graphics context 
     *  
     * @param container The container holding the game 
     * @param game The game holding this state 
     * @param g The graphics context to render to 
     * @throws SlickException Indicates a failure to render an artifact 
     */ 
    public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException; 
     
    /** 
     * Update the state's logic based on the amount of time thats passed 
     *  
     * @param container The container holding the game 
     * @param game The game holding this state 
     * @param delta The amount of time thats passed in millisecond since last update 
     * @throws SlickException Indicates an internal error that will be reported through the 
     * standard framework mechanism 
     */ 
    public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException ; 
     
    /** 
     * Notification that we've entered this game state 
     *  
     * @param container The container holding the game 
     * @param game The game holding this state 
     * @throws SlickException Indicates an internal error that will be reported through the 
     * standard framework mechanism 
     */ 
    public void enter(GameContainer container, StateBasedGame game) throws SlickException; 
 
    /** 
     * Notification that we're leaving this game state 
     *  
     * @param container The container holding the game 
     * @param game The game holding this state 
     * @throws SlickException Indicates an internal error that will be reported through the 
     * standard framework mechanism 
     */ 
    public void leave(GameContainer container, StateBasedGame game) throws SlickException; 
} 

The enter and leave methods gives the state a chance to do something as we start using and stop using them as the actual game state.

Kev

What I do in my games :

  • abstracted away a ‘game flow controler’ (singleton) whose role is to manage game states

  • each state then has s set of methods

    • init() called once
  • start() called when the game enters this state

  • update(double deltaTime) invoked many has long as no state change is required

  • end () at the end of the state

  • destroy() at the end of the game, or the end of a game phase (when you are sure you will never need this state again)

changing of gamestates is just a matter of invoking ‘GameFlowControler.instance().setNextState(nextState)’ in the update() method at appropriate times.

It’s very simple to implement and powerful enough for most games (although it doesn’t support game logic multi threading).

If you add an abstraction of rendering (like a scenegraph), you can even use multiple states working with the same display (like : showing a ‘game over effect’ while the game gackground is still display’). which is good as it keeps your classes small and dedicated.

Lilian :slight_smile:

public abstract class State;
public class MenuState extends State;
public class OptionsState extends State;
public class SinglePlayerState extends State;
public class HighScoreState extends State;
...

that’s a good idea. also, you might wanna make sure you do not mix drawing with model classes (MVC pattern).

Thanks for the feedback guys.