Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am making simple game in java using Slick 2d. My question is how many ways of passing information between states are available in Slick 2d. I am having a Hero class that holds all the hero stats and carry them between states using Singleton pattern- aka creating a single instance of the object and accessible from everywhere . Are there any possible solutions and workarounds ? Some XML-alike solutions ? Is there DB option ? Is it worth the effort ?

[Edit] Put it simple I want instance of my class hero to be accessible from every state. For example my hero goes to the market and buys some armor. That should change his stas in all states. My question was if there is another way to do that like storing the hero stats not in a class but a XML or data base.

share|improve this question

2 Answers 2

up vote 4 down vote accepted

I have elaborated on my comment suggestion, but the answer to your questions are:

Yes, there are alternatives to a singleton. I present one shortly.

Whether you want to serialize your information to xml, a database, yaml, or whatever is up to you. I do not recommend serializing to your chosen method each time your character drinks a potion or whatever, but having a method to serialize out your game data is a good idea. Slick does not provide an api for writing to XML, just reading from it. YAML is a good alternative. SQLite might also be an alternative.


The solution I use:

Here is an example of how to share game data between states. This is an edited version of code I use as the basis of all of my own slick projects.

At the root, I have an abstract class ClientBase (client in this context means game client)

public abstract class ClientBase<T> extends StateBasedGame {

    private T gameData = null;

    public ClientBase(String name, T theGameData) {
        super(name);
        setGameData(theGameData);
    }

    private void setGameData(T theGameData) {
        gameData = theGameData;
    }

    public T getGameData(){
        return gameData;
    }

}

And I have a GameStateBase class to encapsulate individuals states:

public abstract class GameStateBase<T, U extends StateBase> implements GameState {
    private U state;
    private ClientBase<T> client;

    public GameStateBase(ClientBase<T> theClient,U theState){
        setClient(theClient);
    }

    private void setState(U theState) {
        state = theState;
    }

    public U getState(){
        return state;
    }

    private void setClient(ClientBase<T> theClient) {
        client = theClient;
    }

    public ClientBase<T> getClient(){
        return client;
    }

    @Override
    public int getID() {
        return getState().getValue();
    }

    @Override
    public boolean isAcceptingInput() {
        return getClient().getCurrentState()==this;
    }

    /* also contains stubs for other GameState methods */
}

(to make the enum based method a little clearer, let me include StateBase here)

public interface StateBase {
    int getValue();
}

And that concludes a simplification of the plumbing....

Now, to actually USE this stuff:

Here's a simple example of a States class, which implements the StatesBase interface.

public enum States implements StateBase{
    SPLASH(0),
    MAIN_MENU(1);
    private int value;
    States(int theValue){
        value = theValue;
    }
    @Override
    public int getValue() {
        return value;
    }

}

And a concrete class for my client:

public class Client extends ClientBase<GameData> {

    public Client(String name) {
        super(name, new GameData());
    }

    @Override
    public void initStatesList(GameContainer arg0) throws SlickException {
        addState(new SplashState(this, States.SPLASH));
        addState(new MainMenuState(this,States.MAIN_MENU));
        /* other states go here*/
    }

}

And finally one of the game states itself:

public class SplashState extends GameStateBase<GameData,States>{

    private static final int ELAPSED_INITIAL = 0;
    private static final int ELAPSED_FINAL = 5000;
    private int elapsed;

    public SplashState(ClientBase<GameData> theClient, States theState) {
        super(theClient, theState);
    }

    @Override
    public void keyPressed(int theKey, char theCharacter) {
        if(theKey==Input.KEY_ESCAPE){
            elapsed = ELAPSED_FINAL;
        }
    }

    @Override
    protected void enter()
            throws SlickException {
        elapsed = ELAPSED_INITIAL;
    }

    @Override
    protected void render(Graphics theGraphics)
            throws SlickException {
        theGraphics.clear();
        theGraphics.drawString("SPLASH", 0.0f, 0.0f);
    }

    @Override
    protected void update(int theDelta)
            throws SlickException {
        elapsed += theDelta;
        if(elapsed>=ELAPSED_FINAL){
            getClient().enterState(States.MAIN_MENU.getValue());
        }
    }
}

Anywhere within a game state that descends from GameStateBase, a call of:

GameData theGameData = getClient().getGameData();

Will return your shared data.

And what of the class GameData itself?

That's totally up to you. That's why it uses generics.

The pros of this method:

  • All of the states have access to the game data
  • You aren't forced to use a static singleton
  • GameData works as an access layer to whatever storage medium you choose. If the backend is a database or xml file or whatever, GameData talks to it, and the game states don't have to care how it is implemented.

The cons of this method:

  • Since any state has full access to the game data, any state can change the data. This might not seem like a big deal, but there are indeed plenty of states, like the Splash state, which does not care in the slightest about much of any thing in the game.
share|improve this answer

By default there is no possibility to exchange data between states. The reason for this is that the concept of the states is to isolate the the current state your game is in and the data that is needed for each state.

You either need a external class that holds the data you require and you pass the instance of this class to the states that require the data during the construction of the states. Or you use a singleton pattern.

But that should be done rarely as usually every state holds is own data and there is not much data exchanging needed. Any other situation points to a flaw in the design of the games logic and the usage of the game states of Slick.

If you give a more detailed description of your game and what you are doing with the states, we can provide better help for your specific problem. From the little I read there it sounds to me like the problem is the usage of the game states. But at this point I could be wrong.

share|improve this answer
    
I've yet to see a game in which very many of the states are completely isolated from the other states data-wise, if only for the media manager that loads images and sounds. Having said that, I created an abstract class GameStateBase<T,U> that implements GameState where T is the type of data that is shared between all states, and U is an enum that deals with the state name itself (I don't like having to use ints for state ids). These are managed by an abstract ClientBase<T> which manages the shared data and extends StateBasedGame –  PlayDeezGames Jun 13 '12 at 20:31
    
So the option would be to create some sort of storage class for the data that is exchanged and hand that over to the states when you construct them. –  Nitram Jun 13 '12 at 23:18
    
I have edit my question . @PlayDeezGames this sounds like interesting option would you mind elaborate more - why have desiced to do so , what are pros and cons. –  speedyGonzales Jun 14 '12 at 6:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.