Slick Forums

Discuss the Slick 2D Library
It is currently Tue May 21, 2013 12:55 am

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Thu Jun 28, 2012 9:27 am 
Offline

Joined: Thu Jun 28, 2012 9:13 am
Posts: 2
Hi, I just have a (hopefully) quick question.

My game was crashing because I was trying to draw the background while it was null. The draw() was in the render function, but the background variable was supposed to have already been set in the init() function, which it was not.

I solved the problem by forcibly calling init() with
Code:
this.getState(MAINMENUSTATE).init(gc, this);

but my question is why do I need to do this? I thought that the init() functions of game states should be automatically called as soon as they are added to the game states list?
Here's the code of my initStatesList() in the main file:
Code:
@Override
   public void initStatesList(GameContainer gc) throws SlickException {
      
      PlayerInfo.createNewCurrentPlayerInfo();
      
      this.addState(new MainMenuGameState());
      this.getState(MAINMENUSTATE).init(gc, this);
      
      GameplayState state = new GameplayState();
      
      state.setLevelFile("data/level1.lvl");
      
      this.addState(state);
   }


In a previous project I was working with, this problem never occurred, the states were initialized as soon as they were added to the state list, and from what I can tell, there is no difference between that project and this one.

BTW, this is from spiegel's 3rd tutorial


Top
 Profile  
 
PostPosted: Fri Jun 29, 2012 3:43 am 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1467
Do the StateBasedTests (in the "tests" package) work for you? I'd guess there is something wrong with your code.


Top
 Profile  
 
PostPosted: Fri Jun 29, 2012 9:06 am 
Offline

Joined: Thu Jun 28, 2012 9:13 am
Posts: 2
They seem to work fine. I had the main class extend StateBasedTest and had 3 other classes extend TestState1, 2 and 3, added the 3 states to the StateBasedTest, and the window that came up had a state with only text saying "State 1" and "Numbers 1 - 3 will change states".
State 2 had "State 2" and a rotating logo that said "Slick"
State 3 had "State 3" and a menu.
The only problem I found was that there seems to be no transition from State1 to State 2.
When it switches states, you can still see everything from State 1 being overlapped by State 2 for about 2-3 seconds before it disappears and the logo starts spinning. Is this a different kind of transition, or just a bug? lol

In any case, I don't know what I possibly could have done to actually disable the init() call from being made to a state. I mean... the init() method should be called as soon as a state is added to the list, without having to make an explicit call, shouldn't it?

Is there any line of code off the top of your head that disables automatic initialization?

Here's the code for the main class and the MainMenuGameState class:

Code:
public class SlickOutGame extends StateBasedGame {

   public static final int MAINMENUSTATE         = 0;
   public static final int GAMEPLAYSTATE         = 1;
   public static final int LEVELSELECTSTATE      = 2;
   
   public SlickOutGame() {
      super("SlickOut");
   }
   
   @Override
   public void initStatesList(GameContainer gc) throws SlickException {
      
      GameInfo.createNewGameInfo();
      
      this.addState(new MainMenuGameState());
      //this.getState(MAINMENUSTATE).init(gc, this);
      
      GameplayState state = new GameplayState();
      
      this.addState(state);
      
      this.addState(new LevelSelector());
   }
   
   public static void main(String[] args) throws SlickException {
      
      AppGameContainer app = new AppGameContainer(new SlickOutGame());
      
      app.setDisplayMode(800, 600, false);
      app.start();
   }

}


Code:
public class MainMenuGameState extends BasicGameState implements MouseListener {

   private Image background;
   private Image selector;
   private int selection;
   private int optionSelected;
   private int topScore;
   
   @Override
   public int getID() {
      return 0;
   }
   
   @Override
   public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
      background = new Image("data/mainmenu.jpg");
      selector = new Image("data/selector.png");
   }
   
   @Override
   public void enter(GameContainer gc, StateBasedGame sbg) throws SlickException {
      selection = -1;
      optionSelected = selection;
      
      if ( GameInfo.getCurrentGameInfo() != null) {
         topScore = (topScore > GameInfo.getCurrentGameInfo().getPlayerInfo().getScore() ) ? topScore : GameInfo.getCurrentGameInfo().getPlayerInfo().getScore();
      }
   }
   
   @Override
   public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
      background.draw();
      
      if(selection == 1) {
         selector.draw(158, 310);
         selector.draw(694, 310);
         
         GameInfo.createNewGameInfo();
      }else if(selection == 2) {
         selector.draw(158, 474);
         selector.draw(694, 474);
      }
      
      // TODO: Log this
      g.drawString("TOPSCORE: " + topScore, 10, 10);
   }
   
   @Override
   public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
      if(optionSelected == 1) {
         sbg.enterState(2);
      }else if(optionSelected == 2) {
         System.exit(0);
      }
   }
   
   public void mouseMoved(int oldx, int oldy, int newX, int newY) {
      if(newX > 228 && newX < 702) {
         // start game
         if (newY > 308 && newY < 389) {
            selection = 1;
         // exit game
         }else if (newY > 475 && newY < 544) {
            selection = 2;
         }else {
            selection = -1;
         }
      }
   }
   
   public void mouseClicked(int button, int x, int y, int clickCount) {
      optionSelected = selection;
   }
}


Top
 Profile  
 
PostPosted: Sun Jul 01, 2012 10:23 am 
Offline

Joined: Mon Jun 18, 2012 10:31 am
Posts: 7
To be honest, I didn't try your code, nor my modifications to it, but the approach which works for me without problems is:

1) Put all the addState(new State(StateID)) calls in your StateBasedGame's constructor
2) Call enterState(StateID) after those calls
3) From the InitStateList() method, call init() on each state

So, you'd get something like this
Code:
public class SlickOutGame extends StateBasedGame {

   public static final int MAINMENUSTATE         = 0;
   public static final int GAMEPLAYSTATE         = 1;
   public static final int LEVELSELECTSTATE      = 2;
   
   public SlickOutGame() {
      super("SlickOut");
   
      this.addState(new MainMenuState(MAINMENUSTATE));       
      this.addState(new GameplayState(GAMEPLAYSTATE));
      this.addState(new LevelSelectState(LEVELSELECTSTATE));

      this.enterState(MAINMENUSTATE);
   }

   public void initStatesList(GameContainer gc) throws SlickException {
      this.getState(MAINMENUSTATE).init(gc, this);
      this.getState(GAMEPLAYSTATE).init(gc, this);
      this.getState(LEVELSELECTSTATE).init(gc, this);
   }

   public static void main(String[] args) throws SlickException {
      AppGameContainer app = new AppGameContainer(new SlickOutGame());
     
      app.setDisplayMode(800, 600, false);
      app.start();
   }



Also, your MainMenuGameState does not implement the StateID properly; i suppose it comes from Eclipse's automatic creation of constructors from superclass (and/or some other Eclipse's "magic"). You need to make the getID() method return the correct ID, not 0; and set it through constructor, like this:

Code:
public class MainMenuGameState extends BasicGameState implements MouseListener{

   private int stateID = -1;

   public GameState(int stateID){
      this.stateID = stateID;
   }
   
   @Override
   final public int getID(){
      return this.stateID;
   }

   /* other stuff */
}


As to whys, shoulds and shouldn'ts I'm afraid I don't know enough about slick yet to answer that (and I do have my own questions on some things), but this should work.


Top
 Profile  
 
PostPosted: Tue Jul 03, 2012 3:50 am 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1467
Don't call init() manually as it will result in your state being initialized twice. StateBasedGame will init your states for you after calling initStatesList. Also, the first state you add will be "entered" after all states are initialized. So your code should look like this:

Code:
public MyStateGame extends StateBasedGame {
    public MyStateGame() {
        super("test");
    }

   public void initStatesList(GameContainer gc) throws SlickException {
      this.addState(new MainMenuState(MAINMENUSTATE));       
      this.addState(new GameplayState(GAMEPLAYSTATE));
      this.addState(new LevelSelectState(LEVELSELECTSTATE));
   }
}


isokcevic's code was probably taken from an old tutorial which was wrong about Slick's game state usage.

To the OP, I don't have time now to look through your code. If the tests work, then your code must have an issue. :) The transition issue in the state tests seems to be a bug with the cross fading transition, but unrelated to your problem of states not initializing.


Top
 Profile  
 
PostPosted: Tue Jul 03, 2012 6:54 am 
Offline

Joined: Mon Jun 18, 2012 10:31 am
Posts: 7
davedes wrote:
isokcevic's code was probably taken from an old tutorial which was wrong about Slick's game state usage.


It's based on spiegel's tutorials. When was this changed?


Top
 Profile  
 
PostPosted: Tue Jul 03, 2012 11:13 am 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1467
StateBasedGame has always worked this way, so it's a shame spiegel's tutorials have been giving misinformation for however long they've been up. I updated them in the wiki last week when I noticed the problem.

The slick tests (from the dev branch) are generally a better point of reference.


Top
 Profile  
 
PostPosted: Tue Jul 03, 2012 11:53 am 
Offline

Joined: Mon Jun 18, 2012 10:31 am
Posts: 7
Wow, thanks for the info and tutorial update, I'll definitely check it out ASAP :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group